[thelist] Javascript Remote Procedure Calls

Siri Atma Oaklander De Licori saodl at yahoo.com
Thu Oct 2 15:59:05 CDT 2003


I'm not really asking about RPC, but rather good ways
to load fragments from other static pages into the
current page using javascript.

I'm working on a project where I need to add content
from other documents to a page at the user's request. 
I can't include all this information in the page and
just hide it because it would balloon the file size
horribly, and much of it would not be used.  I have to
do this through Javascript for an offline version that
should fit on a cd- another reason for keeping the
additional info in seperate files: many pages require
the same data, and keeping it seperate lets me
actually fit everything on one cd while including
everything would make the files too large by repeating
endlessly the same information.

I'm currently using a hidden IFrame to load up other
files, but this must be done sequentially and
sometimes causes explorer to crash.  I'm not sure why
I get these occasional crashes (they aren't
consistent)- it could be from messing with the
document tree too much, as easily as loading the
files.  I often need to load fragments from upwards of
20 files into the document tree in response to one
click.  The code I'm using (taken largely from
O'Reilly's JavaScript book):

***********Begin code block**********

// global IFrame object- created on first call
// and used for every call thereafter
var IFrameObj;
// either the ID of the object where the result will
// be sent, or the object itself.
var gsDestination; 
// A function call to be made after the page is loaded
// to continue processing.  It gets passed to the 
// setTimeout function.  I use this mainly to 
// facilitate sequential calls.
var gsCallAfter;
// 1st call: creates iframe, sets to IFrameObj.
// loads URL into the iframe.
// sets gsDestination to the display object.
function callToServer(URL,sReturnTo,sCallAfter) {
  if (!document.createElement) {return true};
  var IFrameDoc;
  gsDestination = sReturnTo;
  gsCallAfter = sCallAfter;
  if (!IFrameObj && document.createElement) {
    // create the IFrame and assign a reference to the
    // object to our global variable IFrameObj.
    // this will only happen the first time 
    // callToServer() is called
   try {
      var tempIFrame=document.createElement('iframe');
      tempIFrame.setAttribute('id','RSIFrame');
      tempIFrame.style.border='0px';
      tempIFrame.style.width='0px';
      tempIFrame.style.height='0px';
      IFrameObj =
document.body.appendChild(tempIFrame);
      
      if (document.frames) {
        // this is for IE5 Mac, because it will only
        // allow access to the document object
        // of the IFrame if we access it through
        // the document.frames array
        IFrameObj = document.frames['RSIFrame'];
      }
    } catch(exception) {
      // This is for IE5 PC, which does not allow
dynamic creation
      // and manipulation of an iframe object.
Instead, we'll fake
      // it up by creating our own objects.
      iframeHTML='\<iframe id="RSIFrame" style="';
      iframeHTML+='border:0px;';
      iframeHTML+='width:0px;';
      iframeHTML+='height:0px;';
      iframeHTML+='"><\/iframe>';
      document.body.innerHTML+=iframeHTML;
      IFrameObj = new Object();
      IFrameObj.document = new Object();
      IFrameObj.document.location = new Object();
      IFrameObj.document.location.iframe =
document.getElementById('RSIFrame');
      IFrameObj.document.location.replace =
function(location) {
        this.iframe.src = location;
      }
    }
  }
  
  if (navigator.userAgent.indexOf('Gecko') !=-1 &&
!IFrameObj.contentDocument) {
    // we have to give NS6 a fraction of a second
    // to recognize the new IFrame
   
setTimeout('callToServer('+URL+','+sReturnTo+')',10);
    return false;
  }
  
  if (IFrameObj.contentDocument) {
    // For NS6
    IFrameDoc = IFrameObj.contentDocument; 
  } else if (IFrameObj.contentWindow) {
    // For IE5.5 and IE6
    IFrameDoc = IFrameObj.contentWindow.document;
  } else if (IFrameObj.document) {
    // For IE5
    IFrameDoc = IFrameObj.document;
  } else {
    return true;
  }

  IFrameDoc.location.replace(URL);
  return false;
}

// The loaded document must call this function in its
// body.onload event.  Here we put the contents of the
// document in the specified element, and call the
// follow up function if one was named.
function returnResults() {
  var IFrameDoc;
  if (IFrameObj.contentDocument) {
    // For NS6
    IFrameDoc = IFrameObj.contentDocument; 
  } else if (IFrameObj.contentWindow) {
    // For IE5.5 and IE6
    IFrameDoc = IFrameObj.contentWindow.document;
  } else if (IFrameObj.document) {
    // For IE5
    IFrameDoc = IFrameObj.document;
  } else {
    return true;
  }
  if(typeof gsDestination == 'object') {
    gsDestination.innerHTML =
IFrameDoc.body.innerHTML;
  } else {
    document.getElementById(gsDestination).innerHTML =
IFrameDoc.body.innerHTML;
  }
  if (gsCallAfter) setTimeout(gsCallAfter,0);
}

***********End code block**********

I've done some research and found another possible
method which uses the XMLHttpRequest object.  However,
at least in Mozilla, it won't work offline.  Also one
of the documents I read about this technique was
describing it as a security problem...so maybe it's
best not to count on it.  I thought it'd be nice,
because I could use it asynchonously, and wouldn't
need to chain functions together to continue
processing using body.onload.  Here's the function I
used to try it out:

***********Begin code block**********

// If I could get this to work, I'd probably let layer
// be either an object, or an ID as above.  I'd also
// want to work at running it asynchronously, using
the
// onreadystatechange event of the XMLHttpRequest to 
// load the data (when readyState == 4, fully loaded).
function importFragment(lyr,url){
  if (document.all) {
    // IE version
    var xml = new ActiveXObject("Microsoft.XMLHTTP");
    // asynch set to false for now
    xml.Open( "GET", url, false);
    // no arguments- we are fetching a static page
    xml.Send();
    document.getElementById(lyr).innerHTML =
xml.responseText;
  } else {
    // Mozilla/Netscape 6+ version
    var xml = new XMLHttpRequest();
    xml.open("GET", url, false);
    xml.send(null);
    document.getElementById(lyr).innerHTML =
xml.responseText;
}

***********End code block**********

I know this post is rather verbose.  Thanks for
reading this far, and for your help if you have any
ideas or suggestions.

Siri

__________________________________
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search
http://shopping.yahoo.com


More information about the thelist mailing list