Exibição de Fórmulas Matemáticas com JQuery Mobile e MathJax

Dicas para exibição de conteúdo matemático com MathJax e JQuery Mobile.

jQuery Mobile, segundo seus autores, é um “Framework UI baseado em HTML5 projetado para desenvolver sites e aplicativos que sejam acessíveis em todos os dispositivos (smartphone, tablet e desktop) de forma responsiva”.
MathJax, novamente segundo seus autores, é um “Mecanismo JavaScript para exibição de textos matemáticos que executa em todos os navegadores”.
Juntando essas tecnologias podemos construir aplicações multi-plataforma que mostram conteúdo matemático dinâmico de uma forma simples e versátil.

O aplicativo

Nesta dica vamos ilustrar uma aplicação muito simples que mostra o poder dessas bibliotecas: O Cálculo de equações quadráticas, como mostrado na figura abaixo:

Aplicativo JQuery Mobile com MathJax
Aplicativo JQuery Mobile com MathJax

Veja como as fórmulas matemáticas são exibidos de uma forma muito profissional. Você pode executar este aplicativo on-line aqui.

O funcionamento do aplicativo é muito simples:

  1. O sistema exibe a tela e espera que o usuário digite os coeficientes da equação
  2. O sistema valida os dados inseridos e, se tudo estiver ok, os resultados são apresentados

Para a edição de código-fonte, eu usei as seguintes ferramentas:

  • NetBeans IDE – Excelente suporte para HTML5, CSS3 e JavaScript
  • RIB – é uma ferramenta de design baseada em navegador para criar a interface do usuário para o jQuery Mobile

O código-fonte

Vamos olhar para o código HTML desta aplicação:

<!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é 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="https://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script type="text/javascript" src="https://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`&nbsp;&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>


Pontos de interesse:

  1. A biblioteca MathJax pode ser configurada logo no carregamento. Neste caso, usamos o parâmetro AM_HTMLorMML-full. Este arquivo de configuração é para sites que utilizam apenas o formato AsciiMath para exibir suas fórmulas matemáticas. Ele vai usar a saída MathML nos navegadores que a suportam e saída de HTML/CSS3 caso não haja suporte;
  2. AsciiMath é uma biblioteca que converte expressões matemáticas (computacionais) em código MathML on-the-fly. Para isso, a expressão deve ser delimitada com `…` ;
  3. A chamada à biblioteca local foi colocada no corpo do documento para garantir o carregamento correto de todas as bibliotecas;

Em seguida, olhar para o código javascript:

/* Quadratic Equation Solver
 * 2015, by José Cintra
 * e-Mail: jose.cintra@html-apps.info
 * 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();
}


Pontos de interesse:

  1. Em JQuery Mobile, o equivalente ao evento onload do elemento BODY é o evento pageinit;
  2. O resultado será atualizado cada vez que o usuário pressiona uma tecla, através da captura do evento KeyUP;
  3. O uso da função eval permite que o usuário insira expressões matemáticas (uma fração, por exemplo) para os coeficientes.
  4. Observe que cada vez que a expressão é alterada pelo usuário, nós chamamos o método MathJax.Hub.Queue que irá atualizar a fórmula que está sendo exibida.

Recursos

Conclusão

Há ainda alguns problemas de compatibilidade entre navegadores que não renderizam o MathJax adequadamente, mas o uso combinado dessas bibliotecas viabiliza a construção de aplicações matemáticas muito interessantes.

Isso é tudo! Espere ter ajudado.

Até a próxima…

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *