Setup (divs and tables on page load)

Setup

Setup()

function Setup()
{
	Setup.Elements( document.getElementsByTagName( "DIV"   ) );
	Setup.Elements( document.getElementsByTagName( "FORM"  ) );
	Setup.Elements( document.getElementsByTagName( "TBODY" ) );
}
Setup.CreateTableSetupFn
=
function( id, nr_columns, clear )
{
    var path   = "";
    var search = "";

    if ( undefined === clear ) clear = false;

    return Setup.CreateTableSetupWithDownFn( id, nr_columns, path, search, clear );
}
Setup.CreateTableSetupWithDownFn
=
function( id, nr_columns, path, search, clear )
{
    if ( undefined === clear ) clear = false;

    /*
     *  The returned function parses the JSON formatted response text and creates a table row template for each result tuple.
     *  These are added to the tbody corresponding to 'id' - 'nr_of_columns' is used if no result tuples are returned.
     */

    var fn
    =
    function( responseText )
    {
        var json  = typeof responseText === 'string' || responseText instanceof String ? JSON.parse( responseText ) : responseText;
        var tbody = document.getElementById( id );

        if ( tbody && ("OK" == json.status) )
        {
            var htm  = Setup.CreateTableSetupFn.RetrieveTemplate( id );
            var htm2 = Setup.CreateTableSetupFn.RetrieveTemplate( id + "-tally" );
            var htm3 = Setup.CreateTableSetupFn.RetrieveTemplate( id + "-summary" );

            if ( ! htm )
            {
                alert( "Table '" + id + "' is missing a row template with the id: '" + id + "-template'" );
            }
            else
            {
                var n      = json.results.length;
                var offset = parseInt( tbody.getAttribute( "data-offset" ) );
                    offset = isNaN( offset ) ? 0 : offset;

                var limit  = parseInt( tbody.getAttribute( "data-limit"  ) );
                    limit  = isNaN( limit ) ? 0 : limit;

                if ( (0 == n) && (0 == offset) )
                {
                    var tr = document.createElement( "TR" );
                        tr.innerHTML = "<td colspan='" + nr_columns + "'>No entries added.</td>";

                    Setup.Clear( tbody );

                    tbody.appendChild( tr );
                }
                else
                {
                    if ( clear ) Setup.Clear( tbody );

                    if ( n != limit )
                    {
                        var load_more = document.getElementById( "tbody-load-more" );
                        if ( load_more ) load_more.style.display = "none";
                    }

                    var T = { t: null };

                    var loading = tbody.querySelector( "TR.loading" );
                    if ( loading )
                    {
                        tbody.removeChild( loading )
                    }
                    else
                    {
                        var rows = tbody.querySelectorAll( "TR" );

                        if ( 0 < rows.length )
                        {
                            var tds = rows[0].querySelectorAll( "TD" );

                            if ( (0 < tds.length) && (-1 != tds[0].innerHTML.toLowerCase().indexOf( "loading" ) ) )
                            {
                                tbody.removeChild( rows[0] );
                            }
                        } 
                    }
                    
                    for ( var i=0; i < n; i++ )
                    {
                        var e = document.createElement( "TR" );
                        var t = json.results[i];
                            t['i'] = i + 1;

                        Setup.CreateTableSetupFn.AddT( T, t );

                        if ( t.hasOwnProperty( "results_set_type" ) && ("summary" == t.results_set_type) )
                        {
                            e.innerHTML = Replace( htm3, t );
                        }
                        else
                        {
                            e.innerHTML = Replace( htm, t );

                            if ( path )
                            {
                                e.style.cursor = "pointer";
                                e.onclick      = Locations.CreateDownFn( Replace( path, t, true ), Replace( search, t, true ) );
                                e.className    = "clickable";
                            }
                        }
                        
                        if ( 0 == (i % 2) )
                        {
                            e.className += " alternate"
                        }

                        if ( "css_class" in t )
                        {
                            e.className += " " + t['css_class'];
                        }

                        tbody.appendChild( e );
                    }

                    if ( htm2 && T.t )
                    {
                        var e = document.createElement( "TR" );
                            e.innerHTML = Replace( htm2, T.t );

                        tbody.appendChild( e );
                    }
                }
            }
        }
    }
    
    return fn;
}

Setup.CreateTableSetupFn.RetrieveTemplate
=
function( id )
{
    var htm             = "";
    var row_template_id = id + "-template";
    var template_tr     = document.getElementById( row_template_id );

    if ( template_tr )
    {
        htm = template_tr.innerHTML;
    }
    
    return htm;
}

Setup.CreateTableSetupFn.RetrieveTemplateParameters
=
function( id )
{
    var parameters      = "";
    var row_template_id = id + "-template";
    var template_tr     = document.getElementById( row_template_id );

    if ( template_tr.hasAttribute( "data-parameters" ) )
    {
        parameters = template_tr.getAttribute( "data-parameters" );
    }
    
    return parameters;
}
Setup.CreateTableSetupFn.AddT
=
function( T, t )
{
    if ( null == T.t )
    {
        T.t = Setup.CreateTableSetupFn.AddT.Clone( t );

        for ( var key in T.t )
        {
            if ( isNaN( T.t[key] ) ) T.t[key] = "";
        }
    }
    else
    {
        for ( var key in T.t )
        {
            if ( !isNaN( T.t[key] ) && !isNaN( t[key] ) )
            {
                T.t[key] = parseInt( T.t[key] ) + parseInt( t[key] );
            }
        }
    }
}

