Thursday, February 01, 2007

Managing include files in Javascript

As I continue to write Javascript libraries for use on various projects, I decided it was time to write a simple include() function so that I don't have to manually add superfluous <script></script> tags that I may or may not need on any given page.

Using the XMLHttpRequestObject, I was able to create an asynchronous request to fetch the source of my .js file. Then I create a new script object and set the .text or .innerHTML attribute of that object (depending on browser - IE requires .text) to the fetched source. So far I've tested it in IE 6 and FF 1.5.

Usage for including "/script/myscript.js":
Note: in reality, the include() call would be done from inside another .js file.

<head>
<script language="Javascript" src="ScriptManager.js" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
ScriptManager.script_base_link = '/script'; //set up our base link
//ScriptManager.script_file_extension = '.js'; //defaults to .js
ScriptManager.ErrorHandler.silent = false; //set to true or remove in production

try {
ScriptManager.include( 'myscript' );
}
catch (e) {
ScriptManager.ErrorHandler.handle_error( e );
}

</head>

And that's all.
The code for ScriptManager.js is below.
Copy & paste this into ScriptManager.js:


function ErrorHandler() {


}

ErrorHandler.handle_error = function ( e ) {

try {
ErrorHandler.show_error( e.message );
}
catch(e) {
}

}

ErrorHandler.show_error = function( message ) {

try {
if ( !ErrorHandler.silent ) {
alert( message );
}
}
catch(e) {
}

}

function HTTPRequest() {

//
// Properties
//
this.request_object = null;
this.async = true;
this.onreadystatechange = null;

//
// Methods
//
this.get_request_object = get_request_object;
this.send = send;
this.is_busy = is_busy;
this.abort = abort;
this.get_readyState = get_readyState;
this.get_status = get_status;
this.get_responseText = get_responseText;

function get_request_object() {

try {

if ( !this.request_object ) {

var http_request;

if ( typeof(XMLHttpRequest) != 'undefined' ) {
http_request = new XMLHttpRequest();
}
else {

try {
http_request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(inner_e) {

try {
http_request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(inner_e2) {
}
}
}

this.request_object = http_request;
}

return this.request_object;
}
catch(e) {
throw e;
}
}

function get_readyState() {

try {
if ( request_obj = this.get_request_object() ) {
return request_obj.readyState;
}

return null;
}
catch( e ) {
throw e;
}

}

function get_status() {

try {
if ( request_obj = this.get_request_object() ) {
return request_obj.status;
}

return null;
}
catch( e ) {
throw e;
}

}

function get_responseText() {

try {
if ( request_obj = this.get_request_object() ) {
return request_obj.responseText;
}

return null;
}
catch( e ) {
throw e;
}

}

function send( which_url ) {

try {
var http_request_obj;

if ( !(http_request_obj = this.get_request_object()) ) {
throw 'Your web browser does not support this function.';
}

if ( this.is_busy() ) {
this.abort();
}

if ( this.onreadystatechange ) {
http_request_obj.onreadystatechange = this.onreadystatechange;
}
http_request_obj.open("GET", which_url, this.async);
http_request_obj.send(null);

}
catch(e) {
throw e;
}


}

function is_busy() {

try {
if ( request_obj = this.get_request_object() ) {

switch ( request_obj.readyState ) {
case 1,2,3:
return true;
break;
default:
return 0;
break;
}
}

return 0;
}
catch(e) {
throw e;
}


}

function abort() {

try {
if ( this.request_object ) {
this.request_object.onreadystatechange = null;
this.request_object.abort();
}
}
catch(e) {
throw e;
}
}

}

HTTPRequest.READYSTATE_COMPLETED = 4;
HTTPRequest.STATUS_OK = 200;

////
//// ScriptManager
////
function ScriptManager() {

}

ScriptManager.include = function( file_name ) {

try {
var file_path;
var head;
var body;
var request = new HTTPRequest();
var script_obj;

script_obj = document.createElement('script');
script_obj.setAttribute('type', 'text/javascript');

if ( !ScriptManager.has_script_file_extension(file_name) ) {
file_name = file_name + ScriptManager.script_file_extension;
}

file_path = ScriptManager.script_base_link + '/' + file_name;

request.async = false;
request.send( file_path );

if ( typeof(script_obj.text) != 'undefined' ) {
script_obj.text = request.get_responseText();
}
else if ( typeof(script_obj.innerHTML) != 'undefined' ) {
script_obj.innerHTML = request.get_responseText();
}

if ( head = document.getElementsByTagName('head')[0] ) {
head.appendChild(script_obj);
}
else if ( body = document.getElementsByTagName('body')[0] ) {
body.appendChild(script_obj);
}
else {
throw 'ScriptManager::include requires a or tag';
}

}
catch ( e ) {
ScriptManager.ErrorHandler.handle_error(e);
}
}

ScriptManager.has_script_file_extension = function( file_name ) {

try {
var ext = ScriptManager.script_file_extension;

if ( ext ) {
if ( file_name.substring(file_name.length - ext.length, file_name.length) == ext ) {
return true;
}
}

return 0;
}
catch ( e ) {
throw e;
}

}

ScriptManager.script_base_link = '';
ScriptManager.script_file_extension = '.js';

ScriptManager.ErrorHandler = ErrorHandler;
ScriptManager.ErrorHandler.silent = true;




How to include files in javascript
javascript including files
javascript require file
javascript include()
javascript xmlhttprequest include
script object

3 comments:

best-tutor said...

Hello!

very nice post... enjoyed it very much.

Thank you

http://www.best-tutor.com
http://best-tutor.com"

good site

tutor
tutor

Wow Gold said...

WOW GOLD from randyrun. Most cheapest wow gold supplier.More than 10,000 online satisfied customers bears to the fact that we are genuine and fastest wowgold provider!

Bruce said...

Today,we are proud to announce the launch of the new wedding support service sell ffxi gil,packed with features sure to sell ffxi gils delight adventurers across Vana'diel looking to exchange eternal vows with their beloved!Responding to player demands for greater customization,the new service will grant brides and grooms freedom in choosing location,timing,dialogue,and sell Final Fantasy XI Gil more for their ceremony,allowing them to create a truly memorable event all their own.Information on all the features,including in-game sell ffxi gil item vendors and wedding certificates,can be found on the new wedding support site,so head on over sell ffxi gils and get started planning the wedding of your dreams sell Final Fantasy XIGil!