09.26.2005 - Safari & createElement("script")
I was browsing through Safari's bugzilla and found this extremely exciting bit of information:
"Here's a very simple workaround. Set the onload and src attributes of the script *before* inserting it into the document:"
That's right - we can now get Safari to source scripts created with createElement! I have verified this to work in Safari 2.0.1 with MODIv2 and the original MODI.
The favelets themselves dont work terribly well (yet -- which is why I haven't updated the links), but that's beside the point. This is wonderful news - and not just for favelets either. This is gonna be a great boon for web development as a whole.
Just think - no longer do you have to trudge in a slew of scripts that you might not even need -- now you can dynamically pull in scripts when the functionality they provide is requested without having to worry about Safari!. Oh, happy day.
For those interested, the actual change for MODIv1 is as follows:
The Old Way:
The New Way:
javascript:void(z=document.body.appendChild(document.createElement('script')));
void(z.language='javascript');
void(z.type='text/javascript');
void(z.src='http://slayeroffice.com/tools/modi/modi.js');void(z.id='modi');
javascript:void(z=document.createElement('script'));
void(z.language='javascript');
void(z.type='text/javascript');
void(z.src='http://slayeroffice.com/tools/modi/modi.js');
void(z.id='modi');
void(document.getElementsByTagName('head')[0].appendChild(z));
Time permitting, a progression of updates will start coming out for the favelets over the coming weeks.
Just one trick I thought I'd suggest -- I picked this up myself recently. For favelets, try instantiating and running a new anonymous function like this:
javascript:(function(){ var abc = 123; foobar(abc); whatever(); })();
That removes the need for ensuring that the last statement is void and also allows you to use "var" with impunity, as it's locally scoped.
Posted by Angus Turnbull on September 26, 2005 @ 8:14 pm
Posted by Stephen Clay on September 26, 2005 @ 8:50 pm
@Stephen: Nah, its not. Just one of those legacy things from years ago that proliferated through my lazy copy/pasting :)
Posted by Steve on September 26, 2005 @ 11:52 pm
Posted by Martin on October 12, 2005 @ 6:14 pm
Posted by Jo on October 16, 2005 @ 6:28 am
I was gonna get to work figuring out why my script wasn't working in Safari tomorrow, so you've saved me some time. :) Thanks alot. :D I'm terrible at bugtesting on Mac's, just can't comprehend em, you know.
Posted by Jonas Pihlström on November 10, 2005 @ 4:39 pm
For example, i try load this http://app.feeddigest.com/digest3/YCJVBTOK96.js , on IE, Opera works fine, but Firefox open a new window.
Best regards
Mario
Posted by Mario Brhemenz on November 16, 2005 @ 6:46 pm
index.html
----- cut here ----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Hello World from External Javascript</title>
<script type="text/javascript">
var
oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = 'test.js';
oScript.onload = oScript.onreadystatechange = scriptLoaded;
document.getElementsByTagName('head')[0].appendChild(oScript);
function scriptLoaded() {
helloWorld();
}
</script>
</head>
<body>
<h1>Hello World Example</h1>
Did we get "Hello world" alert?
</body>
</html>
----- cut here ----
test.js
----- cut here ----
function helloWorld() {
alert("Hello World!");
}
----- cut here ----
Posted by Boris on November 17, 2005 @ 6:39 am
Take the "new way" code snippet in the example and use that. I cant see why you would need to fire a method from the onload event of a script object anyway (i half suspect thats the issue as a few quick experiments shows Safari to not fire that event) - just call your init method inline from the bottom of the script if you need a function executed onload.
Go here: http://slayeroffice.com/tools/js_eval
And paste this in:
x = document.createElement("script");
x.type = "text/javascript";
x.src = "http://slayeroffice.com/scripts/page_methods_v4.js";
x.onload = function() { alert("woot!"); }
document.getElementsByTagName("head")[0].appendChild(x);
j = setOldTitles;
Firefox will alert, but Safari won't. Both source the script and write out the function from page_methods_v4.js - so, it works.
Posted by Steve on November 17, 2005 @ 8:34 am
And no, you can't call it manually ("inline" as you say) at the bottom of the script, because loading of the external script is asynchronous operation. If, in my example, I would add
helloWorld();
after
document.getElementsByTagName('head')[0].appendChild(oScript);
helloWorld function would not be called because it is still not existing (error would be reported in Javascript console)
Cheers!
Posted by Boris on November 18, 2005 @ 6:39 am
Have a look at any of the source of any of them that have an init() method and it'll be called as the last line in the script. No need to attach it to an event.
Posted by Steve on November 18, 2005 @ 9:11 am
Nice tool this MODI bookmarklet, great idea, fine job!
Regards...
Posted by Boris on November 18, 2005 @ 11:41 am
Posted by Boris on November 21, 2005 @ 5:05 am
javascript:
(function(){
with(j=(d=document).createElement(s='script')){
type='text/'+(language='java'+s);
src='http://slayeroffice.com/tools/modi/modi.js';
}
d.body.appendChild(j);
})()
:ca_redwards.
Posted by ca_redwards on November 23, 2005 @ 5:50 pm
Comments have been closed for this post.