(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 ';
  if ( !window.noAutoPng && !/msie 6/i.test(navigator.userAgent) ) 
       window.mathPreamble += '\\png ';
  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 replacement = function( mathHtml ) {
    div.innerHTML = mathHtml;
    var mathText = div.firstChild.nodeValue;
    if ( !isMath(mathText) ) return mathHtml;
    
    var src = mathUrls[mathPreamble + mathText] || 
              (mathServer + esc( mathPreamble + mathText ));
    var alt = escHTML(mathText);

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

  if ( !window.mathCleaner ) window.mathCleaner = function(orig) {
      var cleaned = orig.replace(/<\/?(br|p)\b.*?>/ig, '');
      return /[<>]/.test( cleaned ) ? orig : cleaned;
  };
  var replace = window.replaceMath = function(elem, replacer) {
    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, 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 );
      }
  }
})();