Setup.CreateTableSetupFn.AddT.Clone
=
function( obj )
{
    var ret = {};

    for ( var name in obj )
    {
        var value = obj[name];
        ret[name] = obj[name];
    }

    return ret;
}
Setup.CreateTableSetupWithClickFn
=
function( id, nr_columns, click_fn )
{
    /*
     *  The returned function parses the JSON formatted response text and creates a table row template for each result tuple.
     *  These are added to the tbody corresponding to 'id' - 'nr_of_columns' is used if no result tuples are returned.
     */

    var fn
    =
    function( responseText )
    {
        var json  = JSON.parse( responseText );
        var tbody = document.getElementById( id );
        var more  = tbody.getAttribute( "data-more" );

        if ( tbody && ("OK" == json.status) )
        {
            var htm  = Setup.CreateTableSetupFn.RetrieveTemplate( id );
            var htm2 = Setup.CreateTableSetupFn.RetrieveTemplate( id + "-tally" );
            var htm3 = Setup.CreateTableSetupFn.RetrieveTemplate( id + "-summary" );

            var parameters = Setup.CreateTableSetupFn.RetrieveTemplateParameters( id );

            if ( ! htm )
            {
                alert( "Table '" + id + "' is missing a row template with the id: '" + id + "-template'" );
            }
            else
            {
                var n      = json.results.length;
                var offset = parseInt( json.offset );
                    offset = isNaN( offset ) ? 0 : offset;

                var limit  = parseInt( json.limit );
                    limit  = isNaN( limit ) ? 0 : limit;

                if ( (0 == n) && (0 == offset) )
                {
                    var tr = document.createElement( "TR" );
                        tr.innerHTML = "<td colspan='" + nr_columns + "'>No entries added.</td>";

                    Setup.Clear( tbody );

                    tbody.appendChild( tr );
                }
                else
                {
                    if ( more )
                    {
                        var count  = json.results[0].count;
                        var button = document.getElementById( more );

                        if ( button )
                        {
                            button.setAttribute( "data-limit", limit );
                            button.setAttribute( "data-offset", offset + limit );

                            if ( offset + n < count )
                            {
                                Class.RemoveClass( button, "hidden" );
                            }
                            else
                            {
                                Class.AddClass( button, "hidden" );
                            }
                        }
                    }

                    var T = { t: null };

                    var loading = tbody.querySelector( "TR.loading" );
                    if ( loading )
                    {
                        tbody.removeChild( loading )
                    }
                    else
                    {
                        var rows = tbody.querySelectorAll( "TR" );

                        if ( 0 < rows.length )
                        {
                            var tds = rows[0].querySelectorAll( "TD" );

                            if ( (0 < tds.length) && (-1 != tds[0].innerHTML.toLowerCase().indexOf( "loading" ) ) )
                            {
                                tbody.removeChild( rows[0] );
                            }
                        } 
                    }
                    
                    for ( var i=0; i < n; i++ )
                    {
                        var e = document.createElement( "TR" );
                        var t = json.results[i];
                            t['i'] = i + 1;

                        Setup.CreateTableSetupFn.AddT( T, t );

                        if ( parameters )
                        {
                            e.setAttribute( "data-parameters", Replace( parameters, t ) );
                        }

                        if ( t.hasOwnProperty( "results_set_type" ) && ("summary" == t.results_set_type) )
                        {
                            e.innerHTML = Replace( htm3, t );
                        }
                        else
                        {
                            e.innerHTML = Replace( htm, t );

                            if ( click_fn )
                            {
                                e.style.cursor = "pointer";
                                e.onclick      =  click_fn;
                                e.className    = "clickable";
                            }
                        }
                        
                        if ( 0 == (i % 2) )
                        {
                            e.className += " alternate"
                        }

                        if ( "css_class" in t )
                        {
                            e.className += " " + t['css_class'];
                        }

                        tbody.appendChild( e );
                    }

                    if ( htm2 && T.t )
                    {
                        var e = document.createElement( "TR" );
                            e.innerHTML = Replace( htm2, T.t );

                        tbody.appendChild( e );
                    }
                }
            }
        }
    }
    
    return fn;
}
Setup.CreateFormSetupFn
=
function( id, key_field )
{
    var fn
    =
    function( responseText )
    {
        InsertResponseValues( id, key_field, responseText )
    }

    return fn;
}
Setup.CreateDivSetupFn
=
function( id )
{
    var fn
    =
    function( responseText )
    {
        var div = document.getElementById( id )
        
        if ( div )
        {
            var json = typeof responseText === 'string' || responseText instanceof String ? JSON.parse( responseText ) : responseText;
            
            if ( ("OK" == json.status) && (1 == json.results.length) )
            {
                div.innerHTML = Replace( div.innerHTML, json.results[0] )
                div.style.opacity = "1.0"
            }
            else
            {
                alert( "An unexpected error occurred while retrieving data" )
            }
        }
    }
    
    return fn;
}
Setup.CreateMultiDivSetupFn
=
function( id )
{
    var fn
    =
    function( responseText )
    {
        var div  = document.getElementById( id );
        var t    = document.getElementById( id + "-template" );
        var more = div.getAttribute( "data-more" );
        var type = t.getAttribute( "data-type" );

        if ( div && t )
        {
            var json = JSON.parse( responseText )

            if ( "ERROR" == json.status )
            {
                alert( "An unexpected error occurred while retrieving data" );
            }
            else
            {
                var cls    = t.className; 
                var n      = json.results.length;
                var offset = parseInt( json.offset );
                    offset = isNaN( offset ) ? 0 : offset;

                var limit  = parseInt( json.limit );
                    limit  = isNaN( limit ) ? 0 : limit;

                if ( (0 == n) && (0 == offset) )
                {
                    // Ignore for now.
                }
                else
                {
                    if ( more )
                    {
                        var count  = json.results[0].count;
                        var button = document.getElementById( more );

                        if ( button )
                        {
                            button.setAttribute( "data-limit", limit );
                            button.setAttribute( "data-offset", offset + limit );

                            if ( offset + n < count )
                            {
                                Class.RemoveClass( button, "hidden" );
                            }
                            else
                            {
                                Class.AddClass( button, "hidden" );
                            }
                        }
                    }

                    for ( var i=0; i < n; i++ )
                    {
                        var type            = type ? type : "DIV";
                        var child           = document.createElement( type );
                            child.className = cls;
                            child.innerHTML = Replace( t.innerHTML, json.results[i] );

                        div.appendChild( child );
                    }
                }
            }
        }
    }
    
    return fn;
}
Setup.CreateFormHandlerFn
=
function( id, handler, parameter )
{
    var fn
    =
    function( responseText )
    {
        if ( null === responseText )
        {
            setTimeout( function() { handler( parameter ) }, 1000 );
            //handler( parameter );
        }
        else
        {
            var json = JSON.parse( responseText );

            if ( json && ("ERROR" == json.status) )
            {
                alert( json.error );
            }
            else
            {
                handler( parameter );
            }
        }
    }
    
    return fn;
}
Setup.More
=
function( event )
{
    var button    = event.target;
    var target_id = button.getAttribute( "data-target" );
    var target    = document.getElementById( target_id );

    if ( !target )
    {
        alert( "Error, could not find target for Setup.More" );
    }
    else
    {
        var offset   = button.getAttribute( "data-offset"    );
        var endpoint = target.getAttribute( "data-setup-url" );

        var parameters        = Locations.SearchValues();
            parameters.offset = offset;

        Call( endpoint, parameters, target.setup );
    }

    return false;
}

