jsMath selective loading...

Blake Hurd
2009-01-09
2013-04-29
  • Blake Hurd
    Blake Hurd
    2009-01-09

    Hey, I just discovered jsMath. Fantastic product!

    I have been looking into ways to get it to load as fast as possible. If I load via easy/load.js, it auto-processes the page, which I don't want to do. I want to include jsMath, then tell it to load as soon as I need its ProcessElement function. I have tried using Autoload, but the javascript that triggers the Autoload causes jsMath to start loading and then hang.

    I execute this code whenever I make changes to or initialize a certain Element (FYI it's a span with class="math"):

    function processMathElement(e)
    {
         jsMath.Autoload.element = e;
         jsMath.Autoload.Check();
         jsMath.ProcessElement(e);
    }

    I realize that the Autoload.Check(); will be called more than once during the user's time, but currently it's only executed once and it still hangs.

    Thanks in advance!

     
    • OK, a couple of questions first:  if I understand correctly, you are not using easy/load.js, but are loading autoload.js by hand; do you load autoload.js in the HEAD or the BODY of the document?  Can you say more about what you mean by "it hangs"?  Does that mean you get the "loading jsMath" message but it doesn't go away, or is it something else?  Also, what browser are you using and on what platform?

      There are a couple of problems with your current implementation.  First jsMath.Autoload.element should be jsMath.Autoload.checkElement (it was incorrectly documented, and I will fix that in the next release).  Second, since you will be calling this many times, you should use jsMath.Autoload.ReCheck() rather than jsMath.Autoload.Check() since that can only be called once (as you point out).  Finally, note that the CONTENTS of the checkElement are checked, not the element itself.  That is, checkElement is considered to be a container and its contents is scanned for SPAN and DIV elements of class "math"; it is not itself checked to see if it is such a span or div.  So even if everything else were working, this would still not be what you wanted.

      It seems to me that you are only using autoload as a means of loading jsMath at some time after the page has loaded.  At the time processMathElement() is called, you KNOW you want jsMath to load, so you don't really need to check whether you want it to load or not; you just need it to load.  It is probably better to just do a check to see if you have already loaded jsMath and if not, load it directly, and then run your ProcessElement call.  Something like the following (untested) code:

      function processElement(e) {
      _ if (!window.jsMath) {window.jsMath = {}}
      _ if (jsMath.loaded) {
      ___ jsMath.ProcessElement(e);
      _ } else {
      ___ if (jsMath.pendingProcess) {
      _____ jsMath.pendingProcess[jsMath.pendingProcess.length] = e;
      ___ } else {
      _____ jsMath.pendingProcess = [e];
      _____ if (!jsMath.Setup) {jsMath.Setup = {}}
      _____ if (!jsMath.Setup.UserEvent) {jsMath.Setup.UserEvent = {}}
      _____ jsMath.Setup.UserEvent.onload = function () {
      _______ for (var i = 0; i < jsMath.pendingProcess.length; i++) {
      _________ jsMath.ProcessElement(jsMath.pendingProcess[i]);
      _______ }
      _______ delete jsMath.pendingProcess;
      _____ }
      _____ jsMath.Autoload = {root: "jsMath/"}; // put full URL to jsMath directory here
      _____ var script = document.createElement("script");
      _____ script.src = jsMath.Autoload.root + "jsMath.js";
      _____ (document.getElementsByTagName("head"))[0].appendChild(script);
      ___ }
      _ }
      }

      (Note that the underscores at the beginning of the lines are only to make the formatting work on line.  You will need to change them to spaces.)

      This routine checks to see if jsMath is already loaded, and if so just calls its ProcessElement routine.  If not, it checks to see if jsMath is in the process of loading (i.e., it has already been called and stacked an element for processing after jsMath loads), and if so, it simply adds the new element to the stack of pending elements to process.  Otherwise, we start a stack of pending elements, and set up an onload handler that will run when jsMath is loaded and initialized.  The handler simply loops through the pending elements and processes them. Finally, we create a SCRIPT tag that will cause jsMath to be loaded.  This loads asynchronously, which is why you need the onload handler.  That means your processElement call may return before the element is actually processed (and could be called again before it is processed, which is why we need the stack of pending elements, not just one).

      Anyway, I think that should work.  Good luck with your project.

      Davide

       
    • PS, with my code above, you DON'T load autoload.js at all.  You are handling the auotloading by hand in the processElement() routine.

      Davide

       
    • Blake Hurd
      Blake Hurd
      2009-01-09

      Thank you! That's exactly what I trying to do.

      Yeah, I was trying to load autoload.js in the HEAD. I was viewing it with IE. I was getting the Loading jsMath message and it wouldn't go away. The script was in an infinite loop or a hang, because IE asks me after a timeout whether to keep running the script or not. I've tried telling it to keep running the script a couple times and it never finishes, so I think it just hangs. I'm not sure if there is an error here or not, since the surrounding javascript code is innately complex (it's GWT, so it's Java compiled to JavaScript and almost completely async)...there is the possibility that my function was getting called before the <body> was completely developed (at the point where I call it, it's still adding Elements). However, with your proposed code the same standard would apply, except that there's no freezing.

      Thanks again!

       
      • I'm not sure exactly what the problem is, but the timing of loading jsMath versus calling jsMath functions is pretty delicate.  And IE is notoriously problematic, so it is a shame you have to do your development there. 

        Anyway, I'm glad it is working for you now.  It may be advisable for you to test this on several other browsers as well, though I think it should work across the ones supported by jsMath.

        Davide