Displaying Mathematical Content with MathJax and JQuery Mobile


Here are some tips for creating mathematical multiplatform applications in Javascript and display formulas and other content with MathJax and
JQuery Mobile.

This tip was originally published by the author on CodeProject.

Download Source Code  

Live Demo


Introduction

jQuery Mobile, according to its authors, is a "HTML5-based user interface system designed to make responsive web sites and apps that are accessible on all smartphone, tablet and desktop devices".

MathJax, again according to its authors, is a "JavaScript display engine for mathematics that works in all browsers".

Joining these technologies, we can build cross-platform applications that show dynamic mathematical content in a simple and versatile way.

In this tip, we will illustrate a very simple application that shows the power of these tools. This is the calculation of quadratic equations, as shown in the screen below.

Quadratic Equation Solver

 
See how mathematical formulas are displayed in a very professional way. You can run this online application here.

The operation of the application is very simple:

  1. The system displays the screen and waits for the user to enter the coefficients of the equation
  2. The system validates the data entered and, if all is ok, the results are presented

For source code editing, i used the following tools:
NetBeans IDE - Excellent support for HTML5, CSS3 and Javascript
RIB - Is a browser-based design tool for creating the user interface for JQuery Mobile

 

Using the code

Let's look at the HTML code of this application:

 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Yet Another Quadratic Equation Solver</title>
        <meta name="keywords" content="mathematics,math,html5,javascript,mathjs,mathjax,quadratic,equation,solve" />
        <meta name="description" content="Calculating the roots of quadratic equation with mathjax and jquery mobile" />
        <meta name="author" content="Jos&eacute; Augusto Cintra">
        <meta name="robots" content="index, follow">
        <meta name="viewport" content="width=device-width; initial-scale=1.0">
        <meta name="HandheldFriendly" content="true"/>
        <meta name="MobileOptimized" content="320"/>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>        
        <script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=AM_HTMLorMML-full"></script>
    </head>
    <body>
        <div data-role="page" id="main_page" data-theme="a">
            <div data-role="header"  data-position="fixed">
                <h3 style="text-align:left; margin-left:10px;color: green;">Yet Another Quadratic Equation Solver</h3>
            </div>
            <div data-role="content" id="main_content">
                <div class="ui-corner-all ui-overlay-shadow" style="padding: 1em;">
                    <strong>Coefficients for `ax^2 + bx + c`&amp;nbsp;&amp;nbsp;`(a ne 0)`  :</strong>
                    <div class="ui-grid-b">
                        <div class="ui-block-a">
                            <div data-controltype="textinput" >
                                <input class="coef" name="a_coef" id="a_coef" placeholder="a" value="" type="text" >
                            </div>
                        </div>
                        <div class="ui-block-b">
                            <div data-controltype="textinput" >
                                <input class="coef" name="b_coef" id="b_coef" placeholder="b" value="" type="text">
                            </div>
                        </div>
                        <div class="ui-block-c">
                            <div data-controltype="textinput" >
                                <input class="coef" name="c_coef" id="c_coef" placeholder="c" value="" type="text">
                            </div>
                        </div>
                    </div>
                    <div id="results">
                        <p>
                            <br/>
                            <strong style="text-decoration: underline;color: green;">Equation</strong>
                            <br/>
                        <div id="dv_equation"></div>
                        </p>
                        <p>
                            <br/>
                            <strong style="text-decoration: underline;color: green;">Solution</strong>
                            <br/>
                        </p>
                        `Delta = b^2 - 4ac = `<span id="dv_delta"></span>
                        <br/>
                        <br/>
                        <span id="dv_delta_msg"></span>
                        <br/>
                        <span class="x" id="dv_x1"></span>
                        <br/>
                        <span class="x" id="dv_x2"></span>
                    </div>
                </div>
            </div>
            <div data-role="footer" id="main_footer" data-position="fixed" >
                <a href="http://html-apps.info" target="_BLANK" style="text-align:left; margin-left:10px;color: green;">HTML Apps</a>
            </div>
        </div>
        <script src="js/yaques.js"></script>
    </body>
</html>
 

 

