/*
$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 ctrl oder \u2318 + C um Tabelle in Zwischenspeicher zu kopieren.
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 += '
';
obj.single = obj.single || false;
// render single record form html
if (obj.single) {
var fdata = formData(obj);
$this.html(h2 + '' + 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 + '');
// 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 = '' + theadColumns(obj) + '';
tbody = '' + tbodyData(obj) + '';
table = '
' + thead + tbody + '
';
$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 '
' +
'' +
'
';
// niet na een return break;
case "check":
return '
' +
'' +
'
';
// niet na een return break;
case "textarea":
return '
' +
'' +
'
';
// 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 '
' +
'' +
'
';
// 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 '
' +
'' +
'
' +
'
' +
'' +
'
';
// 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 '
' +
'' +
'
';
// niet na een return break;
default:
return '
' +
'' +
'
';
// 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 '
';
}
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 '