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.All
=
function()
{
Selects.CallSetup = true;
Selects( APIServer );
}
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'];
}
Setup.URIEncodeContainedLinks( e );
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'];
}
Setup.URIEncodeContainedLinks( e );
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"
Setup.URIEncodeContainedLinks( div );
}
else
{
alert( "An unexpected error occurred while retrieving data" )
}
}
}
return fn;
}
Setup.CreateMultiDivSetupFn
=
function( id, click_fn )
{
var fn
=
function( responseText )
{
var div = document.getElementById( id );
var t = document.getElementById( id + "-template" );
var et = document.getElementById( id + "-empty-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 )
{
if ( et )
{
var type = type ? type : "DIV";
var child = document.createElement( type );
child.className = cls;
child.innerHTML = et.innerHTML;
div.appendChild( child );
}
}
else
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] );
if ( click_fn )
{
child.style.cursor = "pointer";
child.onclick = click_fn;
}
Setup.URIEncodeContainedLinks( child );
div.appendChild( child );
}
}
}
}
}
return fn;
}
Setup.CreateFormHandlerFn
=
function( id, handler, parameter )
{
var fn
=
function( responseText )
{
if ( ! responseText )
{
setTimeout( function() { handler( parameter ) }, 1000 );
}
else
{
var response = JSON.parse( responseText );
if ( response && ("ERROR" == response.status) )
{
alert( response.error );
}
else
{
if ( 1 == response.results.length )
{
Setup.CreateFormHandlerFn.UpdateSearchVariables( response.results[0] );
}
handler( parameter );
}
}
}
return fn;
}
Setup.CreateFormHandlerFn.UpdateSearchVariables
=
function( tuple )
{
var parameters = Locations.SearchValues();
var n = parameters.length;
for (const [key, value] of Object.entries(parameters))
{
if ( tuple.hasOwnProperty( key ) )
{
parameters[key] = tuple[key];
}
}
var search = "?" + Call.EncodeToString( parameters );
window.history.replaceState( null, null, search );
}
Setup.CreateFormFinalFn
= function( form_id, key, handler )
{
var fn
=
function( responseText )
{
var url = document.getElementById( form_id ).getAttribute( "data-final-url" );
var response = JSON.parse( responseText );
if ( "ERROR" == response.status )
{
alert( response.error );
}
else
if ( !url )
{
alert( "Missing --data-final-url for form with id: " + form_id );
}
else
if ( response.results && response.results[0] )
{
var first = response.results[0];
var parameters = {};
parameters[key] = first[key];
Call( url, parameters, null );
window.setTimeout( handler, 1000 );
}
}
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_orig )
{
if ( element && element.hasAttribute( "data-setup-url" ) && !element.hasAttribute( "data-skip-setup" ) )
{
var url = element.getAttribute( "data-setup-url" );
var handler = Setup.DefaultHandler;
var parameters = { ...parameters_orig };
if ( element.hasAttribute( "data-parameter-names" ) )
{
var names = element.getAttribute( "data-parameter-names" ).split( "," );
var n = names.length;
for ( var i=0; i < n; i++ )
{
var name = names[i];
var value = DataStorage.Local.GetUserItem( name );
if ( !value )
{
value = DataStorage.Session.GetItem( name );
}
parameters[name] = value;
}
}
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( url, parameters, handler );
}
else
if ( element && ("FORM" == element.tagName) )
{
var fakeResponseText = '{"status":"OK","results":[{}]}';
InsertResponseValues( element.id, null, fakeResponseText );
}
}
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 );
}
}
else
if ( true == s.hasAttribute( "data-local" ) )
{
var select = s;
var path = location.pathname;
var name = select.name;
var key = name + "|" + path;
if ( Session.user_hash )
{
key = Session.user_hash + "|" + name + "|" + path;
}
if ( DataStorage.Local.HasItem( key ) )
{
var value = DataStorage.Local.GetItem( key )
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;
}
}
}
Setup.Download
=
function( event )
{
var link = event.target;
var id = link.id;
var converter_fn = link.converter;
var type = link.getAttribute( "data-content-type" );
var url = link.getAttribute( "data-download-url" );
var name = link.getAttribute( "data-download-name" );
var params = link.hasAttribute( "data-download-parameters" )
? GetSearchValues.CreateDictionary( link.getAttribute( "data-download-parameters" ) )
: Locations.SearchValues();
event.preventDefault();
params.submit = name ? name : "";
params.target_id = id;
link.removeEventListener( 'click', Setup.Download );
link.onclick = null;
Call
(
url,
params,
Setup.CreateDownloadLinkFn( type, converter_fn )
);
}
Setup.CreateDownloadLinkFn
=
function( type, converter_fn )
{
var fn
=
function( responseText )
{
var response = JSON.parse( responseText );
if ( "ERROR" == response.status )
{
alert( response.error );
}
else
{
var target_id = response.target_id;
var name = response.submit;
const blob = new Blob
(
converter_fn( type, response ),
{ type: type }
);
const url = URL.createObjectURL(blob);
var a = document.getElementById( target_id );
a.href = url;
if ( name )
{
a.download = name;
}
a.click();
}
}
return fn;
}
Setup.URIEncodeContainedLinks
=
function( e )
{
var links = e.getElementsByTagName( "A" );
var n = links.length;
for ( var i=0; i < n; i++ )
{
var bits = links[i].href.split( "?" );
if ( 2 == bits.length )
{
var href = bits[0] + "?";
var parameters = GetSearchValues.CreateDictionary( bits[1] );
var sep = "";
for ( key in parameters )
{
href += sep + key + "=" + encodeURIComponent( parameters[key] );
sep = "&";
}
links[i].href = href;
}
}
}
Setup.CreateMultiFormSetupFn
=
function( form_id, primary_key )
{
var fn
=
function( responseText )
{
Setup.CreateFormSetupFn( form_id, primary_key )( responseText );
var response = JSON.parse( responseText );
if ( "OK" == response.status )
{
var form = document.getElementById( form_id );
var divs = form.querySelectorAll( "DIV.multiselect" );
var n = divs.length;
for ( var i=0; i < n; i++ )
{
Setup.CreateMultiFormSetupFn.Populate( form, divs[i] );
}
}
}
return fn;
}
Setup.CreateMultiFormSetupFn.Populate
=
function( form, div )
{
var hidden_input_id = div.getAttribute ( "data-hidden-input-id" );
var hidden_input = form.querySelector( "INPUT#" + hidden_input_id );
var div_id = div.id;
var values_string = hidden_input.value.substring( 1, hidden_input.value.length - 1 );
var list = values_string.split( "][" );
var n = list.length;
for ( var i=0; i < n; i++ )
{
var key_value = list[i];
var bits = key_value.split( "=" );
if ( 2 == bits.length )
{
var value = bits[0];
var text = bits[1];
var span = div.querySelector( "SPAN[data-value='" + value + "']" );
if ( !span )
{
var span = document.createElement( "SPAN" );
span.innerText = text;
span.onclick = AddToMulti.Remove;
span.setAttribute( "data-value", value );
div.appendChild( span );
}
}
}
}