Skip to content

Commit 424f652

Browse files
committed
added initial check in for jQuery Late loader (still lacking remote CSS validation for non IE browsers)
1 parent 3d60902 commit 424f652

File tree

4 files changed

+337
-0
lines changed

4 files changed

+337
-0
lines changed

jQuery.LateLoader.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
; (function($) {
2+
$.LateLoader = {
3+
LoadScriptOrCSS: _LoadScriptOrCSS,
4+
/*
5+
Loads a javascript/css from the passed url if it wasn't previously loaded
6+
7+
The parameter can either be a string with the wanted url( then the default
8+
params are used (See Defaults for more details)), or an option object
9+
URL -> relative or absolute URL to your javascript/css
10+
*/
11+
IsScriptOrCSSLoaded: _IsScriptOrCSSLoaded,
12+
/*
13+
Returns true|false if a javascript/css is already loaded (via LoadScriptOrCSS)
14+
15+
Parameters :
16+
URL-> relative or absolute URL to your javascript/css
17+
Type->'js' or 'css' (defaults to 'js')
18+
*/
19+
GetLoadedScriptOrCSSs: _GetScriptOrCSSArray,
20+
/*
21+
Returns an array of all loaded scripts (object with 2 arrays, css and js)
22+
*/
23+
GetLoadedScriptOrCSSsByType: _GetScriptOrCSSArrayByType,
24+
/*
25+
Returns an array of all loaded scripts/css according to the passed type
26+
27+
Parameter :
28+
Type->'js' or 'css'
29+
*/
30+
PluginDefaults:
31+
{
32+
ArrayDataKey: "LateLoaderDataKey", //Unique key used to identify the jQuery Data collection
33+
ElementToAttachDataTo: "body", //DOM object that hosts the jQuery Data collection
34+
RemoteTimeout: 1500 //MS of timeout to wait for a remote script..
35+
},
36+
Defaults:
37+
{
38+
URL: null, //Will be filled in by LoadScriptOrCSS's parameter
39+
Type: 'js', // 'js' or 'css' (defaults to 'js')
40+
LoadedCallBackFunction: null, // Called when the javascript/css is loaded (default is null)
41+
ErrorCallBackFunction: null// Called when an error occurs (default is null)
42+
}
43+
44+
};
45+
46+
//Public method implementation
47+
function _LoadScriptOrCSS(OptionsOrURL) {
48+
var options;
49+
if (typeof (OptionsOrURL) == 'string') {
50+
options = $.extend({}, $.LateLoader.Defaults, { URL: OptionsOrURL });
51+
} else {
52+
options = $.extend({}, $.LateLoader.Defaults, OptionsOrURL);
53+
}
54+
if (_IsScriptOrCSSLoaded(options.URL, options.Type)) {
55+
_CallFunctionIfAvailable(options.LoadedCallBackFunction, options.URL);
56+
return;
57+
}
58+
59+
if (options.Type == 'js') {
60+
if (_URLIsRemote(options.URL)) {
61+
//The error will not be thrown, we'll have to check this according to a certain timeout..
62+
setTimeout(function() {
63+
if (!_IsScriptOrCSSLoaded(options.URL, options.Type))
64+
_Error(options);
65+
}, $.LateLoader.PluginDefaults.RemoteTimeout);
66+
}
67+
$.ajax({
68+
dataType: 'script',
69+
url: options.URL,
70+
success: function() {
71+
_Success(options);
72+
},
73+
error: function() {
74+
_Error(options);
75+
},
76+
data: {}
77+
});
78+
}
79+
else {
80+
_AddCSSFile(options);
81+
}
82+
}
83+
84+
function _IsScriptOrCSSLoaded(URL, Type) {
85+
var ScriptOrCSSArray = _GetScriptOrCSSArray() || {};
86+
return (ScriptOrCSSArray[Type] && ($.inArray(URL, ScriptOrCSSArray[Type]) != -1)) ? true : false;
87+
}
88+
89+
function _GetScriptOrCSSArray() {
90+
var ScriptOrCSSData = $($.LateLoader.PluginDefaults.ElementToAttachDataTo).data($.LateLoader.PluginDefaults.ArrayDataKey);
91+
var ScriptOrCSSArray = ScriptOrCSSData && ScriptOrCSSData['ScriptOrCSSs'] ? ScriptOrCSSData.ScriptOrCSSs : false;
92+
if (!ScriptOrCSSArray)
93+
return false;
94+
else
95+
return ScriptOrCSSArray;
96+
}
97+
98+
function _GetScriptOrCSSArrayByType(Type) {
99+
var ScriptOrCSSArray = _GetScriptOrCSSArray() || false;
100+
if (!ScriptOrCSSArray)
101+
return false;
102+
if (!ScriptOrCSSArray[Type])
103+
return false;
104+
return ScriptOrCSSArray[Type];
105+
}
106+
107+
//Private helpers
108+
function _Error(options) {
109+
_CallFunctionIfAvailable(options.ErrorCallBackFunction, 'error loading ' + options.Type + ' - ' + options.URL);
110+
}
111+
function _Success(options) {
112+
_AddLoadedScriptOrCSSToArray(options);
113+
_CallFunctionIfAvailable(options.LoadedCallBackFunction, options.URL);
114+
}
115+
116+
function _ValidateCSSFileLoaded(options) {
117+
var $createdLink = $("link[href='" + options.URL + "']");
118+
119+
var success = true;
120+
121+
if (!$createdLink.length) {
122+
success = false;
123+
}
124+
if ($.browser.msie) {
125+
success = $createdLink.get(0).readyState == "complete";
126+
} else {
127+
if (false /*Need to find a non IE solution to validate if the external stylesheet has loaded*/) {
128+
success = false;
129+
}
130+
}
131+
132+
if (success) {
133+
_Success(options);
134+
}
135+
else {
136+
_Error(options);
137+
}
138+
}
139+
140+
function _AddCSSFile(options) {
141+
if (!_URLIsRemote(options.URL)) {
142+
$.ajax({
143+
url: options.URL,
144+
dataType: "text",
145+
success: function(data) {
146+
var randID = Math.round(Math.random() * 321312);
147+
var $link = $("<style />")
148+
.attr({ "rel": "stylesheet", "type": "text/css", "id": randID.toString() });
149+
$link.appendTo("head");
150+
setTimeout(function() {
151+
var created = $("#" + randID.toString());
152+
if ($.browser.msie)
153+
created.get(0).styleSheet.cssText = data;
154+
else
155+
created.text(data);
156+
_Success(options);
157+
}, 15);
158+
},
159+
error: function() { _Error(options); },
160+
data: {}
161+
});
162+
}
163+
else {
164+
$("<link />")
165+
.ready(function() { setTimeout(function() { _ValidateCSSFileLoaded(options); }, 15); })
166+
.attr({ "rel": "stylesheet", "type": "text/css", "href": options.URL })
167+
.appendTo("head");
168+
}
169+
}
170+
171+
function _AddLoadedScriptOrCSSToArray(options) {
172+
var ScriptOrCSSArray = _GetScriptOrCSSArray() || {};
173+
if (!ScriptOrCSSArray[options.Type])
174+
ScriptOrCSSArray[options.Type] = new Array();
175+
ScriptOrCSSArray[options.Type].push(options.URL);
176+
$($.LateLoader.PluginDefaults.ElementToAttachDataTo).data($.LateLoader.PluginDefaults.ArrayDataKey, { ScriptOrCSSs: ScriptOrCSSArray });
177+
}
178+
function _CallFunctionIfAvailable(method, param) {
179+
if (method && $.isFunction(method))
180+
method(param);
181+
}
182+
183+
function _URLIsRemote(url) {
184+
return url.indexOf("http") > -1 &&
185+
(url.indexOf("http://" + window.location.host) == -1 && url.indexOf("https://" + window.location.host) == -1);
186+
}
187+
188+
})(jQuery);

