I have no idea if this possible solution to making getScript work across all browsers (including Safari) has already been mentioned, but I thought I'd provide it in case anyone was looking for a way. I've seen uses of timeouts and such to try to figure out when a script has been loaded, but ultimately I think this solution is better. It gets javascript (and css) by means of AJAX, then dynamically creates style and script tags and appends the text content of the ajax response. Of course a few browser specific fixes are incorporated, but that's the gist of it. I made this plugin for personal use a couple months ago, and I guess I should have probably shared it back then, but I hope better late than never.
An example use of this plugin would be: $("#load").click(function(){ $.include("jqModal.css,jqModal.js,jqDnR-R.js", {onload: function(){ $('<div class="jqmWindow"><div><h3 style="cursor:move">Success!</ h3><hr /><p>If you\'re reading this message then the test was successful...</p><p>You should be able to drag this box by its title.</ p><input type="button" value="Close" class="jqmClose" /></div></ div>').appendTo("body").jqm().jqDrag('h3').jqmShow().jqmAddClose('.jqmClose'); }}); }); This uses $.include to dynamically load each listed file one after the other. It might be beneficial because it doesn't load the script for making jqModal work until it's needed. This might not be the best example, but it shows what it can do. /* * jQuery.include - A dynamic javascript/css loader plugin for jQuery. * * Copyright (c) 2007 Dave Stewart <[EMAIL PROTECTED]>, http://www.yesterdave.com * Licensed under the MIT License: * http://www.opensource.org/licenses/mit-license.php * * $Version: 2007.04.27 +r3 * * hard time figuring out a way to ensure js/css is loaded before proceeding with the next file * - use ajax to get js/css file then inject it in a new script/ style tag * * hard time trying to figure out why safari wouldn't work with either: * - script.onload * - script.text * finally found http://tobielangel.com/2007/2/23/to-eval-or-not-to-eval * - append javscript text to script tag with document.createTextNode * * keep in mind that no two external files should have the same name, becase path is disregarded * * Options: * - sync: determines whether or not the files are load synchronously (Default: true) * - onload: the function to run after all the files are loaded (Default: null) * - jsBase: the base directory where javascript files are found (Default: '') * - cssBase: the base directory where css files are found (Default: '') * */ (function($){ var list = {}; var queue = []; var running = false; var add = function(file, o){ o = $.extend({sync: true, onload: null, jsBase: '', cssBase: ''}, o || {}); fillList(); var files = file.split(','); var len = files.length; $.each(files, function(i, file){ file = (file.indexOf('.css') > -1 ? o.cssBase : o.jsBase) + file; var cb = (i == len - 1) ? o.onload : null; if (!o.sync) insert(file, cb || function(){}, false); else queue.push({file: file, onload: cb}); }); if (!running) next(); }; var next = function(){ if (queue.length > 0) { running = true; var item = queue.shift(); var cb = function(){ if (item.onload) item.onload(); next(); }; insert(item.file, cb, true); } else running = false; }; var insert = function(file, cb, sync){ if (!list[file]) { list[file] = true; if (file.indexOf('.css') > -1) createCSS(file, cb, sync); else createJS(file, cb, sync); } else cb(); }; var createJS = function(file, cb, sync){ if (!sync) { $(document.createElement('script')).attr({type: 'text/ javascript', src: file}).appendTo('head'); cb(); } else { $.get(file, null, function(jsText){ var s = $ (document.createElement('script')).attr('type', 'text/javascript'); if ($.browser.safari) s.append(document.createTextNode(jsText)); else s[0].text = jsText; s.appendTo('head'); cb(); }); } } var createCSS = function(file, cb, sync){ if (!sync) { $(document.createElement('link')).attr({type: 'text/css', rel: 'stylesheet', href: file}).appendTo('head'); cb(); } else { $.get(file, null, function(cssText){ if ($.browser.msie) { var s = document.createStyleSheet(); s.cssText = cssText; } else { var s = $ (document.createElement('style')).attr('type', 'text/css'); try { s.append(document.createTextNode(cssText)); } catch (e) { s[0].cssText = cssText; } s.appendTo('head'); } cb(); }); } }; var fillList = function(){ var toAdd = []; $("script").each(function(){ toAdd.push(this.src); }); $("link").each(function(){ toAdd.push(this.href); }); $.each(toAdd, function(i, file){ if (file && file.length > 0 && file != '//:') list[stripPath(file)] = true; }); }; var stripPath = function(href){ return href.substring(href.lastIndexOf('/') + 1); }; $.extend({ include: add, externalResources: list }); $(fillList); })(jQuery);