(function() {  // Randall Farmer, twotwotwo at gmail.  Public domain, 2007-2009.
  var esc = function(str) { 
    var s = escape(str); 
    return s.replace(/\+/g, '%2B') 
  };
  var escHTML = function(str) {
    return str.replace( // escape for HTML attribute
        /[\'\"<>\=\$\\]/g, 
        function(c) { return '&#' + c.charCodeAt(0) + ';' } 
    );
  };
  var images = [];  // for hide-raw-TeX-on-load hack
  var mathUrls = {};
  var mathRegExp = 
    /\$\$(.|\n)*?\$\$|\B\$[^<$]*?\$\B|\\\((.|\n)*?\\\)|\\\[(.|\n)*?\\\]/g;
  var mathRegExp2 = 
    /(\$\$(.|\n)*?\$\$|\B\$[^<$]*?\$\B|\\\((.|\n)*?\\\)|\\\[(.|\n)*?\\\])/;

  if ( !window.mathSite ) 
    window.mathSite = window.location.hostname + window.location.pathname + 
      window.location.search;
  if ( !window.mathServer ) 
    window.mathServer = 'http://mathcache.appspot.com/?tex=';
  if ( !window.mathJsServer ) 
    window.mathJsServer = 'http://mathcache.appspot.com/';
  if ( !window.mathPreamble ) window.mathPreamble = '\\large \\parstyle ';
  var div = document.createElement('div');
  var $L = function(i) { if ( window.console ) window.console.log(i) }
  
  var isMath = window.mathChecker || function( mathText ) {
      if ( window.mathNoDollar )
          return /^(\$\$|\\\(|\\\[)/.test(mathText);
      if ( /[_\\^]|\$\$|\w\(/.test(mathText) ) 
      	  return true;
      if ( /[A-Za-z]{2,} [A-Za-z]{2,}/.test(mathText) )
          return false;
      if ( !!/^\$[ \t\n]/.test(mathText) != !!/[ \t\n]\$$/.test(mathText) )
          return false;
      return true;
  };
  
  var spans = {};
  var replacement = function( mathHtml ) {
    div.innerHTML = mathHtml;
    var mathText = div.firstChild.nodeValue;
    if ( !isMath(mathText) ) return mathHtml;
    
    var staticUrl = mathUrls[mathPreamble + mathText];
    var src = staticUrl || 
              (mathServer + esc( mathPreamble + mathText ));
    var alt = escHTML(mathText);

    var num = images.length;
    var imgHtml = "<img class='mathimg' src='"+src+"' alt='" +
                  alt + "' title='" + alt + "' />";
    var html = '<span class="math" id="math' + num + '">' 
               + (staticUrl ? imgHtml : mathHtml) 
               + '</span>';
    var img = images[num] = new Image();
    img.onload = function() {
      var span = document.getElementById( 'math' + num );
      if ( span ) span.innerHTML = imgHtml;
      else html = imgHtml;
    };
    img.src = src;
    return html;
  }

  var msie = /msie/i.test(navigator.userAgent);
  if ( !window.mathCleaner ) window.mathCleaner = function(orig) {
      var cleaned = orig.replace(/<\/?(br|p)\b.*?>/ig, '');
      return /[<>]/.test( cleaned ) ? orig : cleaned;
  };
  var isDesignMode = window.mathIsDesignMode = function(elem) {
    var e = elem;
    while (e.parentNode) e=e.parentNode;
    return /^on$/i.test(e.designMode);
  }
  var lacksAttribute = function(elem, attr) {
    var res = elem.getAttribute(attr);
    return res == undefined || res == null;
  }
  var replace = window.replaceMath = function(elem, richEditsOnly, replacer) {
    var iframes = elem.getElementsByTagName('iframe');
    for ( var i = 0; i < iframes.length; ++i ) {
      try {
        var doc = 
          iframes[i].contentDocument || iframes[i].contentWindow.document;
        replace(doc.body, richEditsOnly, replacer);
      } catch (e) {};
    }
    if ( richEditsOnly
         && /^body$/i.test(elem.tagName) 
         && !isDesignMode(elem)
         && lacksAttribute(elem, 'contentEditable') ) return;

    if ( !mathRegExp2.test( elem.innerHTML ) ) return;
    if ( /pre|code/.test( elem.tagName ) )
      return elem.innerHTML = elem.innerHTML.replace(/([\$\\])/g, escHTML);
    
    for ( var child = elem.firstChild; child; child = child.nextSibling )
      if ( child.tagName ) replace( child, richEditsOnly, replacer );

    var newHtml = elem.innerHTML.replace( mathRegExp, window.mathCleaner );
    if ( elem.innerHTML != newHtml ) elem.innerHTML = newHtml;
    
    for ( var child = elem.firstChild; child; child = child.nextSibling )
      if ( child.nodeType == 3 && mathRegExp2.test( child.nodeValue ) ) {
        // simple case for "only children"
        if ( child == elem.firstChild && !child.nextSibling ) {
          elem.innerHTML = 
            elem.innerHTML.replace( mathRegExp, replacer || replacement );
          continue;
        }
        var s = elem.insertBefore( document.createElement('span'), child );
        s.appendChild( child );
        child = s;
        child.innerHTML = 
          child.innerHTML.replace( mathRegExp, replacer || replacement );
      }
  }

  // Alternate path to replace TeX with static images, and unreplace math
  var seenTex = {};
  var foundTex = [];
  var renderedCount = 0;
  var elemToReplace;
  var doRichEditsOnly;
  var texCollector = function(tex) {
    if ( !seenTex[tex] ) {
      seenTex[tex] = 1;
      foundTex.push(tex);
    }
    return tex;
  };
  var newScript = function() {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    return script;
  }
  var replaceStatic = window.replaceMathStatic = function(elem, richEditsOnly) {
    window.replaceMath(elem, richEditsOnly, texCollector);
    elemToReplace = elem; doRichEditsOnly = richEditsOnly;
    // Saddens me to do a script per bit of TeX being replaced, but everything
    // chokes on long GET requests and other cross-domain methods suck so huh
    var initialSrc = window.mathJsServer + '?cb=mathFinishReplacingStatic';
    var script = newScript();
    var src = initialSrc;
    for ( var i = 0; i < foundTex.length; ++i ) {
      src += '&tex=' + esc(window.mathPreamble + foundTex[i]);
      if ( src.length > 1000 ) {
        script.src = src;
        document.getElementsByTagName('head')[0].appendChild(script);
        script = newScript();
        src = initialSrc;
      }
    }
    script.src = src;
    document.getElementsByTagName('head')[0].appendChild(script);
  }
  var finishReplacingStatic = window.mathFinishReplacingStatic = 
  function(tex_url_map) {
    for ( tex in tex_url_map ) { 
      mathUrls[tex] = tex_url_map[tex]; 
      renderedCount++;
    }
    if ( renderedCount >= foundTex.length )
      window.replaceMath(elemToReplace, doRichEditsOnly);
  }
  var outtext = function(tex) {
    if (/\$|\\\(|\\\[/.test(tex)) return tex;
    if (isMath('$ ' + tex + ' $')) return '$ ' + tex + ' $';
    return '\\(' + tex + '\\)';
  }
  var mathSpanRegExp = /<span[^<]*class=[\'\"]?math(.|\n)*?<\/span>/i;
  var unReplace = window.unReplaceMath = function(elem) {
    var iframes = elem.getElementsByTagName('iframe');
    for ( var i = 0; i < iframes.length; ++i ) {
      try {
        var doc = 
          iframes[i].contentDocument || iframes[i].contentWindow.document;
        unReplace(doc.body);
      } catch (e) {};
    }
    var nodesToEatLater = [];
    var images = elem.getElementsByTagName('img');
    for ( var i = 0; i < images.length; ++i ) {
      var img = images[i];
      // Unreplace replacemath images
      if (/\b(mathimg)\b/.test(img.className)) {
        var textNode = document.createTextNode(img.alt)
        var span = img.parentNode;
        span.parentNode.insertBefore(textNode, span);
        if (/\bmath\b/.test(span.className)) nodesToEatLater.push(span);
        else nodesToEatLater.push(img)
      }
      // Give LaTeXrender images and untagged replacemath images a try, too
      else if (/latexrender|d1zzpfmd0gfoe8.cloudfront.net/i.test(img.src)) {
        var textNode = document.createTextNode(outtext(img.alt))
        img.parentNode.insertBefore(textNode, img)
        nodesToEatLater.push(img)
      }
    }
    for ( var i = 0; i < nodesToEatLater.length; ++i )
      nodesToEatLater[i].parentNode.removeChild(nodesToEatLater[i])
  }
  if ( window.onMathLoaded ) window.onMathLoaded();
})();
