determining the location of a script on the server? Firefox bug won't let me

P

petermichaux

Hi,

I'm hoping for a reason I'm wrong or an alternate solution...

I'd like to be able to dynamically include some javascript files. This
is like scriptaculous.js library but their solution is broken in
Firefox 1.5.0.1 on OS X. What happens with the Scriptaculous library is
this

In the html document the author only has to include one line

<script type="text/javascript"
src="/javascripts/scriptaculous.js"></script>

but scriptaculous.js determines where scriptaculous.js was from and
then add other lines to the html doc to src other JavaScript files. By
the end of scriptaculous.js the html doc has something like

<script type="text/javascript"
src="/javascripts/scriptaculous.js"></script>
<script type="text/javascript" src="/javascripts/effects.js"></script>
<script type="text/javascript" src="/javascripts/dragdrop.js"></script>

(All the scripts are in the same server directory.)

This is a good idea in scriptaculous because it insures that the
JavaScript files are src'ed in the correct order. Also, if the
implementation of scriptaculous library changes then the html docs that
use it are not broken. This may lead to too much javascript being
src'ed by the html doc but I'm not worried about that right now.

The problem with the method of determining from what domain and which
directory scriptaculous.js came from in the first place cannot be used
twice in Firefox (ie for two separate libraries). I tried to play the
same trick but document.getElementsByTagName('script') will not let me
do it. I have tried to trim down the following example to show what I
want to do. It works in Safari. The divs backgrounds are green and red.
In Firefox only one has a background color. No errors or exceptions.
Firefox can never find the <script src="grof.js"> tag.

