Reputation: 42267
How might one go about obtaining a reference to the DOM script tag that called a function?
For example:
<script type="text/javascript">
var globalfunc = function(){
//obtain a reference to the script block that globalfunc() was called from
}
</script>
<script type="text/javascript">
globalfunc();
</script>
I know that I could assign an id or class to the script element and pass that through to my function to do a DOM lookup, but I think it would be more flexible and elegant to do it without such a thing. The main reason is that I may have to do some work on our site to get 3rd party ads wrangled into shape, and we don't have control over the scripts they use to load their ads.
Upvotes: 3
Views: 2780
Reputation: 35850
Here's my solution: It will work in every browser except IE, it requires that you catch a real error (well it doesn't for Firefox, but other browsers do), and you must call it from an external script (<script src="...">
) to use it.
var getErrorScriptNode = (function () {
var getErrorSource = function (error) {
var loc, replacer = function (stack, matchedLoc) {
loc = matchedLoc;
};
if ("fileName" in error) {
loc = error.fileName;
} else if ("stacktrace" in error) { // Opera
error.stacktrace.replace(/Line \d+ of .+ script (.*)/gm, replacer);
} else if ("stack" in error) { // WebKit
error.stack.replace(/at (.*)/gm, replacer);
loc = loc.replace(/:\d+:\d+$/, "");
}
return loc;
},
anchor = document.createElement("a");
return function (error) {
anchor.href = getErrorSource(error);
var src = anchor.href,
scripts = document.getElementsByTagName("script");
anchor.removeAttribute("href");
for (var i = 0, l = scripts.length; i < l; i++) {
anchor.href = scripts.item(i).src;
if (anchor.href === src) {
anchor.removeAttribute("href");
return scripts.item(i);
}
}
};
}());
var globalfunc = function (err) {
var scriptNode = getErrorScriptNode(err);
// ...
};
In an external (must be EXTERNAL) script that calls globalfunc()
:
try {
0();
} catch (e) {
var err = e;
}
// do stuff...
globalfunc(err);
Upvotes: 1
Reputation: 356
Assuming the script tag is not deferred, when the function executes, it should be from the last script tag in the page. So something like
var scripts = document.getElementsByTagName("script");
var scriptElement = scripts[scripts.length-1];
should get the reference.
You should wrap the original function in your own construct to insert this code, something like:
var old_global = globalFunction;
globalFunction = function () {
var scripts = document.getElementsByTagName("script");
var scriptElement = scripts[scripts.length-1];
old_global.call(this,arguments);
// do something after
};
This code is untested but may give you the idea.
Upvotes: 2
Reputation: 31300
Actually, you can't assign a class or id to a script
element if you want to have valid markup. That said, I have used that method and yes it does work.
Alternatively, and let the record show that I would never do this, you could do something like:
var scripts = document.getElementsByTagName("script");
for (var i=0, l=scripts.length; i<l; ++i ) {
if ( scripts[i].innerHTML.indexOf("globalfunc();") != -1 ) {
// Found a script tag in which `globalfunc();` is executed
}
}
Upvotes: 1