A few important notes:

  1. The MathJax library can be configured since the loading. In this case, we use the AM_HTMLorMML-full parameter. This configuration file is for sites that only use AsciiMath format for their mathematics. It will use MathML output in browsers where that is supported well, and HTML-CSS output otherwise;
  2. AsciiMath is a library that converts mathematical (computational) expressions into MathML code on-the-fly. For this, the expression must be enclosed with `...` delimiters.
  3. The reference to local JS Library was made in the document body to ensure correct loading of libraries;

 

Next, Look the code behind:

[code]/* Quadratic Equation Solver
 * 2015, by José Cintra
 * e-Mail: This email address is being protected from spambots. You need JavaScript enabled to view it.
 * HomePage: html-apps.info
 */
var a_coef = b_coef = c_coef = 0;

//Event handling
	$('#main_page').on('pageinit', function() {
		$('#results').hide();
		$('.coef').bind('keyup', function(event) {
		  $('#results').hide();
		  a_coef = Number(eval($('#a_coef').val()));
		  b_coef = Number(eval($('#b_coef').val()));
		  c_coef = Number(eval($('#c_coef').val()));
		  if ($.isNumeric(a_coef) && $.isNumeric(b_coef) && $.isNumeric(c_coef)) {
			if (a_coef != 0) {
				Refresh();
			}
		  }  
		});
	});

//Calculating and updating the screen
function Refresh(){
    
    //Display equation
    a_coef_text = b_coef_text = c_coef_text = "";
    a_coef_text = (a_coef < 0 ? "-" : "") + (Math.abs(a_coef) === 1 ? "" : String(Math.abs(a_coef))) + "x^2 ";
    if(b_coef !== 0){
      b_coef_text = (b_coef < 0 ? " - " : " + ") + (Math.abs(b_coef) === 1 ? "" : String(Math.abs(b_coef))) + "x ";
    }
    if(c_coef !== 0){
      c_coef_text = (c_coef < 0 ? " - " : " + ") + String(Math.abs(c_coef));
    }
    equation_text = a_coef_text + b_coef_text + c_coef_text + " = 0";
    $('#dv_equation').text("`" + equation_text + "`");
    MathJax.Hub.Queue(["Typeset", MathJax.Hub, "dv_equation"]);

    //Get the solution
    x1 = x2 = 0;
    delta = (Math.pow(b_coef,2)) - (4 * a_coef * c_coef);

    $('.x').text(""); //clear roots
    $('#dv_delta').text('`' + delta + '`');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'dv_delta']);

    delta_msg = "How `Delta` is negative, the equation has NO real roots";
	if (delta === 0) {
		delta_msg = "How `Delta` is ZERO, the equation has ONE real root:";
		x1 = (-b_coef + Math.sqrt(delta))/(2*a_coef)
		x1_text = "x = (-b + sqrt(Delta))/(2a) = ".concat(x1);
		$('#dv_x1').text('`' + x1_text + '`');
    	MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'dv_x1']);
	}
	else if (delta > 0) {
		delta_msg = "How `Delta` is positive, the equation has TWO real roots:";
		x1 = (-b_coef + Math.sqrt(delta))/(2*a_coef)
		x1_text = "x1 = (-b + sqrt(Delta))/(2a) = ".concat(x1);
		$('#dv_x1').text('`' + x1_text + '`');
    		MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'dv_x1']);
		x2 = (-b_coef - Math.sqrt(delta))/(2*a_coef)
		x2_text = "x2 = (-b - sqrt(Delta))/(2a) = ".concat(x2);
		$('#dv_x2').text('`' + x2_text + '`');
    	MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'dv_x2']);
	}

    //Print solution
    $('#dv_delta_msg').text(delta_msg);
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'dv_delta_msg']);
	$('#results').show();
}

[/code]


A few important notes:

  1. In JQuery Mobile, the equivalent to the onload event of the body element is the event pageinit;
  2. The result will be updated every time the user presses (release) a key, by capturing the event keyup;
  3. The use of eval function allows the user to enter mathematical expressions (a fraction, for example) for the coefficients.
  4. Note that every time the expression is changed by the user, we call the method MathJax.Hub.Queue that will update the formula being displayed.


Conclusion

There are still some compatibility issues between browsers, but the combined use of these  tools enable the construction of very interesting mathematical applications.

See you soon!