884 lines
36 KiB
JavaScript
884 lines
36 KiB
JavaScript
/*
|
|
$Revision$
|
|
$Id$
|
|
|
|
File: console.js
|
|
|
|
Description: Generic include file for consoles for Facilitor
|
|
|
|
|
|
*/
|
|
|
|
var targets = {},
|
|
models = {},
|
|
day_in_ms = 86400000,
|
|
language = "EN",
|
|
windowObjectReference,
|
|
environment = "production";
|
|
|
|
/* System constants */
|
|
var dataTables_i18n = {
|
|
NL: {
|
|
"sProcessing": "Bezig...",
|
|
"sLengthMenu": "_MENU_ resultaten weergeven",
|
|
"sZeroRecords": "Geen resultaten gevonden",
|
|
"sInfo": "_START_ tot _END_ van _TOTAL_ resultaten",
|
|
"sInfoEmpty": "Geen resultaten om weer te geven",
|
|
"sInfoFiltered": " (gefilterd uit _MAX_ resultaten)",
|
|
"sInfoPostFix": "",
|
|
"sSearch": "Zoeken:",
|
|
"sEmptyTable": "Geen resultaten aanwezig in de tabel",
|
|
"sInfoThousands": ".",
|
|
"sLoadingRecords": "Een moment geduld aub - bezig met laden...",
|
|
"oPaginate": {
|
|
"sFirst": "Eerste",
|
|
"sLast": "Laatste",
|
|
"sNext": "Volgende",
|
|
"sPrevious": "Vorige"
|
|
},
|
|
"oAria": {
|
|
"sSortAscending": ": activeer om kolom oplopend te sorteren",
|
|
"sSortDescending": ": activeer om kolom aflopend te sorteren"
|
|
}
|
|
},
|
|
DE: {
|
|
"sEmptyTable": "Keine Daten in der Tabelle vorhanden",
|
|
"sInfo": "_START_ bis _END_ von _TOTAL_ Einträgen",
|
|
"sInfoEmpty": "Keine Daten vorhanden",
|
|
"sInfoFiltered": "(gefiltert von _MAX_ Einträgen)",
|
|
"sInfoPostFix": "",
|
|
"sInfoThousands": ".",
|
|
"sLengthMenu": "_MENU_ Einträge anzeigen",
|
|
"sLoadingRecords": "Wird geladen ..",
|
|
"sProcessing": "Bitte warten ..",
|
|
"sSearch": "Suchen",
|
|
"sZeroRecords": "Keine Einträge vorhanden",
|
|
"oPaginate": {
|
|
"sFirst": "Erste",
|
|
"sPrevious": "Zurück",
|
|
"sNext": "Nächste",
|
|
"sLast": "Letzte"
|
|
},
|
|
"oAria": {
|
|
"sSortAscending": ": aktivieren, um Spalte aufsteigend zu sortieren",
|
|
"sSortDescending": ": aktivieren, um Spalte absteigend zu sortieren"
|
|
},
|
|
"select": {
|
|
"rows": {
|
|
"_": "%d Zeilen ausgewählt",
|
|
"0": "",
|
|
"1": "1 Zeile ausgewählt"
|
|
}
|
|
},
|
|
"buttons": {
|
|
"print": "Drucken",
|
|
"colvis": "Spalten",
|
|
"copy": "Kopieren",
|
|
"copyTitle": "In Zwischenablage kopieren",
|
|
"copyKeys": "Taste <i>ctrl</i> oder <i>\u2318</i> + <i>C</i> um Tabelle<br>in Zwischenspeicher zu kopieren.<br><br>Um abzubrechen die Nachricht anklicken oder Escape drücken.",
|
|
"copySuccess": {
|
|
"_": "%d Zeilen kopiert",
|
|
"1": "1 Zeile kopiert"
|
|
},
|
|
"pageLength": {
|
|
"-1": "Zeige alle Zeilen",
|
|
"_": "Zeige %d Zeilen"
|
|
}
|
|
}
|
|
},
|
|
EN: {
|
|
"sEmptyTable": "No data available in table",
|
|
"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
|
|
"sInfoEmpty": "Showing 0 to 0 of 0 entries",
|
|
"sInfoFiltered": "(filtered from _MAX_ total entries)",
|
|
"sInfoPostFix": "",
|
|
"sInfoThousands": ",",
|
|
"sLengthMenu": "Show _MENU_ entries",
|
|
"sLoadingRecords": "Loading...",
|
|
"sProcessing": "Processing...",
|
|
"sSearch": "Search:",
|
|
"sZeroRecords": "No matching records found",
|
|
"oPaginate": {
|
|
"sFirst": "First",
|
|
"sLast": "Last",
|
|
"sNext": "Next",
|
|
"sPrevious": "Previous"
|
|
},
|
|
"oAria": {
|
|
"sSortAscending": ": activate to sort column ascending",
|
|
"sSortDescending": ": activate to sort column descending"
|
|
}
|
|
},
|
|
FR: {
|
|
"sEmptyTable": "Aucune donnée disponible dans le tableau",
|
|
"sInfo": "Affichage de l'élément _START_ à _END_ sur _TOTAL_ éléments",
|
|
"sInfoEmpty": "Affichage de l'élément 0 à 0 sur 0 élément",
|
|
"sInfoFiltered": "(filtré à partir de _MAX_ éléments au total)",
|
|
"sInfoPostFix": "",
|
|
"sInfoThousands": ",",
|
|
"sLengthMenu": "Afficher _MENU_ éléments",
|
|
"sLoadingRecords": "Chargement...",
|
|
"sProcessing": "Traitement...",
|
|
"sSearch": "Rechercher :",
|
|
"sZeroRecords": "Aucun élément correspondant trouvé",
|
|
"oPaginate": {
|
|
"sFirst": "Premier",
|
|
"sLast": "Dernier",
|
|
"sNext": "Suivant",
|
|
"sPrevious": "Précédent"
|
|
},
|
|
"oAria": {
|
|
"sSortAscending": ": activer pour trier la colonne par ordre croissant",
|
|
"sSortDescending": ": activer pour trier la colonne par ordre décroissant"
|
|
},
|
|
"select": {
|
|
"rows": {
|
|
"_": "%d lignes sélectionnées",
|
|
"0": "Aucune ligne sélectionnée",
|
|
"1": "1 ligne sélectionnée"
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/* global functions */
|
|
// console messages for development support
|
|
window.console.original_log = window.console.log;
|
|
window.console.log = function (msg, force) {
|
|
if (environment == "development" || force) {
|
|
window.console.original_log(msg);
|
|
}
|
|
};
|
|
// return the data of a single object or of a row object (e.g. obj.data["issue"] or obj.data["issues"][row])
|
|
function rowInfo(obj, row) {
|
|
"use strict";
|
|
return (obj.single ? obj.data[obj.table] : obj.data[obj.table][row]);
|
|
}
|
|
|
|
// return the value of a column
|
|
function dataInfo(obj, row, column) {
|
|
"use strict";
|
|
return rowInfo(obj, row)[column];
|
|
}
|
|
|
|
// return a formatted column value according to the column_type
|
|
function typeFormat(parms) {
|
|
"use strict";
|
|
switch (parms.column_type) {
|
|
case "datetime":
|
|
if (parms.single) {
|
|
// return the datevalue in case of a single object column
|
|
return new Date(parms.value);
|
|
}
|
|
return new Intl.DateTimeFormat(undefined, {
|
|
dateStyle: 'medium',
|
|
timeStyle: 'short',
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
}).format(new Date(parms.value));
|
|
// niet na een return break;
|
|
case "date":
|
|
if (parms.single) {
|
|
// return the datevalue in case of a single object column
|
|
return new Date(parms.value);
|
|
}
|
|
return new Intl.DateTimeFormat(undefined, {
|
|
dateStyle: 'medium'
|
|
}).format(new Date(parms.value));
|
|
// niet na een return break;
|
|
case "integer":
|
|
return parseInt(parms.value, 10);
|
|
// niet na een return break;
|
|
case "number":
|
|
// return safe number
|
|
return $.fn.dataTable.render.number().display(parms.value);
|
|
// niet na een return break;
|
|
default:
|
|
// return safe text
|
|
return $.fn.dataTable.render.text().display(parms.value);
|
|
}
|
|
}
|
|
|
|
// return label of the column
|
|
function columnType(obj, column) {
|
|
"use strict";
|
|
// determine column_type from [ targets[target].columns[column].type ] or from [ models[model].field[column].type ] or from fallback value "text"
|
|
return (obj.columns[column].type || (models[obj.url].fields[column] && models[obj.url].fields[column].type) || "text");
|
|
}
|
|
|
|
// return label of the column
|
|
function columnLabel(obj, column) {
|
|
"use strict";
|
|
// determine label from [ models[model].field[column].label ] or else from [ target.columns[column].label ] or else from [ column name ]
|
|
return ((models[obj.url].fields[column] && models[obj.url].fields[column].label) || obj.columns[column].label || column);
|
|
}
|
|
|
|
// return value of the column (single value or [column].name value)
|
|
function columnValue(data) {
|
|
"use strict";
|
|
// determine whether the value is an object with a { name: value }
|
|
return (data && typeof data.name !== "undefined" ? data.name || "" : data || "");
|
|
}
|
|
|
|
// return the formatted column value, independent of single object or row object
|
|
function dataFormat(obj, row, column) {
|
|
"use strict";
|
|
// get column value (as single value or as { id: xx, name: yy })
|
|
var data = dataInfo(obj, row, column);
|
|
return typeFormat({
|
|
value: columnValue(data),
|
|
column_type: columnType(obj, column),
|
|
single: obj.single
|
|
});
|
|
}
|
|
|
|
// return combined server-data and targets[target]/models[model][column] information object
|
|
function columnInfo(obj, row, column) {
|
|
"use strict";
|
|
var data, column_label, column_data, column_type, column_valuemin, column_valuemax, column_recid;
|
|
// get column value (as single value or as { id: xx, name: yy })
|
|
data = dataInfo(obj, row, column);
|
|
// get column label
|
|
column_label = columnLabel(obj, column);
|
|
// get formatted column value
|
|
column_data = dataFormat(obj, row, column);
|
|
// get column_type
|
|
column_type = columnType(obj, column);
|
|
// determine minimum value (only for use in a progressbar)
|
|
column_valuemin = (obj.columns[column].valuemin || 0);
|
|
// determine maximum value (only for use in a progressbar)
|
|
column_valuemax = (obj.columns[column].valuemax || 100);
|
|
// determine record id in case the column is a foreign table value
|
|
column_recid = (data && typeof data.id !== "undefined" ? parseInt(data.id, 10) : false);
|
|
return {
|
|
data: data,
|
|
column_label: column_label,
|
|
column_data: column_data,
|
|
column_type: column_type,
|
|
column_valuemin: column_valuemin,
|
|
column_valuemax: column_valuemax,
|
|
column_recid: column_recid
|
|
};
|
|
}
|
|
|
|
// return the column [ data-order ] value, used for ordering DataTable rows ([ date ] or [ datetime ] serial number only)
|
|
function dataOrder(obj, row, column) {
|
|
"use strict";
|
|
var column_type = columnType(obj, column),
|
|
value, data = dataInfo(obj, row, column);
|
|
if (obj.single) {
|
|
value = "";
|
|
} else {
|
|
value = columnValue(data);
|
|
}
|
|
switch (column_type) {
|
|
case "datetime":
|
|
case "date":
|
|
return new Date(value).getTime();
|
|
// niet na een return break;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// return DataTable settings based on targets[target]columns
|
|
function tColumnDefs(obj) {
|
|
"use strict";
|
|
var defs = {
|
|
language: dataTables_i18n[language],
|
|
columnDefs: []
|
|
},
|
|
index = 0;
|
|
$.each(obj.columns, function (key, value) {
|
|
if (key !== "id") {
|
|
if (value.hidden) {
|
|
defs.columnDefs.push({
|
|
targets: [index],
|
|
visible: false,
|
|
searchable: true
|
|
});
|
|
}
|
|
index++;
|
|
}
|
|
});
|
|
console.log(defs);
|
|
return defs;
|
|
}
|
|
|
|
// return tableHeader row
|
|
function theadColumns(obj) {
|
|
"use strict";
|
|
var thead = "",
|
|
column;
|
|
for (column in obj.columns) {
|
|
if (column !== "id") {
|
|
thead += '<th>' + $.fn.dataTable.render.text().display(columnLabel(obj, column)) + '</th>';
|
|
}
|
|
}
|
|
return thead;
|
|
}
|
|
|
|
// return tableBody rows
|
|
function tbodyData(obj) {
|
|
"use strict";
|
|
var tbody = "",
|
|
row, column, order, col_info;
|
|
for (row = 0; row < obj.data[obj.table].length; row += 1) {
|
|
tbody += '<tr recid=' + obj.data[obj.table][row].id + '>';
|
|
for (column in obj.columns) {
|
|
if (column !== "id") {
|
|
col_info = columnInfo(obj, row, column);
|
|
tbody += '<td name="' + column + '"' +
|
|
(col_info.column_recid ? 'recid="' + col_info.column_recid + '"' : '') +
|
|
((order = dataOrder(obj, row, column)) ? 'data-order="' + order + '"' : '') +
|
|
'>' +
|
|
col_info.column_data +
|
|
'</td>';
|
|
}
|
|
}
|
|
tbody += '</tr>';
|
|
}
|
|
return tbody;
|
|
}
|
|
|
|
// return formdata (single record form)
|
|
function formData(obj) {
|
|
"use strict";
|
|
var target_selector = targets[obj.target].selector;
|
|
var formbody = "",
|
|
column, column_id, col_info;
|
|
for (column in obj.columns) {
|
|
if (column !== "id" && !(targets[obj.target].columns[column].hidden || false)) {
|
|
column_id = target_selector + "-" + column;
|
|
col_info = columnInfo(obj, undefined, column);
|
|
col_info.column_id = column_id;
|
|
col_info.single = obj.single;
|
|
formbody +=
|
|
'<div class="form-group form-group-sm pb-0 mb-0 form-row">' +
|
|
'<label for="' + column_id + '" class="col-sm-4 col-form-label text-nowrap">' + col_info.column_label + '</label>' +
|
|
new Field(col_info).render() +
|
|
'</div>';
|
|
}
|
|
}
|
|
return formbody;
|
|
}
|
|
|
|
// return filterdata (buttons for filtering DataTable data)
|
|
function filterData(obj) {
|
|
"use strict";
|
|
// var container_selector = targets[obj.target].selector;
|
|
var formbody = "",
|
|
row, column, col_info,
|
|
btn_size_class = targets[obj.target].btn_size_class,
|
|
btn_has_icon = targets[obj.target].btn_has_icon,
|
|
icon_column = targets[obj.target].icon_column,
|
|
color_column = targets[obj.target].color_column,
|
|
icon;
|
|
for (row = 0; row < obj.data[obj.table].length; row += 1) {
|
|
if (icon_column && !!obj.data[obj.table][row][icon_column] && obj.data[obj.table][row][icon_column].substring(0, 3) == "fa-") {
|
|
icon = obj.data[obj.table][row][icon_column];
|
|
} else {
|
|
icon = "fa-tag";
|
|
}
|
|
formbody += '<button type="button" class="btn text-center ' + btn_size_class + ' ' + settings.btn_text_class + ' ' + settings.btn_class + '" recid=' + obj.data[obj.table][row].id + (color_column && !!obj.data[obj.table][row][color_column] ? ' color="' + obj.data[obj.table][row][color_column].split(";")[0] + '"' : "") + '>' +
|
|
'<div class="">' + (btn_has_icon ? '<i class="fa ' + icon + ' fa-lg"></i>' : "") + '</div>';
|
|
for (column in obj.columns) {
|
|
if (column !== "id") {
|
|
col_info = columnInfo(obj, row, column);
|
|
formbody += '<div class="' + (targets[obj.target].columns[column].hidden ? "" : "d-inline-block text-truncate") + '" name="' + column + '"' +
|
|
((targets[obj.target].columns[column].hidden || false) ? "hidden" : '') +
|
|
(col_info.column_recid ? ' recid=' + col_info.column_recid : '') + '>' +
|
|
"<small>" +
|
|
((targets[obj.target].columns[column].hidden || false) ? '' : col_info.column_data) +
|
|
'</small></div>';
|
|
}
|
|
}
|
|
formbody += '<div name="badge"></div>';
|
|
formbody += '</button>';
|
|
}
|
|
return formbody;
|
|
}
|
|
|
|
// populate the target (datatable, form or filter)
|
|
function populate(obj) {
|
|
"use strict";
|
|
// the model needs to be present (loaded) for correct workings, except for reports (graphs)
|
|
if (targets[obj.target].report || models[obj.url].id) {
|
|
var $this = $("#" + targets[obj.target].selector),
|
|
h2;
|
|
obj.columns = obj.columns || targets[obj.target].columns;
|
|
console.log("populate: " + obj.target);
|
|
obj.table = obj.single || obj.url;
|
|
h2 = '<h2 name="formtitle">' + (lcl[language][targets[obj.target].title] || obj.table) + '</h2>';
|
|
obj.single = obj.single || false;
|
|
// render single record form html
|
|
if (obj.single) {
|
|
var fdata = formData(obj);
|
|
$this.html(h2 + '<form id="' + targets[obj.target].selector + '-form">' + fdata + '</form>' + new Customfields(obj).render());
|
|
// render buttons from rows for filter form html
|
|
} else if (targets[obj.target].filter) {
|
|
var fdata = filterData(obj);
|
|
$this.html(h2 + '<form id="' + targets[obj.target].selector + '-form" class="form-inline">' + fdata + '</form>');
|
|
// render h2 header only for report
|
|
} else if (targets[obj.target].report) {
|
|
$this.html(h2);
|
|
// render table html
|
|
} else {
|
|
var $this, thead, tbody, table;
|
|
thead = '<thead class="thead-dark">' + theadColumns(obj) + '</thead>';
|
|
tbody = '<tbody>' + tbodyData(obj) + '</tbody>';
|
|
table = '<table class="table table-sm table-striped table-hover" name="' + obj.target + '">' + thead + tbody + '</table>';
|
|
$this.html(h2 + table);
|
|
}
|
|
// set trigger(s) if available
|
|
if (targets[obj.target].trigger) {
|
|
$(targets[obj.target].trigger_selector, $this).off().on(targets[obj.target].events, targets[obj.target].trigger);
|
|
}
|
|
// run ready function if available
|
|
if (targets[obj.target].ready) {
|
|
targets[obj.target].ready(obj);
|
|
}
|
|
} else {
|
|
console.log("model " + obj.url + "not yet present!");
|
|
// retry the populate until the model is present
|
|
setTimeout(function () {
|
|
populate(obj);
|
|
}, 100);
|
|
}
|
|
}
|
|
|
|
// save the model definition in models
|
|
function setModel(obj) {
|
|
"use strict";
|
|
if (obj.model) {
|
|
models[obj.model] = obj.data;
|
|
obj.data.fields.forEach(function (field) {
|
|
models[obj.model].fields[field.id] = field;
|
|
});
|
|
}
|
|
}
|
|
|
|
// get api2 data through ajax
|
|
function api2(obj) {
|
|
"use strict";
|
|
if (obj.target) {
|
|
obj.filter = (Object.keys(targets[obj.target].columns).length ? (obj.filter ? obj.filter + "&" : "?") + "fields=" + Object.keys(targets[obj.target].columns).join(",") : obj.filter || "");
|
|
}
|
|
var ajaxHdl = $.ajax({
|
|
url: settings.facilitor_url + "api2/" + obj.url + (obj.filter || ""),
|
|
dataType: "json",
|
|
success: function (data, textStatus, jqXHR) {
|
|
console.log("Ajax success start: " + (obj.target || obj.model));
|
|
obj.data = data;
|
|
if (obj.model) {
|
|
setModel(obj);
|
|
} else {
|
|
populate(obj);
|
|
}
|
|
console.log(data);
|
|
console.log("Ajax success stop: " + (obj.target || obj.model));
|
|
},
|
|
complete: function (jqXHR, textStatus) {
|
|
console.log("Ajax complete: " + (obj.target || obj.model));
|
|
}
|
|
});
|
|
console.log({
|
|
target: (obj.target || "model_" + obj.model),
|
|
ajaxHdl: ajaxHdl
|
|
});
|
|
}
|
|
|
|
// google maps initialisation
|
|
var map, marker, geocoder, panorama, selector;
|
|
|
|
// google maps interface to set a location and a marker
|
|
function codeAddress(address) {
|
|
"use strict";
|
|
geocoder.geocode({
|
|
'address': address
|
|
}, function (results, status) {
|
|
if (status == 'OK') {
|
|
map.setCenter(results[0].geometry.location);
|
|
marker = new google.maps.Marker({
|
|
map: map,
|
|
position: results[0].geometry.location
|
|
});
|
|
panorama.setPosition(results[0].geometry.location);
|
|
panorama.addListener('position_changed', function () {
|
|
if (!panorama.getVisible()) {
|
|
panorama.setVisible(true);
|
|
}
|
|
});
|
|
$("#" + selector).closest(".row").attr("hidden", false);
|
|
} else {
|
|
alert('Geocode was not successful for the following reason: ' + status);
|
|
}
|
|
});
|
|
}
|
|
|
|
// google maps initialisation and first location set to Facilitor
|
|
function initAutocomplete(mapselector, viewselector, location) {
|
|
"use strict";
|
|
selector = mapselector;
|
|
// The location of Facilitor
|
|
var facilitor = location || {
|
|
lat: 52.216670,
|
|
lng: 6.946060
|
|
};
|
|
// map part
|
|
map = new google.maps.Map(
|
|
document.getElementById(mapselector), {
|
|
zoom: 13,
|
|
center: facilitor,
|
|
mapTypeId: 'roadmap'
|
|
});
|
|
marker = new google.maps.Marker({
|
|
map: map,
|
|
position: facilitor
|
|
});
|
|
// streetview part
|
|
panorama = new google.maps.StreetViewPanorama(
|
|
document.getElementById(viewselector), {
|
|
position: facilitor,
|
|
panControl: false,
|
|
addressControl: false,
|
|
pov: {
|
|
heading: 34,
|
|
pitch: 20
|
|
}
|
|
});
|
|
map.setStreetView(panorama);
|
|
geocoder = geocoder || new google.maps.Geocoder();
|
|
$("#" + mapselector).closest(".row").attr("hidden", !location);
|
|
}
|
|
|
|
/* settings and functions from refactoring of targets object */
|
|
var settings = {
|
|
facilitor_url: "../../",
|
|
btn_class: "btn-secundary",
|
|
btn_text_class: "text-dark",
|
|
btn_selected_class: "btn-success",
|
|
btn_partial_class: "btn-success",
|
|
btn_size_class: "col-sm-3",
|
|
btn_has_icon: true,
|
|
icon_column: false,
|
|
color_column: false
|
|
};
|
|
// set partial, full or no class on parent button dependent on the number of selected child buttons
|
|
function setParentSelectedClass(parms) {
|
|
"use strict";
|
|
var selected = $("button:visible." + settings.btn_selected_class + " div[name=" + parms.name + "][recid=" + parms.value + "]", parms.context).length;
|
|
var present = $("button:visible div[name=" + parms.name + "][recid=" + parms.value + "]", parms.context).length;
|
|
// reset classes to default
|
|
var button = $("button[recid=" + parms.value + "]", parms.parent)
|
|
.removeClass(settings.btn_selected_class + ' ' + settings.btn_partial_class)
|
|
.addClass(settings.btn_class + ' ' + settings.btn_text_class)
|
|
.css({
|
|
backgroundColor: ""
|
|
});
|
|
// all childs are selected
|
|
if (present == selected) {
|
|
button
|
|
.addClass(settings.btn_selected_class)
|
|
.removeClass(settings.btn_class + ' ' + settings.btn_text_class)
|
|
.css({
|
|
backgroundColor: (button.attr("color") ? button.attr("color") : "")
|
|
});
|
|
// part of the childs are selected
|
|
} else if (selected > 0) {
|
|
button
|
|
.addClass(settings.btn_selected_class + ' ' + settings.btn_partial_class)
|
|
.removeClass(settings.btn_class + ' ' + settings.btn_text_class)
|
|
.css({
|
|
backgroundColor: (button.attr("color") ? button.attr("color") : "")
|
|
});
|
|
}
|
|
return button;
|
|
}
|
|
// set full or no class on child buttons dependent on the parent button
|
|
function setChildSelectedClass(parms) {
|
|
"use strict";
|
|
var button;
|
|
var items = $("button div[name=" + parms.name + "][recid=" + parms.$this.attr("recid") + "]", parms.parent);
|
|
items
|
|
.each(
|
|
function () {
|
|
button = $(this).closest("button");
|
|
button
|
|
.removeClass(settings.btn_partial_class)
|
|
.toggleClass(settings.btn_selected_class, parms.$this.hasClass(settings.btn_selected_class))
|
|
.toggleClass(settings.btn_class, !parms.$this.hasClass(settings.btn_selected_class))
|
|
.toggleClass(settings.btn_text_class, !parms.$this.hasClass(settings.btn_selected_class))
|
|
.css({
|
|
backgroundColor: (button.attr("color") && button.hasClass(settings.btn_selected_class) ? button.attr("color") : "")
|
|
});
|
|
}
|
|
);
|
|
return items;
|
|
}
|
|
// set color of child-buttons to color of parent-button when a child-button has no specific color of it's own
|
|
function setChildrenColor(parms) {
|
|
"use strict";
|
|
var $this, parent;
|
|
var items = $("button:not([color]) div[name=" + parms.name + "]", parms.context);
|
|
items
|
|
.each(
|
|
function () {
|
|
$this = $(this);
|
|
// parent button has a specific colour
|
|
parent = $("button[recid=" + $this.attr("recid") + "]", parms.parent);
|
|
if (parent.length) {
|
|
$this.closest("button")
|
|
.attr("color", parent.attr("color"))
|
|
.css({
|
|
backgroundColor: parent.attr("color")
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
// save recid's of selected buttons in [ context ]
|
|
function saveSelectedbuttonIds(parms) {
|
|
"use strict";
|
|
targets[parms.target].selected_ids = [];
|
|
$("button." + settings.btn_selected_class, parms.context).each(function () {
|
|
targets[parms.target].selected_ids.push($(this).attr("recid"));
|
|
});
|
|
}
|
|
// save recid's used in table
|
|
function saveUsedtabledataIds(parms) {
|
|
"use strict";
|
|
var index, recid, key_count = {};
|
|
targets[parms.target].selected_ids = [];
|
|
$("td[name=" + parms.name + "]", parms.context).each(function () {
|
|
recid = $(this).attr("recid");
|
|
key_count[recid] = key_count[recid] ? key_count[recid] + 1 : 1;
|
|
index = targets[parms.target].selected_ids.indexOf(recid);
|
|
if (index === -1) {
|
|
targets[parms.target].selected_ids.push(recid);
|
|
}
|
|
});
|
|
return key_count;
|
|
}
|
|
// set classes for button dependent on button_selected_class
|
|
function setButtonClasses(parms) {
|
|
"use strict";
|
|
parms.$this.removeClass(settings.btn_selected_class == settings.btn_partial_class ? "" : settings.btn_partial_class)
|
|
.toggleClass(settings.btn_selected_class)
|
|
.toggleClass(settings.btn_class, !parms.$this.hasClass(settings.btn_selected_class))
|
|
.toggleClass(settings.btn_text_class, !parms.$this.hasClass(settings.btn_selected_class))
|
|
.css({
|
|
backgroundColor: (parms.$this.attr("color") && parms.$this.hasClass(settings.btn_selected_class) ? parms.$this.attr("color") : "")
|
|
});
|
|
}
|
|
// reset classes for all buttons
|
|
function resetAllButtonClasses(parms) {
|
|
"use strict";
|
|
$("button", parms.context)
|
|
.removeClass(settings.btn_partial_class + ' ' + settings.btn_selected_class)
|
|
.addClass(settings.btn_class + ' ' + settings.btn_text_class)
|
|
.css({
|
|
backgroundColor: ""
|
|
});
|
|
}
|
|
// set hidden attr for buttons dependent on button_selected_class
|
|
function setButtonHidden(parms) {
|
|
"use strict";
|
|
$("button", parms.context)
|
|
.attr("hidden", function () {
|
|
$(this).attr("hidden", !$(this).hasClass(settings.btn_selected_class))
|
|
});
|
|
}
|
|
// autoselect first row in case there is only 1 result
|
|
function autoselectRow(parms) {
|
|
"use strict";
|
|
// select (click) the first row if there is only 1 result
|
|
if ($("tbody tr", "#" + targets[parms.target].selector).length == 1) {
|
|
$("tbody tr:first", "#" + targets[parms.target].selector).click();
|
|
}
|
|
}
|
|
// redraw the table and select first row in case there is only 1 result
|
|
function redrawTable(parms) {
|
|
"use strict";
|
|
targets[parms.target].data_table.draw();
|
|
$("#" + targets[parms.target].selector).closest("div.card").resize();
|
|
autoselectRow(parms);
|
|
}
|
|
// resize innerHeight of target-card to innerHeight of base-card
|
|
function resizeCard(targetselector, baseselector) {
|
|
function _resizeCard() {
|
|
console.log("resize " + targetselector);
|
|
$("#" + targetselector).closest("div.card").innerHeight($("#" + baseselector).closest("div.card").innerHeight());
|
|
}
|
|
return function _setTimeout() {
|
|
setTimeout(_resizeCard, 100);
|
|
}
|
|
}
|
|
|
|
/* Objects to be used for rendering dashboards */
|
|
|
|
// Object with render function to return field html (without label)
|
|
function Field(parms) {
|
|
"use strict";
|
|
var self = this,
|
|
date, time;
|
|
// prefix a string with a zero when string length < length to be used ( hour/minute/day/month fields )
|
|
var prefixZero = function (str, len) {
|
|
return ("0" + str).slice(-len);
|
|
};
|
|
this.single = parms.single;
|
|
this.column_name = parms.column_name;
|
|
this.column_type = parms.column_type;
|
|
this.column_id = parms.column_id;
|
|
this.column_data = typeFormat({
|
|
value: (parms.column_data || ""),
|
|
column_type: parms.column_type,
|
|
single: parms.single
|
|
});
|
|
this.column_valuemin = parms.column_valuemin;
|
|
this.column_valuemax = parms.column_valuemax;
|
|
this.render = function () {
|
|
switch (self.column_type) {
|
|
case "progressbar":
|
|
return '<div class="col-sm-8 progress" style="height: 2rem;">' +
|
|
'<div class="progress-bar progress-bar-info form-control form-control-sm" role="progressbar" id="' + self.column_id + '" style="width: ' + Math.round(1 / self.column_valuemax * self.column_data * 100) + '%;" aria-valuenow="' + self.column_data + '" aria-valuemin="' + self.column_valuemin + '" aria-valuemax="' + self.column_valuemax + '"></div>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
case "check":
|
|
return '<div class="form-check">' +
|
|
'<input type="checkbox" class="form-control form-control-sm form-check-input" id="' + self.column_id + '" name=' + self.column_name + (self.column_data == 1 ? ' checked' : '') + ' disabled>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
case "textarea":
|
|
return '<div class="col-sm-8">' +
|
|
'<textarea class="sm-textarea form-control form-control-sm" id="' + self.column_id + '" readonly>' + self.column_data + '</textarea>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
case "date":
|
|
date = self.column_data == "" ? "" : self.column_data.getFullYear().toString() + "-" + prefixZero((self.column_data.getMonth() + 1).toString(), 2) + "-" + prefixZero(self.column_data.getDate().toString(), 2);
|
|
return '<div class="col-sm-8">' +
|
|
'<input type="date" class="form-control form-control-sm" id="' + self.column_id + '" name=' + self.column_name + '" value="' + date + '" readonly>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
case "datetime":
|
|
time = self.column_data == "" ? "" : prefixZero(self.column_data.getHours().toString(), 2) + ":" + prefixZero(self.column_data.getMinutes().toString(), 2);
|
|
date = self.column_data == "" ? "" : self.column_data.getFullYear().toString() + "-" + prefixZero((self.column_data.getMonth() + 1).toString(), 2) + "-" + prefixZero(self.column_data.getDate().toString(), 2);
|
|
return '<div class="col-sm-5">' +
|
|
'<input type="date" class="form-control form-control-sm" id="' + self.column_id + '" name=' + self.column_name + '" value="' + date + '" readonly>' +
|
|
'</div>' +
|
|
'<div class="col-sm-3">' +
|
|
'<input type="time" class="form-control form-control-sm" id="' + self.column_id + '_time" name=' + self.column_name + '_time" value="' + time + '" readonly>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
case "time":
|
|
time = self.column_data == "" ? "" : prefixZero(self.column_data.getHours().toString(), 2) + ":" + prefixZero(self.column_data.getMinutes().toString(), 2);
|
|
return '<div class="col-sm-3">' +
|
|
'<input type="time" class="form-control form-control-sm" id="' + self.column_id + '_time" name=' + self.column_name + '_time" value="' + time + '" readonly>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
default:
|
|
return '<div class="col-sm-8">' +
|
|
'<input type="' + self.column_type + '" class="form-control form-control-sm" id="' + self.column_id + '" name=' + self.column_name + '" value="' + self.column_data + '" readonly>' +
|
|
'</div>';
|
|
// niet na een return break;
|
|
}
|
|
}
|
|
console.log(self);
|
|
}
|
|
|
|
// Object with render function to return label and customfield html
|
|
function Customfield(parms) {
|
|
"use strict";
|
|
var self = this;
|
|
this.single = parms.single;
|
|
this.column_name = parms.column_name;
|
|
this.custom_field = parms.custom_field;
|
|
this.selector = parms.selector;
|
|
this.column_id = parms.selector + "-" + self.custom_field.propertyid;
|
|
// translate customfield-type to model field-type
|
|
this.custom_field_type = function () {
|
|
switch (self.custom_field.type) {
|
|
case "V":
|
|
return "check";
|
|
case "D":
|
|
return "date";
|
|
case "T":
|
|
return "time";
|
|
case "N":
|
|
return "number";
|
|
default:
|
|
return "text";
|
|
}
|
|
}
|
|
this.render = function () {
|
|
return '<div class="form-group form-group-sm pb-0 mb-0 form-row">' +
|
|
'<label for="' + self.column_id + '" class="col-sm-4 col-form-label text-nowrap">' + self.custom_field.label + '</label>' +
|
|
new Field({
|
|
single: self.single,
|
|
column_name: self.column_name,
|
|
column_id: self.column_id,
|
|
column_type: self.custom_field_type(),
|
|
column_data: self.custom_field.value
|
|
}).render() +
|
|
'</div>';
|
|
}
|
|
console.log(self);
|
|
}
|
|
|
|
// Object with render function to return html for all customfields including labels
|
|
function Customfields(parms) {
|
|
"use strict";
|
|
var self = this;
|
|
// sort customfields on sequence
|
|
this.custom_fields = (parms.data[parms.table].custom_fields ? parms.data[parms.table].custom_fields.sort(function (a, b) {
|
|
return (a.sequence > b.sequence ? 1 : -1)
|
|
}) : []);
|
|
this.single = parms.single;
|
|
this.target = parms.target;
|
|
this.table = parms.table;
|
|
this.render = function () {
|
|
var fields = "",
|
|
custom_field;
|
|
if (targets[self.target].show_custom_fields && self.custom_fields.length) {
|
|
for (custom_field in self.custom_fields) {
|
|
// only customfields other than type Q, L or M
|
|
if (["Q", "L", "M"].indexOf(self.custom_fields[custom_field].type) == -1 && (targets[self.target].show_custom_field_when_empty || self.custom_fields[custom_field].value != null)) {
|
|
fields += new Customfield({
|
|
single: self.single,
|
|
column_name: custom_field,
|
|
selector: targets[self.target].selector,
|
|
custom_field: self.custom_fields[custom_field]
|
|
}).render();
|
|
}
|
|
}
|
|
}
|
|
return '<div name="custom-fields">' + fields + '</div>';
|
|
}
|
|
console.log(self);
|
|
}
|
|
|
|
// Object base for targets
|
|
function Target(parms) {
|
|
"use strict";
|
|
var self = this;
|
|
var choose = function (first_choice, fallback_choice) {
|
|
return (typeof first_choice != "undefined" ? first_choice : fallback_choice);
|
|
};
|
|
this.title = parms.title || "";
|
|
this.selector = parms.selector;
|
|
this.mode = parms.mode;
|
|
this.columns = choose(parms.columns, {});
|
|
this.events = choose(parms.events, "click");
|
|
this.trigger = parms.trigger || false;
|
|
this.ready = parms.ready || false;
|
|
this.filter = parms.filter || false;
|
|
this.report = parms.report || false;
|
|
this.trigger_selector = (this.filter ? "button" : "table tbody tr");
|
|
this.btn_size_class = choose(parms.btn_size_class, settings.btn_size_class);
|
|
this.btn_has_icon = choose(parms.btn_has_icon, true);
|
|
this.icon_column = choose(parms.icon_column, settings.icon_column);
|
|
this.color_column = choose(parms.color_column, settings.color_column);
|
|
this.show_custom_fields = parms.show_custom_fields || false;
|
|
this.show_custom_field_when_empty = parms.show_custom_field_when_empty || false;
|
|
console.log(self);
|
|
} |