API Docs for: 0.6.0
Show:

File: src/form.js


    /**
     * Handles all UI business for the HTML form for writing, issuing
     * and drawing sgvizler queries.
     *
     * Dependencies:
     *
     *  - sgvizler.util
     *  - sgvizler.namespace
     *  - sgvizler.registry
     *  - sgvizler.Query
     *
     * @class sgvizler.form
     * @static
     **/
    S.form = (function () {

        /*global $ */

        // Module dependencies:
        var util = S.util,
            prefixesSPARQL = S.namespace.prefixesSPARQL,
            registry = S.registry,
            Query = S.Query,

            /**
             * Approx. 15 properties giving name to HTML elements
             * which appear in the form.
             * @property idXs
             * @type String
             * @private
             * @since 0.2
             **/
            idprefix  =         'sgvzlr_',
            idMainCon =         idprefix + 'mainCon',
            idFormCon =         idprefix + 'formCon',
            idChartCon =        idprefix + 'gchart',      // #id to the container to hold the chart
            idQueryForm =       idprefix + 'formQuery',   //
            idQueryTxt =        idprefix + 'cQuery',      // query text area.
            idFormQuery =       idprefix + 'strQuery',    // hidden query string. "trick" taken from snorql.
            idFormEndpointGrp = idprefix + 'strEndpointGrp', //
            idFormEndpoint =    idprefix + 'strEndpoint', //
            idFormFormatGrp =   idprefix + 'btnFormatGrp',   //
            idFormFormat =      idprefix + 'btnFormat',   //
            idFormSizeGrp =     idprefix + 'strSizeGrp',    //
            idFormWidth =       idprefix + 'strWidth',    //
            idFormHeight =      idprefix + 'strHeight',   //
            idFormChartGrp =    idprefix + 'optChartGrp',    //
            idFormChart =       idprefix + 'optChart',    //
            idFormButtonGrp =   idprefix + 'btnSendGrp',    //
            idPrefixCon =       idprefix + 'cPrefix',     // print prefixes
            idMessageCon =      idprefix + 'cMessage',    // print messages
            idLogo =            idprefix + 'logo',
            idFooter =          idprefix + 'footer',

            /**
             * Contains groups of elements which make out the
             * form. Described using the array syntax edible by
             * sgvizler.util.createHTMLElement.
             * @property html
             * @type Object
             * @private
             * @since 0.6.0
             **/
            html = (function () {
                // Difficult to get whitespace correct while keeping it readable:
                /*jslint white: true */
                return {

                    /**
                     * The heading for the form: "Sgvizler".
                     * @property html.heading
                     * @type Array
                     * @private
                     * @since 0.6.0
                     **/
                    heading: ['h1', null, ['Sgvizler']],

                    /**
                     * Logo pointing to homepage.
                     * @property html.logo
                     * @type Array
                     * @private
                     * @since 0.6.0
                     **/
                    logo: ['div', { id: idLogo },
                           [
                               ['a', { href: S.core.HOMEPAGE },
                                [
                                    ['img',
                                     {
                                         src: S.core.HOMEFOLDER + 'www/mr.sgvizler.png',
                                         alt: "Mr. Sgvizler"
                                     }
                                    ]
                                ]
                               ],
                               'Mr. Sgvizler'
                           ]
                          ],

                    /**
                     * The form.
                     * @property html.main
                     * @type Array
                     * @private
                     * @since 0.6.0
                     **/
                    main:
                    ['div', { id: idFormCon },
                     [
                         // prefixes and namespaces.
                         ['pre', { id: idPrefixCon } ],
                         // textarea for writing query.
                         ['textarea', { id: idQueryTxt, rows: '10', cols: '80' } ],
                         ['form', { id: idQueryForm, method: 'get' },
                          [
                              ['p', null,
                               [
                                   // hidden query string
                                   ['input',
                                    {
                                        id: idFormQuery,
                                        type: 'hidden',
                                        name: 'query',
                                        value: ''
                                    }
                                   ],
                                   ['span', { 'id': idFormEndpointGrp }, [
                                        ['label', { 'for': idFormEndpoint }, ['Endpoint: '] ],
                                        ['input',
                                         {
                                             id: idFormEndpoint,
                                             type: 'text',
                                             name: 'endpoint',
                                             size: '30'
                                         }
                                        ]
                                    ]
                                   ],
                                   // format radio buttons
                                   ['span', { 'id': idFormFormatGrp }, [
                                        ['label', { 'for': idFormFormat }, ['Output format: '] ],
                                        ['input',
                                         {
                                             id: idFormFormat,
                                             type: 'radio',
                                             name: 'endpoint_output',
                                             value: 'xml'
                                         }
                                        ],
                                        "xml ",
                                        ['input',
                                         {
                                             id: idFormFormat,
                                             type: 'radio',
                                             name: 'endpoint_output',
                                             value: 'json'
                                         }
                                        ],
                                        "json ",
                                        ['input',
                                         {
                                             id: idFormFormat,
                                             type: 'radio',
                                             name: 'endpoint_output',
                                             value: 'jsonp'
                                         }
                                        ],
                                        "jsonp"
                                    ]
                                   ],

                                   // Chart type, dropdown.
                                   ['span', { 'id': idFormChartGrp }, [
                                        ['label', { 'for': idFormChart }, ['Chart type: '] ],
                                        ['select',
                                         {
                                             id: idFormChart,
                                             name: 'chart'
                                         }
                                        ]
                                    ]
                                   ],

                                   // Width, Height
                                   ['span', { 'id': idFormSizeGrp }, [
                                        ['label', { 'for': idFormWidth }, ['Width: '] ],
                                        ['input',
                                         {
                                             id: idFormWidth,
                                             name: 'width',
                                             type: 'text',
                                             size: '3'
                                         }
                                        ],
                                        ['label', { 'for': idFormHeight }, ['Height: '] ],
                                        ['input',
                                         {
                                             id: idFormHeight,
                                             name: 'height',
                                             type: 'text',
                                             size: '3'
                                         }
                                        ]
                                    ]
                                   ],

                                   // Buttons
                                   ['span', { 'id': idFormButtonGrp }, [
                                        ['input',
                                         {
                                             type: 'button',
                                             value: 'Reset',
                                             onclick: 'sgvizler.formReset()' // NB! must be the global function.
                                         }
                                        ],
                                        ['input',
                                         {
                                             type: 'button',
                                             value: 'Go',
                                             onclick: 'sgvizler.formSubmit()' // NB! must be the global function.
                                         }
                                        ]
                                    ]
                                   ]
                               ]
                              ]
                          ]
                         ],
                         // Logging container.
                         ['div', { id: idMessageCon } ]
                     ]
                    ],

                    /**
                     * Container for holding the chart.
                     * @property html.chart
                     * @type Array
                     * @private
                     * @since 0.6.0
                     **/
                    chart:
                        ['div',
                         {
                             id: idChartCon,
                             style: "width:800px; height:400px;"
                         }
                        ],

                    /**
                     * The footer
                     * @property html.footer
                     * @type Array
                     * @private
                     * @since 0.6.0
                     **/
                    footer:
                        ['div',
                         {
                             id: idFooter
                         },
                         [
                             ['p', null,
                              [
                                  ['a', { href: S.core.HOMEPAGE },  ['Sgvizler'] ],
                                  ' version ' + S.core.VERSION +
                                      ' (c) 2011–2013 Martin G. Skjæveland.'
                              ]
                             ]
                         ]
                        ]
                };
            }()),

            /**
             * A list of permissible URL parameters. The parameter
             * name must be in this list to be read by the form.
             * @property permissible_urlparams
             * @type Array
             * @private
             * @since 0.3.1
             **/
            permissible_urlparams = [ 'query',
                                      'endpoint',
                                      'endpoint_output',
                                      'chart',
                                      'width',
                                      'height',
                                      'ui'],

            /**
             * Tests if there really is an element with the give
             * element id.
             * @method isElement
             * @private
             * @param {String} elementID The element Id
             * @return {boolean} Returns true iff the element with
             * this element id exists.
             * @since 0.5
             **/
            isElement = function (elementID) {
                return $('#' + elementID).length > 0;
            },

            /**
             * Set a value for a given element. Is used to set the
             * value of form input fields.  Uses `jQuery.val`.
             * @method setElementValue
             * @private
             * @param {String} elementID The element id of the element to set value for.
             * @param {Primitive} value The value to set.
             * @since 0.5
             **/
            setElementValue = function (elementID, value) {
                if (isElement(elementID)) {
                    $('#' + elementID).val(value);
                }
            },

            /**
             * Set the text for a given element. Is used to set the
             * text contents of containers.  Uses `jQuery.text`.
             * @method setElementText
             * @private
             * @param {String} elementID The element id of the element to set value for.
             * @param {String} text The value to set.
             * @since 0.5
             **/
            setElementText = function (elementID, text) {
                if (isElement(elementID)) {
                    $('#' + elementID).text(text);
                }
            },
            /* UNUSED
             * Set the html content for a given element. Uses `jQuery.html`.
             * @method setElementHTML
             * @private
             * @param {String} elementID The element id of the element to set value for.
             * @param {String} html The value to set.
             * @since 0.6.0
             * setElementHTML = function (elementID, html) {
                if (isElement(elementID)) {
                    $('#' + elementID).html(html);
                }
            },
             */

            /**
             * Displays the prefixes set in `sgvizler.namespace` as
             * SPARQL prefix declarations in the designated container.
             * @method displayPrefixes
             * @private
             * @since 0.1
             **/
            displayPrefixes = function () {
                setElementText(idPrefixCon, prefixesSPARQL());
            },

            /**
             * Displays query information in the form input fields,
             * e.g., the query string, query format, chart dimensions,
             * set in the input parameter.
             * @method displayUserInput
             * @param {sgvizler.Query} query
             * @private
             * @since 0.1
             **/
            displayUserInput = function (query) {
                setElementValue(idQueryTxt, query.query());
                setElementValue(idFormEndpoint, query.endpointURL());
                $('input:radio[id=' + idFormFormat + '][value=' + query.endpointOutputFormat() + ']').attr('checked', true);
                setElementValue(idFormChart, query.chartFunction());
                setElementValue(idFormWidth, query.chartWidth());
                setElementValue(idFormHeight, query.chartHeight());
            },

            /**
             * Populates the drop-down menu of available chart types
             * with the registered chart types found in the
             * `sgvizler.registry`, grouped by modules.
             * @method displayChartTypesMenu
             * @private
             * @since 0.2
             **/
            displayChartTypesMenu = function () {
                var i, j, ilen, jlen,
                    charts = registry.chartFunctions().sort(),
                    createOptGrp = function (name) {
                        return util.createHTMLElement('optgroup', { label: name + '.*' });
                    },
                    libs = registry.chartModules(),
                    group = {},
                    added = false;

                if (isElement(idFormChart)) {
                    // Create option groups for chart function modules.
                    for (j = 0, jlen = libs.length; j < jlen; j += 1) {
                        group[libs[j]] = createOptGrp(libs[j]);
                        $('#' + idFormChart).append(group[libs[j]]);
                    }

                    for (i = 0, ilen = charts.length; i < ilen; i += 1) {
                        added = false;
                        for (j = 0, jlen = libs.length; j < jlen; j += 1) {
                            if (util.startsWith(charts[i], libs[j])) {
                                $(group[libs[j]])
                                    .append($('<option/>')
                                            .val(charts[i])
                                            .html(charts[i].replace(libs[j] + '.', '')));
                                added = true;
                            }
                        }
                        if (!added) {
                            $('#' + idFormChart).
                                append($('<option/>')
                                       .val(charts[i])
                                       .html(charts[i]));
                        }
                    }
                }
            },

            /**
             * Draws an intitially empty form on page. If elementID is
             * provided only the form and container for chart is
             * drawn; otherwise, a complete page, with header, logo
             * and footer, is draw directly in the body element.
             * @method createPage
             * @private
             * @param {String} [elementID=body]
             * @param {String} UItype values: 'result', 'form' or 'page'.
             * @since 0.6.0
             **/
            createUI = function (elementID, UItype) {
                var
                    createHTMLElements = function (elementsArray) {
                        return util.createHTMLElement.apply(undefined, elementsArray);
                    },
                    setChartContainer = function (elementID) {
                        if (elementID) {
                            idChartCon = elementID;
                        } else {
                            $('body').append(createHTMLElements(html.chart));
                        }
                    },
                    setForm = function (elementID) {
                        var main;
                        if (elementID) {
                            main = $('#' + elementID);
                        } else { // add to body.
                            main = util.createHTMLElement('div', { id: idMainCon });
                            $('body').append(
                                createHTMLElements(html.logo),
                                createHTMLElements(html.heading),
                                main,
                                createHTMLElements(html.footer)
                            );
                        }
                        main.append(
                            createHTMLElements(html.main), // container for query business.
                            createHTMLElements(html.chart) // chart container.
                        );
                    };

                if (UItype === 'result') {
                    setChartContainer(elementID);
                } else {
                    setForm(elementID);
                }
            },

            /**
             * Displays prefix information, query information and
             * selections in the form, using other `displayX` methods.
             * @method displayUI
             * @private
             * @since 0.1
             **/
            displayUI = function (query) {
                displayPrefixes();
                displayChartTypesMenu();
                displayUserInput(query);
            },

            /**
             * Parses the current URL for parameters. Permissible
             * parameters are, if present, those listed in the input
             * of this method, or in the array
             * `permissible_urlparams`.
             * @method getUrlParams
             * @param {Array} [urlparams]
             * @private
             * @return {Object} A list of parameter--value pairs.
             * @since 0.1
             **/
            getUrlParams = function (urlparams) {
                /*jslint regexp: true */
                var urlParams = {},
                    e,
                    r = /([^&=]+)=?([^&]*)/g, // parameter, value pairs.
                    d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }, // replace '+' with space.
                    q = window.location.search.substring(1), // URL query string part.
                    params = urlparams || permissible_urlparams; // set defaults if necessary.

                while ((e = r.exec(q)) !== null) {
                    if (e[2].length > 0 && util.isInArray(e[1], params)) {
                        urlParams[d(e[1])] = d(e[2]);
                    }
                }
                return urlParams;
            },

            /**
             * "Button method" used to clear the form and load default
             * values. Does this by simply reloading the page without
             * any URL parameters.
             * @method formReset
             * @public
             * @for sgvizler
             * @since 0.1
             **/
            reset = function () {
                document.location = (window.location.href).replace(window.location.search, "");
            },

            /**
             * "Button method" used to submit the form.
             * @method formSubmit
             * @public
             * @for sgvizler
             * @since 0.1
             **/
            submit = function () {
                $('#' + idFormQuery).val($('#' + idQueryTxt).val());
                $('#' + idQueryForm).submit();
            },

            /**
             * Main method. Draws the form, gets possible URL
             * parameters, populates form with data, and, if
             * requested, sends a query and draws the chart in the
             * chart container.
             * @method formDraw
             * @param {String} [elementID=body]
             * @public
             * @for sgvizler
             * @since 0.1
             **/
            draw = function (elementID) {
                var params = getUrlParams(),
                    query = new Query(
                        {
                            query: params.query,
                            chart: params.chart,
                            endpoint: params.endpoint,
                            endpoint_output: params.endpoint_output
                        },
                        {
                            width: params.width,
                            height: params.height
                        }
                    );

                createUI(elementID, params.ui);
                displayUI(query);

                if (isElement(idChartCon) && params.query) {
                    query.logContainer(idMessageCon);
                    query.draw(idChartCon);
                }
            };


        /////////////////////////////////////////////////////////////////
        // PUBLICs

        return {
            draw: draw,

            reset: reset,
            submit: submit
        };

    }());