5
\$\begingroup\$

I have this page that allows a user to quickly compile \$\LaTeX\$ code into a mathematical display. Whenever the user compiles the code, that page also generates an URL from which it is possible to view the output simply by visiting the URL:

Demonstration

index.html (Note that this Stack Snippet generates non-working URLs because it is on a different domain):

<!DOCTYPE html>
<html>
    <head>
        <script type="text/x-mathjax-config">
            MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
        </script>

        <script type="text/javascript" async
                src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML">
        </script>

        <script type="text/javascript">
            function get_url_parameter(param)
            {
                var page_url = window.location.search.substring(1);
                var url_vars = page_url.split('&');

                for (var i = 0; i < url_vars.length; ++i) 
                {
                    var param_name = url_vars[i].split('=');

                    if (param_name[0] == param) 
                    {
                        return param_name[1];
                    }
                }
            }
        </script>

        <title>LaTeX console</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1 align="center">Type in the LaTeX code and press <b>Compile!</b></h1>

        <div align="center" style="margin: 30px;">
            <p id="latex_output">
                {06f672e0-065e-445d-8e16-0790142de8ab}
            </p>
        </div>

        <div align="center">
            <h3>Input area</h3>
            <textarea id="latex_input" rows="5" cols="80">{bcd26d9d-9bcd-40d8-9357-ef17752144a1}</textarea>
        </div>

        <div align="center" style="margin: 30px;">
            <button type="button" id="compile_button">Compile!</button>
        </div>

        <div align="center">
            <h3>URL to share</h3>
            <textarea id="encoded_url_textarea" rows="5" cols="80"></textarea>
        </div>

        <script>
            compile_button       = document.getElementById("compile_button");
            latex_output         = document.getElementById("latex_output");
            latex_input          = document.getElementById("latex_input");
            encoded_url_textarea = document.getElementById("encoded_url_textarea");

            compile_button.onclick = function() { 
                latex_output.innerHTML = latex_input.value;
                MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
                encoded_url_textarea.value = location.protocol +
                                             '//' +
                                             location.host +
                                             location.pathname +
                                             "?code=" +
                                             encodeURIComponent(latex_input.value);
            };

            var code = get_url_parameter("code");

            if (code) 
            {
                latex_input.value = decodeURIComponent(code);
                latex_output.innerHTML = latex_input.value;
                MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
            }
        </script>
    </body>
</html>

As always, any critique is appreciated.

\$\endgroup\$
1
\$\begingroup\$

I'll just go through this as I find issues:

  1. Don't declare your main dependency as async. In case the server goes down that makes your page look stupid. What you should do instead is check that the script was actually loaded before trying to use it.

  2. JS standard naming convention for functions is camelCase. see the js-standard api as well as every major js framework. This is not python: get_url_parameter \$\rightarrow\$ getUrlParameter.
    Same applies for variable names throughout your code.

  3. Use 'use strict' to force compliance to new JS standards. And use it in the largest scope you control alone:

    function getUrlParameter(param) {
        'use strict'
        let pageUrl =  // ...
    
  4. I like how you encapsulated the parameter getting into it's own method. I also like how you use standard functions to URI-encode correctly instead of rolling your own encoding

  5. Last time I checked (which is a while ago) it was common to wrap top-level code into a self-executing function like this:

    (function() {
        // ... 
    })();
    

    the main reason why is outlined here on SO

  6. use let over var to communicate mutability intents to other developers (and the script engine). Also don't rely on implicit variable declaration. that's cheap :)

  7. I never understood the point of aligning an assignment operation's right hand side :/

  8. You can make things a tad easier when creating the encodedUrlTextarea.value by using template interpolation:

    encodedUrlTextarea.value = `${location.protocol}//${location.host}${location.pathname}?code=${encodeURIComponent(latexInput.value)}`;
    

    This can be made a bit cleaner with some extraction:

    let baseUrl = `${location.protocol}//${location.host}${location.pathname}`;
    let code = encodeURIComponent(latexInput.value);
    encodedUrlTextarea.value = `${baseUrl}?code=${code}`;
    

    As we can see, the creation of baseUrl can be pulled out of the function. It won't change during the script lifetime. Take advantage of that. It's definitely debatable whether the call to encodeURIComponent now really needs to be outside the template string

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.