If you want to see the problem I found with Firefox more isolated
please see bugzilla
(https://bugzilla.mozilla.org/show_bug.cgi?id=331174). What I found was
the problem is that in firefox you cannot ask for the length of the
scriptTags variable below twice (grof.js, burp.js). Changing the
variable name (scriptTags) in only grof.js did not make a difference.

So what is another way to determine the location (url) of grof.js (and
burp.js) in the following example (or scriptaculous.js in that library)
so that I can dynamically src the other js files in the libraries
(grof2.js)? I don't want to hardcode any locations.

Thanks for reading this far and I hope someone has a suggestion.

Peter


------------------- test.html -------------------

<html>
<head>

<script type="text/javascript" src="grof.js"></script>

<script type="text/javascript" src="burp.js"></script>


</head>
<body>
<div id="grof">Grof</div>
<div id="burp">Burp</div>
</body>
</html>


------------------- grof.js -------------------

var scriptTags = document.getElementsByTagName("script");
for(var i=0;i<scriptTags.length;i++) {
if(scriptTags.src && scriptTags.src.match(/grof\.js(\?.*)?$/))
{
var path = scriptTags.src.replace(/grof\.js(\?.*)?$/,'');
document.write('<script type="text/javascript"
src="'+path+'grof2.js"></script>');
}
}

------------------- grof2.js -------------------
function g(){
var burp = document.getElementById("grof");
burp.style.background="green";
}

window.addEventListener("load", g, false);


------------------- burp.js -------------------

var scriptTags = document.getElementsByTagName("script");
for(var i=0;i<scriptTags.length;i++) {
if(scriptTags.src && scriptTags.src.match(/burp\.js(\?.*)?$/))
{
// Firefox will never get in here because the if condition will
never be true.
var path = scriptTags.src.replace(/burp\.js(\?.*)?$/,'');
document.write('<script type="text/javascript"
src="'+path+'burp2.js"></script>');
}
}

------------------- burp2.js -------------------

function b(){
var burp = document.getElementById("burp");
burp.style.background="red";
}

window.addEventListener("load", b, false);
 
C

Csaba Gabor

So what is another way to determine the location (url) of grof.js (and
burp.js) in the following example (or scriptaculous.js in that library)
so that I can dynamically src the other js files in the libraries
(grof2.js)? I don't want to hardcode any locations.

Thanks for reading this far and I hope someone has a suggestion.

I don't quite follow all of what your are thinking to do. In
particular, if you call on your first js file to be loaded, why can't
it presume that the rest haven't been loaded, given that you are
defining one "gateway" to access all the files. In other words, all
anybody is ever supposed to write is <script
src="firstJSfileToCall.js"> and that takes care of loading the rest,
which the HTML author is not supposed to care about.

But, if you argue some schizophrenia on the part of the file
identifications, you could test for the existence of a function or
variable you know to exist. For example, each script that you are
interested in could set itself (that is, its name) on
window.aIAmLoaded.

Also, you could assign an id to each script as well as an onload so
that is perhaps another way to get to the script element you are
looking for. For example, you could put in properties
id="currentScriptFileName" and
onload='bootstrapIterator("nextScriptFileName")', which function you'd
define in your first script file.

Could it be that the script loading has not settled? Perhaps you could
put in a
window.setTimeout(
function(){
var st = document.getElementsByTagName("script");
alert(st.length)},100);

Does it make a difference whether you use document.write or DOM methods
(document.createElement...)?

Good luck,
Csaba Gabor from Vienna
 
P

petermichaux

Hi Csaba,

Thanks for taking the time to read all of my problem. And thanks for
the ideas. I still think there is a fundamental problem left unsolved.
I've inserted comments below.

Peter
I don't quite follow all of what your are thinking to do. In
particular, if you call on your first js file to be loaded, why can't
it presume that the rest haven't been loaded, given that you are
defining one "gateway" to access all the files.

I could but there is a bigger plan behind my example. This may be
wasteful if the two gateway scripts are subsets of one big library.
This isn't my big problem now anyway.
In other words, all
anybody is ever supposed to write is <script
src="firstJSfileToCall.js"> and that takes care of loading the rest,
which the HTML author is not supposed to care about.

Yes, but where are the rest of the scripts? This is my big problem.
Determining the location of the other scripts. I have the library
installed in a top level directory ("/javascripts/") on my web app but
I give the library to someone else they may install the library further
down the directory tree. The gateway file for the library needs a way
to locate all of the rest of the scripts.
For example, you could put in properties
id="currentScriptFileName" and
onload='bootstrapIterator("nextScriptFileName")', which function you'd
define in your first script file.

I can't chain the files together in this case. But even if I could I
don't know the URL of the next script. I'm hoping I don't have to force
the library user into writing the whole URL in the initial script src
tag for their installation of the library. That would feel like
failure. There should be some workaround so the gateway script can
identify it's own URL and use this as a basis to determine the other
files' URLs.
Could it be that the script loading has not settled? Perhaps you could
put in a
window.setTimeout(
function(){
var st = document.getElementsByTagName("script");
alert(st.length)},100);

Does it make a difference whether you use document.write or DOM methods
(document.createElement...)?

scriptaculous.js says that document.createElement method doesn't work
in Safari. I haven't tried this yet but either way i still need to know
the locations of all the script files in the library.

Any other ideas about getting the script locations?

thanks again,
Peter
 
C

Csaba Gabor

Yes, but where are the rest of the scripts? This is my big problem.
Determining the location of the other scripts. I have the library
installed in a top level directory ("/javascripts/") on my web app but
I give the library to someone else they may install the library further
down the directory tree. The gateway file for the library needs a way
to locate all of the rest of the scripts.


I can't chain the files together in this case. But even if I could I
don't know the URL of the next script. I'm hoping I don't have to force

I think I'm missing something here. Who does know the URL (or more
rather, file name) of the next script(s). In other words, once the
first file in your library is loaded, either that file should know the
rest of the scripts involved, or it should know the next one only and
the next one is responsible for knowing the 3rd one's name and so on.
Or is there something else going on? I assumed it was the second of
the two possibilities I mentioned since you were mentioning that you
were ensured sequential loading. If this is off, please correct me.
Not that it really would have changed my responses, I think.
the library user into writing the whole URL in the initial script src
tag for their installation of the library. That would feel like

So let me paraphrase what I think I read. I imagined that you had a
library (of several javascript files full of lots of fun code). And
that this library winds up on other people's servers - that is to say
that the javascript files wind up on someone's server who is intending
to use the library. Only it could be in an arbitrary location relative
to the HTML documents they are serving up. So you want them to be able
to have a minimally long src="..." in order to specify the location of
the first javascript file in the library. And that javascript file is
responsible for loading all the rest. But to do that, it needs to know
where it itself is, so that it can write a complete src for the
remaining SCRIPTS that it writes out. And it intends to do this by
finding the src for its own SCRIPT tag (and also window.location.href).
failure. There should be some workaround so the gateway script can
identify it's own URL and use this as a basis to determine the other
files' URLs.


scriptaculous.js says that document.createElement method doesn't work
in Safari. I haven't tried this yet but either way i still need to know
the locations of all the script files in the library.

Any other ideas about getting the script locations?

So is it not the case, that you only ever need to fish out one script
tag, really, that first one that the user/developer must code because
that will allow subsequent scripts to determine the location of all the
remaining script files?

In this case, won't placing an id=... allow that script element to be
recovered? I still think this is the one that bears most careful
examination.
<script type='text/javascript' id='PetersFunkyLibrary'
onLoad="alert(document.getElementById('PetersFunkyLibrary').id)"
src="..."></script>

Up to some months (a year?) ago, it was the case that in FF the SCRIPT
elements sat in the HEAD element off the HTML element
(=document.documentElement). But that is evidently no longer the case,
as I am now finding the SCRIPT elements under document.body, and not
necessarily directly under (if you wrap the SCRIPT in a DIV). It seems
to me that they were happy where they used to live and I don't see the
reason for their eviction. Nevertheless, perhaps directly walking all
the elements of document.body.childNodes and checking for
..nodeName=="SCRIPT" might have a shot at finding all the script
elements in the problem browser (though I don't give it good chances if
document.body.getElementsByTagName('SCRIPT') is failing).

Csaba
 
P

petermichaux

Casab,
So you want them to be able
to have a minimally long src="..." in order to specify the location of
the first javascript file in the library. And that javascript file is
responsible for loading all the rest. But to do that, it needs to know
where it itself is, so that it can write a complete src for the
remaining SCRIPTS that it writes out. And it intends to do this by
finding the src for its own SCRIPT tag (and also window.location.href).

Yes, exactly.
So is it not the case, that you only ever need to fish out one script
tag, really, that first one that the user/developer must code because
that will allow subsequent scripts to determine the location of all the
remaining script files?

Yes that is true. If two libraries are included then I need to do this
once for each library. That is where the scriptaculous idea fails in
firefox. Once the trick is used once then it can't be used again due to
a bug. It might be breaking other things too.

In this case, won't placing an id=... allow that script element to be
recovered? I still think this is the one that bears most careful
examination.
<script type='text/javascript' id='PetersFunkyLibrary'
onLoad="alert(document.getElementById('PetersFunkyLibrary').id)"
src="..."></script>

I was hoping to avoid adding anything on the part of the library user
but maybe it is necessary for now. If I can't find a cross browser
solution then I will try this.

Up to some months (a year?) ago, it was the case that in FF the SCRIPT
elements sat in the HEAD element off the HTML element
(=document.documentElement). But that is evidently no longer the case,
as I am now finding the SCRIPT elements under document.body, and not
necessarily directly under (if you wrap the SCRIPT in a DIV). It seems
to me that they were happy where they used to live and I don't see the
reason for their eviction. Nevertheless, perhaps directly walking all
the elements of document.body.childNodes and checking for
.nodeName=="SCRIPT" might have a shot at finding all the script
elements in the problem browser (though I don't give it good chances if
document.body.getElementsByTagName('SCRIPT') is failing).

I didn't know that there were such problems with the SCRIPT elements in
Firefox. Thanks for this suggestion. I tried direct walking
document.childNodes and it worked in Firefox!!! Now I don't even have
to check for script tags. I just look for any tag with a src with a
regular string match. This is great! Now I have to try on IE. Nail
biting time.

Below is my new burp.js which needs some clean up (and the old one for
reference).

Many thanks! I really appreciate your patients in helping me.

:D

Peter


------------------------------ new burp.js
-------------------------------------

function check_is_script(element){
if(element.src && element.src.match(/burp\.js(\?.*)?$/)){
return element;
}

var children = element.childNodes;
for(var i=0;i<children.length;i++) {
var found = check_is_script(children);
if (found != null) {
return found;
}
}

return null;
}

var asdf = check_is_script(document);
if(asdf != null) {
var path = asdf.src.replace(/burp\.js(\?.*)?$/,'');
document.write('<script type="text/javascript"
src="'+path+'burp2.js"></script>');
}


------------------------------ old burp.js
-------------------------------------

var scriptTags = document.getElementsByTagName("script");
for(var i=0;i<scriptTags.length;i++) {
if(scriptTags.src && scriptTags.src.match(/burp\.js(\?.*)?$/))
{
var path = scriptTags.src.replace(/burp\.js(\?.*)?$/,'');
document.write('<script type="text/javascript"
src="'+path+'burp2.js"></script>');
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top