Module 4 - Building JavaScript
==============================

In this module you're going to learn how to use the ``jsbuild`` tool to minify
the JavaScript of your application. Minifying the JavaScript code is important
if you care about performance, as it drastically reduces the time to load the
JavaScript code.

Installation
------------

The ``jsbuild`` tool is included in the ``JSTools`` Python package. The MapFish
framework package depends on ``JSTools``, so ``JSTools`` was installed in the
virtual Python environment as part of the framework installation.

You can check that ``jsbuild`` is properly installed by running this command::

    (env) C:\MapFish>C:\MapFish\env\Scripts\jsbuild.exe --help

It should produce this output::

    Usage: jsbuild-script.py [options] filename1.cfg [filename2.cfg...]

    Options:
      -h, --help            show this help message and exit
      -u, --uncompress      Don't compresses aggregated javascript
      -v, --verbose         print more info
      -o OUTPUT_DIR, --output=OUTPUT_DIR
                            Output directory
      -r RESOURCE_DIR, --resource=RESOURCE_DIR
                            resource base directory (for interpolation)
      -j SINGLE_FILE, --just=SINGLE_FILE
                            Only create file for this section
      -s CONCAT, --single-file-build=CONCAT
                            Create a single file of all of possible output
      -c COMPRESSOR, --compressor=COMPRESSOR
                            Compressor plugin to use in form
                            {specifier}:{'arguments_string'}

Creating Build Profile
----------------------

To be able to minify your application JavaScript code you must first create a
*build profile*. A build profile holds the build configuration: paths to
JavaScript folders, etc.

A build profile for the default user interface is provided in
``jsbuild/app.cfg``. It looks like this::

    [MapFish.js]
    root =
        ../mapfishapp/public/mfbase/openlayers/lib
        ../mapfishapp/public/mfbase/mapfish
        ../mapfishapp/public/mfbase/geoext/lib
        ../mapfishapp/public/app/js
    first =
        OpenLayers/SingleFile.js
        OpenLayers.js
        OpenLayers/Util.js
        OpenLayers/Lang.js
        OpenLayers/Lang/en.js
        OpenLayers/Console.js
        OpenLayers/BaseTypes.js
        OpenLayers/BaseTypes/Class.js
        OpenLayers/BaseTypes/Pixel.js
        OpenLayers/BaseTypes/Bounds.js
        OpenLayers/BaseTypes/LonLat.js
        OpenLayers/BaseTypes/Element.js
        OpenLayers/BaseTypes/Size.js
        Rico/Corner.js
        SingleFile.js
        MapFish.js
        core/Util.js
    include =
        mapfishapp_init.js
    exclude =
        GeoExt.js
        GeoExt/SingleFile.js

``[MapFish.js]``
    ``MapFish.js`` will be the name of the resulting build file.

``root``
    The ``root`` property provides the paths to the folders containing
    JavaScript code. It is to be noted that, with the above build profile, the
    JavaScript code for OpenLayers, GeoExt, MapFish Client, and the application
    is minified and merged in a single build file, ``MapFish.js``.

``first``
    The ``first`` property provides the list of JavaScript files that
    must be first in the resulting build file.

``include``
    The ``include`` property provides the list of files that should be included
    in the build file. You'll note that only file is specified here: the entry
    point file. The other JavaScript files to be included in the build file are
    specified using ``@include`` directives in the JavaScript files themselves.

``exclude``
    The ``exclude`` property provides the list of files that should not be
    included in the build file.

Building
--------

Before actually building the JavaScript code you need to create the folder
where the build file will be placed. In the ``public`` folder create a folder
named ``build`` with two sub-folders, ``mapfish`` and ``openlayers``.

You can now launch the build command::

    (env) C:\MapFish>cd MapFishApp/jsbuild
    (env) C:\MapFish\MapFishApp\jsbuild>C:\MapFish\env\Scripts\jsbuild.exe -o ..\mapfishapp\public\build\mapfish app.cfg

The output should be::

    Done:
    ..\mapfishapp\public\build\mapfish\MapFish.js

The last thing that you need to do is copy resource files. Copy the MapFish
``img`` folder in the ``public/build/mapfish`` folder, and copy the OpenLayers
``img`` and ``theme`` folders in the ``public/build/openlayers`` folder.  Look
at the ``README.txt`` file in the ``jsbuild`` folder to know where the MapFish
``img``, the OpenLayers ``img`` and the OpenLayers ``theme`` folders are. Note
that you need to do this copy operations only once.

You can now edit ``public/index.html`` to use the built version of the
JavaScript code. For that comment the *debug mode* section and uncomment the
*non debug mode* section. Like this::

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
        <meta name="content-language" content="en" />
        <title>Application</title>

        <link rel="stylesheet" type="text/css" href="mfbase/ext/resources/css/ext-all.css"></link>
        <link rel="stylesheet" type="text/css" href="mfbase/ext/resources/css/xtheme-gray.css"></link>
        <link rel="stylesheet" type="text/css" href="mfbase/mapfish/mapfish.css"></link>

        <script type="text/javascript" src="mfbase/ext/adapter/ext/ext-base.js"></script>

        <!-- debug mode (begin) -->
        <!--
        <script type="text/javascript">
            // Because of a bug in Firefox 2 we need to specify the MapFish base path.
            // See https://bugzilla.mozilla.org/show_bug.cgi?id=351282
            var gMfLocation = "mfbase/mapfish/";
        </script>
        <script type="text/javascript" src="mfbase/ext/ext-all-debug.js"></script>
        <script type="text/javascript" src="mfbase/openlayers/lib/OpenLayers.js"></script>
        <script type="text/javascript" src="mfbase/geoext/lib/GeoExt.js"></script>
        <script type="text/javascript" src="mfbase/mapfish/MapFish.js"></script>
        <script type="text/javascript" src="app/js/mapfishapp_layout.js"></script>
        <script type="text/javascript" src="app/js/mapfishapp_init.js"></script>
        -->
        <!-- debug mode (end) -->

        <!-- non debug mode (begin) -->
        <script type="text/javascript" src="mfbase/ext/ext-all.js"></script>
        <script type="text/javascript" src="build/mapfish/MapFish.js"></script>
        <!-- non debug mode (end) -->

    </head>
    <body>
    </body>
    <html>

You can now reload http://localhost:5000 in your browser.

You should get JavaScript errors in the FireBug console, this is because you
added functionality in the previous modules of this workshop without adding
proper ``@include`` directives in the ``mapfishapp_layout.js``. You should be
able to fix that by adding the missing ``@include`` directives::

    @include OpenLayers/Layer/WMS.js
    @include OpenLayers/Request/XMLHttpRequest.js
    @include core/Searcher/Map.js
    @include core/Protocol/MapFish.js
    @include core/Protocol/TriggerEventDecorator.js
    @include core/Protocol/MergeFilterDecorator.js
