org.rstudio.studio.client.common.mathjax.MathJaxLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.rstudio.studio.client.common.mathjax.MathJaxLoader.java

Source

/*
 * MathJaxLoader.java
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.studio.client.common.mathjax;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.HeadElement;
import com.google.gwt.dom.client.ScriptElement;
import com.google.inject.Singleton;

@Singleton
public class MathJaxLoader {
    public interface Callback {
        public void onLoaded(boolean alreadyLoaded);
    }

    public MathJaxLoader() {
        ensureMathJaxLoaded();
    }

    public static boolean isMathJaxLoaded() {
        return MATHJAX_LOADED;
    }

    public static void ensureMathJaxLoaded() {
        if (MATHJAX_LOADED)
            return;

        initializeMathJaxConfig();
        ScriptElement mathJaxEl = createMathJaxScriptElement();
        HeadElement headEl = Document.get().getHead();
        headEl.appendChild(mathJaxEl);
        Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
            @Override
            public boolean execute() {
                if (isMathJaxReady()) {
                    MATHJAX_LOADED = true;
                    for (Callback callback : MATHJAX_CALLBACKS)
                        callback.onLoaded(false);
                    onMathJaxLoaded();
                    return false;
                }

                RETRY_COUNT++;
                return RETRY_COUNT < 50;
            }
        }, 500);
    }

    public static final void withMathJaxLoaded(Callback callback) {
        if (callback == null)
            return;

        if (MATHJAX_LOADED) {
            callback.onLoaded(true);
            return;
        }

        MATHJAX_CALLBACKS.add(callback);
    }

    // Private Methods ----

    private static final native void onMathJaxLoaded() /*-{
                                                       var MathJax = $wnd.MathJax;
                                                           
                                                       // avoid jittering
                                                       MathJax.Hub.processSectionDelay = 0;
                                                       }-*/;

    private static final native void initializeMathJaxConfig() /*-{
                                                                   
                                                               if (typeof $wnd.MathJax !== "undefined")
                                                               return;
                                                                   
                                                               $wnd.MathJax = {
                                                               extensions: ['tex2jax.js'],
                                                               jax: ['input/TeX', 'output/HTML-CSS'],
                                                               tex2jax: {
                                                               inlineMath:  [['$', '$'], ['\\(', '\\)']],
                                                               displayMath: [['$$', '$$'], ['\\[', '\\]']],
                                                               processEscapes: true
                                                               },
                                                               "HTML-CSS": {
                                                               minScaleAdjust: 125,
                                                               availableFonts: []
                                                               },
                                                               showProcessingMessages: false,
                                                               showMathMenu: false,
                                                               messageStyle: "none",
                                                               skipStartupTypeset: true,
                                                               menuSettings: {
                                                               zoom: "None",
                                                               context: "Browser"
                                                               }
                                                               };
                                                                   
                                                               }-*/;

    private static final native boolean isMathJaxReady() /*-{
                                                         var mathjax = $wnd.MathJax || {};
                                                         return mathjax.isReady;
                                                         }-*/;

    private static ScriptElement createMathJaxScriptElement() {
        ScriptElement el = Document.get().createScriptElement();
        el.setAttribute("type", "text/javascript");
        el.setSrc("mathjax/MathJax.js?config=TeX-MML-AM_CHTML");
        el.setAttribute("async", "true");
        return el;
    }

    private static List<Callback> MATHJAX_CALLBACKS = new ArrayList<Callback>();
    private static boolean MATHJAX_LOADED = false;
    private static int RETRY_COUNT = 0;

}