// GLOBALS var mybic_failed_requests = 0; // a placeholder to count the number of failed requests to the server /** * Constructor for MyBIC's ajax object * This only needs to be instantiated once in your script and you'll be able to re-use the same object for all your requests *@param string The URL of the page you're going to connect to on the server, by default mybic_server.php *@param string The function that will be called when ajax responses come back from the server, by default mybic handles this for you */ function XMLHTTP(server_url, readyStateFunction) { this.version = '0.6.4'; this.server_url = server_url; // the SERVER page URL to connect to IE ajax_server.php this.async = true; // whether we're in syncronous mode or async (default) this.debug=0; // debug turned off by default, to see your request/response do ajaxObj.debug=1 this.throttle=1; // this enables throttling by default so all your requests are in the proper order this.method = "POST"; // by default all requests are sent via POST to override just use ajaxObj.method="GET"; before your call this.req = null; // the xmlhttprequest variable, starts off as null this.headers = new Array(); // array of optional headers you may pass in this.callBack = ''; // the callback function, when the ajax request is sent, this is the function that will be called this.format = "JSON"; // by default JSON encoding is the expected format, to override: ajaxObj.format = "XML"; or ajaxObj.format="TEXT"; this.net_down_func = this.down; // the function that will be called if mybic cannot make a request to the server (server down) this.abort_timeout = 5000; // the number of seconds to wait before calling network down function, set to -1 disable feature, defaults to 5 seconds this.failed_threshold = 3; // the number of failed requests before mybic is disabled -> prevents repeated error notifications this.ignoreCall = 0; // set this to 1 if you have a polling object and you don't want to see debug msgs every second or activity indicators this.readyStateFunction = (readyStateFunction) ? readyStateFunction : this.responseHandler; /*-- SYSTEM PROPERTIES - no need to change the properites below --*/ this.debugID = 0; // used for showing expandable visual debug data this.errors = new Array(); // array of errors generated this.queue = new Array(); // the queue that will handle the throttling requests to keep your stuff in sync this.queue_in_process = 0; // the current index for the throttling array this.currentCallIgnore=0; // system uses this to see what calls to ignore from the queue } /** * Method to create an XMLHTTP object *@access private */ XMLHTTP.prototype.getXMLHTTP = function() { // moz XMLHTTPRequest object if (window.XMLHttpRequest) { this.req = new XMLHttpRequest(); } // IE/Windows ActiveX version else if (window.ActiveXObject){ this.req = new ActiveXObject("Microsoft.XMLHTTP"); } else { if(this.debug == 1) { this.showDebug("
FATAL ERROR: Could not create XMLHTTPRequest Object!
"); } return false; } return this.req; } /** * Main API method to use for AJAX requests * example: ajaxObj.call("action=loadComments&id=1", myCallBackFunction); *@access public *@param string A url encoded string of data to send to the server *@param string A callback function that the server will launch when the response is generated *@param string Used by the response handler function to send back throttled requests, you won't need to worry about this param */ XMLHTTP.prototype.call = function(queryVars, userCallback, queue_request) { // test for too many failed requests if(mybic_failed_requests >= this.failed_threshold) { // call network down method with instruction to notify of mybic being disabled this.net_down_func('disable'); return false; } else { var currentVars; var callback; this.fullUrl = ''; if(this.throttle == 1 && queue_request != 'queue') { // throttling keeps your requests in sync, so things aren't out of order this.add2Queue(queryVars, userCallback); } if(this.queue_in_process == 0) { // get XMLHTTPRequest Object if(!this.getXMLHTTP()) { return false; } if(this.throttle == 1) { this.queue_in_process = 1; var currentCall = this.queue.shift(); // get the current call to make currentVars = currentCall.queryVars; callback = currentCall.userCallback; this.currentCallIgnore = currentCall.ignoreCall; } else { currentVars = queryVars; callback = userCallback; var ignoreCall=0; } this.callBack = callback; // set response handler, if none is set, use our default one this.req.onreadystatechange = this.readyStateFunction; // check for JSON encoding if(this.format != 'JSON') { currentVars = currentVars+'&json=false'; } // if get is used, append the query variables to the url string this.full_url = (this.method == "POST") ? this.server_url : this.server_url + '?'+ currentVars; if(this.debug == 1 && this.currentCallIgnore != 1) { try { var matches = currentVars.match(/action=(\w+)&?/); this.showDebug('new', 'MYBIC - CALLING: '+matches[1]); this.showDebug("Server Page: "+this.server_url+"
HTTP Method: "+this.method+"
Encoding Format: "+this.format+"
Query String: "+currentVars+"
"); }catch(e){} } // open connection this.req.open(this.method, this.full_url, this.async); /* // set any optional headers if(this.headers){ for(var i in this.headers) { if(i != '') { try { this.req.setRequestHeader( i, this.headers[i]); if(this.debug == 1) { this.showDebug('Setting Custom Header: '+this.headers[i]+'
');} } catch(e) {} } } } */ // START TIMER TO ABORT REQUEST if(this.abort_timeout != -1) { this.end_timer = setInterval('ajaxObj.endCall()', this.abort_timeout); } // send request if(this.method == 'POST') { this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); this.request = currentVars; this.req.send(currentVars); } else { this.req.send(null); } } } } /** * Default method for parsing the response from the server. It will try to eval the obj.method_to_call property and pass the native JS object */ XMLHTTP.prototype.responseHandler = function() { if(ajaxObj.req) { try { // only if req shows "complete" if (ajaxObj.req.readyState == 4) { // only if "OK" if (ajaxObj.req.status && ajaxObj.req.status == 200) { if(ajaxObj.req.responseText.indexOf('ajax_msg_failed') != -1) { ajaxObj.showDebug("Fatal Error: mybic_server sent back ajax_msg_failed! - MSG: "+ajaxObj.req.responseText+"
"); ajaxObj.callBack(false); } else { // clear out network down timer if(this.abort_timeout != -1) { clearInterval(ajaxObj.end_timer); } if(ajaxObj.format == "JSON") { try { var myObject = JSON.parse(ajaxObj.req.responseText); /* security login check */ // are there any error messages var variable = "myObject.errors"; var defined = eval('(typeof('+variable+') != "undefined");'); if (defined) { // check if there is a login error variable = "myObject.errors['error_num']"; defined = eval('(typeof('+variable+') != "undefined");'); if (defined) { if (myObject.errors['error_num']==0) { alert("For a security reason your session has timed out. \nYou will now be redirected to a login window. \n\n Thank you for your patience!"); window.location = myObject.errors['login_url']; return; } } } // callback function we passed to the server to process the results if(document.getElementById(ajaxObj.callBack)) { document.getElementById(ajaxObj.callBack).innerHTML = myObject; } else { ajaxObj.callBack(myObject); } } catch(e) { alert('an error occurred in your response function, not mybic related. Error Name: ' + e.name + ' Message:' + e.message); if(document.getElementById(ajaxObj.callBack)) { } else { ajaxObj.callBack(false); } } } else if(ajaxObj.format == "XML") { // send the raw xml data to the callback function ajaxObj.callBack(ajaxObj.req.responseXML); } else { if(document.getElementById(ajaxObj.callBack)) { document.getElementById(ajaxObj.callBack).innerHTML = ajaxObj.req.responseText; } else { ajaxObj.callBack(ajaxObj.req.responseText); } } } mybic_failed_requests = 0; // reset failed requests back to 0 } else { // server is came back with a bad status try{ ajaxObj.showDebug("Fatal Error: MSG: "+ajaxObj.req.responseText+" StatusText: "+ajaxObj.req.statusText+"
"); } catch(e){} ajaxObj.endCall(); } if(ajaxObj.debug == 1 && ajaxObj.currentCallIgnore != 1) { // STRIP HTML var str = ajaxObj.req.responseText.replace(/(\<)/gi, '<'); var str = str.replace(/(\>)/gi, '>'); ajaxObj.showDebug("HTTP Server Response:
"+str+"
"); } // reset the method, format, etc back to class defaults ajaxObj.restoreDefaults(); // reset our queue and call ajaxObj.queue_in_process = 0; if(ajaxObj.queue.length > 0) { ajaxObj.call('','','queue'); } } } catch(e) { /*network is down*/} } } /** * This method will allow you to lazy load javascript source files for on-demand javascript processing * Just pass in the url of the javascript file you wish to pull in and you're all set, its not ajaxified so you * can pull in scripts from any URL you want! *@param string The URL of the script you wish to load */ XMLHTTP.prototype.loadScript = function(url) { try{ // lets check to see if the script is already loaded, if so lets remove it and add a new one var scripts = document.getElementsByTagName('script'); s_len = scripts.length; for(var i=0;i");} } catch(e) { // server is completely down, call netdown function clearInterval(ajaxObj.end_timer); ajaxObj.net_down_func('disable'); } } /** * Default method that will be called when mybic experiences a network down situation, or is disabled * This method will pop up a div alerting the user of a general network error * You should define your own method to properly fit in with your page layout */ XMLHTTP.prototype.down = function(status) { var notif_div = '
'; notif_div += ' MSGHERE

'; if(status == 'disable') { var notif = 'A network issue has disabled network connections for this page. Please reload this page or contact the site administrator'; } else { var notif = 'A network issue has occurred which canceled your last request'; } // lets try and find an existing error message or use the current one in the DOM try{ if(document.getElementById('mybic_notification')) { document.getElementById('mybic_notification').style.display='block'; } else { var new_div = document.createElement('div'); new_div.innerHTML = notif_div; document.body.appendChild(new_div); } document.getElementById('mybic_notif_msg').innerHTML = notif; } catch(e) { alert('Network Unavailable: Please re-load page or contact the site administrator'); } } /** * This method will let developers view debug information on the screen from not only the system calls but also let them tap into it as well *@access public *@param string The Message you wish to push to debugging or pass in 'break' and the UI will break a new expandable column for you *@param string OPTIONAL: If you pass in break, also send in a string that will show what the break label should be *@param int OPTIONAL: If you pass in break, if you pass in a 1 to the function it will allow you have your section autoexpanded */ XMLHTTP.prototype.showDebug = function(msg, label, expand) { if(ajaxObj.debug == 1) { if(!document.getElementById('mybic_debug')) { var errs = document.createElement('div'); errs.id = 'mybic_errs'; var deb = document.createElement('div'); deb.id = 'mybic_debug'; deb.style.border = "thick solid black"; deb.style.backgroundColor = "#eeeeee"; deb.style.padding = "10px"; deb.style.margin = '75px 10px 10px 10px'; deb.style.width = '90%'; deb.innerHTML += 'MyBic Debugger: hide/show me!'; deb.innerHTML += '    Clear'; deb.innerHTML += '    Expand All'; deb.innerHTML += '    Contract All

'; deb.appendChild(errs); if(document.body) { document.body.appendChild(deb); } else { document.lastChild.appendChild(deb); } } var deb = document.getElementById('mybic_errs'); if(msg == 'new') { ajaxObj.debugID++; var dimg = '+'; deb.innerHTML += '
'+dimg+' label'+ajaxObj.debugID+': '+label+'
'; } else { deb.innerHTML +=''; } } } /** * This method is used by MyBic to visually show the debug data you've passed in *@private *@param object The image element that triggers the show/hide functionality */ XMLHTTP.prototype.debug_expand = function(el) { var deb = document.getElementById('mybic_errs'); var deb_len = deb.childNodes.length; if(el == 'none' || el == 'block') { var label = "mybic_debug"; var links = deb.getElementsByTagName('a'); var links_len = links.length; for(var q=0;q'; } } else { var label = el.parentNode.id; label = label.split('_'); label = "mybic_debug"+label[1]; } for(var i=0; i