test.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.Fuchsia
2+
{
3+
background-color: Fuchsia !important;
4+
}
5+
6+
hr
7+
{
8+
color: #f00;
9+
background-color: #f00;
10+
height: 5px;
11+
}

test.html

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<html>
2+
<head>
3+
<title>jQuery Late Loader Tester</title>
4+
5+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
6+
7+
<script type="text/javascript" src="jQueryLateLoader.js"></script>
8+
9+
<script type="text/javascript">
10+
function LogToConsole(toLog) {
11+
$console = $("#console");
12+
$console.val($("#console").val() + "\n" + toLog)
13+
$console.get(0).scrollTop = $console.get(0).scrollHeight;
14+
return;
15+
}
16+
17+
$(document).ready(function() {
18+
$("#testButton").click(function() {
19+
$.LateLoader.LoadScriptOrCSS({
20+
URL: $("#url").val(),
21+
Type: $("#type").val(),
22+
LoadedCallBackFunction: function(url) {
23+
LogToConsole('Loaded - ' + url);
24+
},
25+
ErrorCallBackFunction: function(data) { LogToConsole('error loading ' + data); }
26+
});
27+
});
28+
$("#hasButton").click(function() {
29+
LogToConsole($.LateLoader.IsScriptOrCSSLoaded($("#url").val(), $("#type").val()));
30+
});
31+
$("#data").click(function() {
32+
var scripts = $.LateLoader.GetLoadedScriptOrCSSs();
33+
for (var script in scripts['js'])
34+
LogToConsole('Script -> ' + scripts['js'][script]);
35+
for (var css in scripts['css'])
36+
LogToConsole('StyleSheet -> ' + scripts['css'][css]);
37+
});
38+
$("#TestLocalJS").click(function() {
39+
$.LateLoader.LoadScriptOrCSS({
40+
URL: 'test.js',
41+
LoadedCallBackFunction: function() {
42+
LogToConsole('Local Script Loaded...');
43+
}
44+
});
45+
});
46+
$("#testUI").click(function() {
47+
$.LateLoader.LoadScriptOrCSS({
48+
URL: 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js',
49+
LoadedCallBackFunction: function() {
50+
$("<div title='jQuery Late Loader Tester'>This dialog was loaded dynamically!</div>").dialog();
51+
LogToConsole("jQuery UI Javascript loaded");
52+
}
53+
});
54+
});
55+
$("#testUICSS").click(function() {
56+
$.LateLoader.LoadScriptOrCSS({
57+
URL: 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/redmond/jquery-ui.css',
58+
Type: 'css', LoadedCallBackFunction: function() {
59+
LogToConsole('jQuery UI CSS theme loaded (Redmond). Try the jQuery UI Javascript button now!');
60+
}
61+
});
62+
});
63+
$("#testLocalCSS").click(function() {
64+
$.LateLoader.LoadScriptOrCSS({
65+
URL: 'test.css',
66+
Type: 'css',
67+
LoadedCallBackFunction: function() {
68+
LogToConsole('Local CSS Loaded.. Check out the background color!');
69+
}
70+
});
71+
});
72+
$("#TestErrorLocalJS").click(function() {
73+
$.LateLoader.LoadScriptOrCSS({
74+
URL: 'jquery-ui.min.js',
75+
LoadedCallBackFunction: function() {
76+
LogToConsole("You shouldn't get here! This is the success method!");
77+
},
78+
ErrorCallBackFunction: function(data) { LogToConsole('error loading ' + data); }
79+
});
80+
});
81+
$("#TestErrorRemoteJS").click(function() {
82+
$.LateLoader.LoadScriptOrCSS({
83+
URL: 'http://ajax.googleapis.com/ajax/libs/jqujquery-ui.min.js',
84+
LoadedCallBackFunction: function() {
85+
LogToConsole("You shouldn't get here! This is the success method!");
86+
},
87+
ErrorCallBackFunction: function(data) { LogToConsole('error loading ' + data); }
88+
});
89+
});
90+
$("#TestErrorRemoteCSS").click(function() {
91+
$.LateLoader.LoadScriptOrCSS({
92+
URL: 'http://ajax.googleapis.com/themes/redmond/jquery-ui.css',
93+
Type: 'css',
94+
LoadedCallBackFunction: function() {
95+
LogToConsole("You shouldn't get here! This is the success method!");
96+
},
97+
ErrorCallBackFunction: function(data) { LogToConsole('error loading ' + data); }
98+
});
99+
});
100+
$("#TestErrorLocalCSS").click(function() {
101+
$.LateLoader.LoadScriptOrCSS({
102+
URL: 'test1.css',
103+
Type: 'css',
104+
LoadedCallBackFunction: function() {
105+
LogToConsole("You shouldn't get here! This is the success method!");
106+
},
107+
ErrorCallBackFunction: function(data) { LogToConsole('error loading ' + data); }
108+
});
109+
});
110+
});
111+
</script>
112+
113+
</head>
114+
<body class="Fuchsia">
115+
<label>
116+
URL<input type="text" value="" id="url" name="url" /></label>
117+
<label>
118+
Type<select id="type" name="type">
119+
<option value="js" selected="selected">Javascript</option>
120+
<option value="css">Style Sheet</option>
121+
</select></label>
122+
<hr />
123+
<input type="button" value="Load" id="testButton" />
124+
<input type="button" value="Existing?" id="hasButton" />
125+
<input type="button" value="Get Loaded Data" id="data" />
126+
<input type="button" value="jQuery UI Javascript" id="testUI" />
127+
<input type="button" value="Local JavaScript" id="TestLocalJS" />
128+
<input type="button" value="jQuery UI CSS" id="testUICSS" class="ui-state-highlight" />
129+
<input type="button" value="Local CSS" id="testLocalCSS" />
130+
<input type="button" value="Error from Local Javascript" id="TestErrorLocalJS" />
131+
<input type="button" value="Error from Remote Javascript" id="TestErrorRemoteJS" />
132+
<input type="button" value="Error from Remote CSS" id="TestErrorRemoteCSS" />
133+
<input type="button" value="Error From Local CSS" id="TestErrorLocalCSS" />
134+
<hr />
135+
<textarea id="console" style="width: 100%; height: 300px; overflow: auto;"></textarea>
136+
</body>
137+
</html>

test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
alert("I'm an alert that was loaded dynamically from the file test.js");

0 commit comments

Comments
 (0)