I was reading the following article about creating 'on-demand' ajax calls to javascript functions' so that basically your scripts are only called when needed, which meand your pages load faster. However Im very confused about exactly how to implement this on my site. I have download the two main js from the wiki demo, util.js and ajaxcaller.js
but have no idea what to do with them! how do I tell them to 'do their stuff' with my scripts?
http://ajaxpatterns.org/On-Demand_Javascript#twoBirds_full_AJAX__-__everything_on_demand
I want to use this functioning because my pages are heavy on js and take too long to load, though most are included eg <script src="blabla.js"></script>
The two js above
util.js
var util = {
shouldDebug: false,
// Note: Will fail in pathological cases (where the members contain
// strings similar to describe() result).
membersEqual: function(array1, array2) {
return util.describe(array1)==util.describe(array2);
},
describe: function(obj) {
if (obj==null) { return null; }
switch(typeof(obj)) {
case 'object': {
var message = "";
for (key in obj) {
message += ", [" + key + "]: [" + obj[key] + "]";
}
if (message.length > 0) {
message = message.substring(2); // chomp initial ', '
}
return message;
}
default: return "" + obj;
}
},
debug: function(message) {
if (this.shouldDebug) {
alert("AjaxJS Message:\n\n" + message);
}
},
error: function(message) {
if (this.shouldDebug) {
alert("AjaxJS ERROR:\n\n" + message);
}
},
trim: function(str) {
return str.replace(/(^\s+|\s+$)/g,'');
},
strip: function(str) {
return str.replace(/\s+/, "");
}
}
function $() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string') {
if (document.getElementById) {
element = document.getElementById(element);
} else if (document.all) {
element = document.all[element];
}
}
elements.push(element);
}
if (arguments.length == 1 && elements.length > 0) {
return elements[0];
} else {
return elements;
}
}
function $C(elType) {
return document.createElement(elType);
}
// From prototype library. Try.these(f1, f2, f3);
var Try = {
these: function() {
var returnValue;
for (var i = 0; i<arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
}
function getElementsByClassName(classname) {
var a = [];
var re = new RegExp('\\b' + classname + '\\b');
var els = document.getElementsByTagName("*");
for(var i=0,j=els.length; i<j; i++)
if(re.test(els[i].className))a.push(els[i]);
return a;
}
function extractIFrameBody(iFrameEl) {
var doc = null;
if (iFrameEl.contentDocument) { // For NS6
doc = iFrameEl.contentDocument;
} else if (iFrameEl.contentWindow) { // For IE5.5 and IE6
doc = iFrameEl.contentWindow.document;
} else if (iFrameEl.document) { // For IE5
doc = iFrameEl.document;
} else {
alert("Error: could not find sumiFrame document");
return null;
}
return doc.body;
}
/* function getElementsByClassName(needle) {
var xpathResult = document.evaluate('//*[@class = needle]', document, null, 0, null);
var outArray = new Array();
while ((outArray[outArray.length] = xpathResult.iterateNext())) {
}
return outArray;
}
*/
/*
function acceptNode(node) {
if (node.hasAttribute("class")) {
var c = " " + node.className + " ";
if (c.indexOf(" " + needle + " ") != -1)
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_SKIP;
}
var treeWalker = document.createTreeWalker(document.documentElement,
NodeFilter.SHOW_ELEMENT,
acceptNode,
true);
var outArray = new Array();
if (treeWalker) {
var node = treeWalker.nextNode();
while (node) {
outArray.push(node);
node = treeWalker.nextNode();
}
}
return outArray;
}
*/
///////////////////////////////////////////////////////////////////////////////
// Used for pattern-specific demos.
///////////////////////////////////////////////////////////////////////////////
var DELAY = 1000;
var steps = 0;
function andThen(action) {
var delayTime = (++steps * DELAY);
setTimeout(action, delayTime);
}
function log(message) {
$("log").innerHTML += message + "<br/>";
}
function createXMLHttpRequest() {
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
try { return new XMLHttpRequest(); } catch(e) {}
alert("XMLHttpRequest not supported");
return null;
}
and ajaxcaller.js
var ajaxCaller = {
shouldDebug: false,
shouldEscapeVars: false,
shouldMakeHeaderMap: true,
calls : new Array(),
pendingResponseCount : 0,
/**************************************************************************
PUBLIC METHODS
*************************************************************************/
getXML: function(url, callbackFunction) {
this.get(url, null, callbackFunction, true, null);
},
getPlainText: function(url, callbackFunction) {
this.get(url, null, callbackFunction, false, null);
},
postForPlainText: function(url, vars, callbackFunction) {
this.postVars(url, vars, null, callbackFunction, false,
null, "POST", null, null, null);
},
postForXML: function(url, vars, callbackFunction) {
this.postVars(url, vars, null, callbackFunction, true,
null, "POST", null, null, null);
},
get: function(url, urlVars, callbackFunction, expectingXML, callingContext) {
this._callServer(url, urlVars, callbackFunction, expectingXML,
callingContext, "GET", null, null, null);
},
postVars:
function(url, bodyVars, optionalURLVars, callbackFunction, expectingXML,
callingContext) {
this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, "POST", bodyVars, null, null);
},
postBody:
function(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, bodyType, body) {
this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, "POST", null, bodyType, body);
},
putBody:
function(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, bodyType, body) {
this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, "PUT", null, bodyType, body);
},
options:
function(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, bodyType, body) {
this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, "OPTIONS", null, bodyType, body);
},
trace:
function(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, bodyType, body) {
this._debug("trace");
this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
callingContext, "TRACE", null, bodyType, body);
},
deleteIt: function(url, urlVars, callbackFunction,
expectingXML, callingContext) {
this._callServer(url, urlVars, callbackFunction, expectingXML,
callingContext, "DELETE", null, null, null);
},
head: function(url, urlVars, callbackFunction, expectingXML, callingContext)
{
this._callServer(url, urlVars, callbackFunction, expectingXML,
callingContext, "HEAD", null, null, null);
},
/**************************************************************************
PRIVATE METHODS
*************************************************************************/
_callServer: function(url, urlVars, callbackFunction, expectingXML,
callingContext, requestMethod, bodyVars,
explicitBodyType, explicitBody) {
if (urlVars==null) {
urlVars = new Array();
}
this._debug("_callServer() called. About to request URL\n"
+ "call key: [" + this.calls.length + "]\n"
+ "url: [" + url + "]\n"
+ "callback function: [" + callbackFunction + "]\n"
+ "treat response as xml?: [" + expectingXML + "]\n"
+ "Request method?: [" + requestMethod + "]\n"
+ "calling context: [" + callingContext + "]\n"
+ "explicit body type: [" + explicitBodyType + "]\n"
+ "explicit body: [" + explicitBody + "]\n"
+ "urlVars: [" + util.describe(urlVars) + "]\n"
+ "bodyVars: [" + util.describe(bodyVars) + "]"
);
var xReq = this._createXMLHttpRequest();
xReq.onreadystatechange = function() {
ajaxCaller._onResponseStateChange(call);
}
var call = {xReq: xReq,
callbackFunction: callbackFunction,
expectingXML: expectingXML,
callingContext: callingContext,
url: url};
if (urlVars!=null) {
var urlVarsString = this._createHTTPVarSpec(urlVars);
if (urlVarsString.length > 0) { // TODO check if appending with & instead
url += "?" + urlVarsString;
}
}
xReq.open(requestMethod, url, true);
if ( requestMethod=="GET"
|| requestMethod=="HEAD"
|| requestMethod=="DELETE") {
this._debug("Body-less request to URL " + url);
xReq.send(null);
return;
}
if ( requestMethod=="POST"
|| requestMethod=="PUT"
|| requestMethod=="OPTIONS"
|| requestMethod=="TRACE") {
bodyType = null;
body = null;
if (explicitBodyType==null) { // It's a form
bodyType = 'application/x-www-form-urlencoded; charset=UTF-8';
body = this._createHTTPVarSpec(bodyVars);
} else {
bodyType = explicitBodyType;
body = explicitBody;
}
this._debug("Content-Type: [" + bodyType + "]\nBody: [" + body + "].");
xReq.setRequestHeader('Content-Type', bodyType);
xReq.send(body);
return;
}
this._debug("ERROR: Unknown Request Method: " + requestMethod);
},
// The callback of xmlHttpRequest is a dynamically-generated function which
// immediately calls this function.
_onResponseStateChange: function(call) {
xReq = call.xReq;
if (xReq.readyState < 4) { //Still waiting
return;
}
if (xReq.readyState == 4) { //Transmit to actual callback
this._debug("Call " + util.describe(call)
+ " with context [" + call.callingContext+"]"
+ " to " + call.url + " has returned.");
callbackFunction = call.callbackFunction;
if (!callbackFunction) { // Maybe still loading, e.g. in another JS file
setTimeout(function() {
_onResponseStateChange(call);
}, 100);
}
var content = call.expectingXML ? xReq.responseXML : xReq.responseText;
responseHeaders = xReq.getAllResponseHeaders();
headersForCaller = this.shouldMakeHeaderMap ?
this._createHeaderMap(responseHeaders) : responseHeaders;
callbackFunction(content, headersForCaller, call.callingContext);
}
call = null; // Technically the responsibility of GC
this.pendingResponseCount--;
},
// Browser-agnostic factory function
_createXMLHttpRequest: function() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject('Microsoft.XMLHTTP')
} else {
_error("Could not create XMLHttpRequest on this browser");
return null;
}
},
_createHTTPVarSpec: function(vars) {
var varsString = "";
for( key in vars ) {
var value = vars[key];
if (this.shouldEscapeVars) {
escapePlusRE = new RegExp("\\\+");
value = value.replace(escapePlusRE, "%2B");
}
varsString += '&' + key + '=' + value;
}
if (varsString.length > 0) {
varsString = varsString.substring(1); // chomp initial '&'
}
this._debug("Built var String: " + varsString)
return varsString;
},
/* Creates associative array from header type to header */
_createHeaderMap: function(headersText) {
extractedHeaders = headersText.split("\n");
delete extractedHeaders[extractedHeaders.length]; // Del blank line at end
headerMap = new Array();
for (i=0; i<extractedHeaders.length-2; i++) {
head = extractedHeaders[i];
fieldNameEnding = head.indexOf(":");
field = head.substring(0, fieldNameEnding);
value = head.substring(fieldNameEnding + 2, head.length);
value = value.replace(/\s$/, "");
headerMap[field] = value;
}
return headerMap;
},
_debug: function(message) {
if (this.shouldDebug) {
alert("AjaxJS Message:\n\n" + message);
}
},
_error: function(message) {
if (this.shouldDebug) {
alert("AjaxJS ERROR:\n\n" + message);
}
}
};