Helper functions

Setup.Elements
=
function( elements )
{
	var n = elements.length;
	
	for ( var i=0; i < n; i++ )
	{
		var element    = elements[i];
		var parameters = GetSearchValues();
        var parameters = Setup.AddSelectCookies( parameters );

		Setup.Element( element, parameters );
	}
}

Setup.Element
=
function( element, parameters )
{
	if ( element && element.hasAttribute( "data-setup-url" ) )
	{
		var url        = element.getAttribute( "data-setup-url" );
		var handler    = Setup.DefaultHandler;

		if ( element.hasOwnProperty( "setup" ) )
		{
			handler = element.setup;

			handler = handler ? handler : element.handler;
		}

		if ( !parameters.target_id && element.hasAttribute( "id" ) )
		{
			parameters.target_id = element.getAttribute( "id" );
		}

		Call( Resolve() + url, parameters, handler );
	}
}

Setup.DefaultHandler
=
function( responseText )
{
	var json = JSON.parse( responseText );
	
	if ( "OK" != json.status )
	{
		console.log( responseText );
	}
}

Setup.AddSelectCookies
=
function( parameters )
{
    var selects = document.getElementsByTagName( "SELECT" );
    var n       = selects.length;

    for ( var i=0; i < n; i++ )
    {
        var s = selects[i];

        if ( true == s.hasAttribute( "data-cookie" ) )
        {
            var name  = s.name;
            var value = GetCookie( name );

            parameters[name] = value;

            if ( ! s.hasAttribute( "data-value" ) )
            {
                s.setAttribute( "data-value", value );
            }
        }
    }

    return parameters;
}
Setup.Clear
=
function( container )
{
    //  Need to remove from back to maintain
    //  order of children.

    var n = container.children.length - 1;
    
    for ( var i = n; 0 <= i; i-- )
    {
        var child = container.children[i];

        switch ( child.tagName )
        {
        case "DIV":
        case "TR":
            if ( -1 == child.id.toLowerCase().indexOf( "template" ) )
            {
                container.removeChild( child );
            }
            break;
        }
    }
}