Files
Facilitor/APPL/Shared/resultset_table_v2.inc
Erik Groener cfddeb8830 YAXX#86411 Kenmerken op regio niveau ondersteunen
svn path=/Website/trunk/; revision=67617
2025-01-16 10:11:14 +00:00

2546 lines
98 KiB
PHP
Raw Blame History

<% /*
File: shared/resultset_table_v2.inc
$Revision$
$Id$
*/
%>
<!-- #include file="resultset_filter_table.inc" -->
<!-- #include file="resultset_flex.inc" -->
<!-- #include file="iface.inc" -->
<!-- #include file="../api/api.inc" -->
<!-- #include file="../Shared/rs_columns.inc" -->
<%
FCLTHeader.Requires({ plugins: ["jQuery"],
js: ["resultset_table_v2.js", "sorttable.js"]
});
var APIname = getQParam("API","");
var useHamburger = S("inline_actions_hamburger");
if (getQParam("touch","") == 1 || device.test(device.isTouch))
useHamburger = 1; // Hamburger onClick
var hasInlineActions = false;
var book_id = null;
if (APIname == "REPORT")
{
var API = new API_func();
book_id = getQParam("BOOKMARK");
var sql = "SELECT fac_bookmark_path, "
+ " fac_bookmark_query"
+ " FROM fac_bookmark"
+ " WHERE fac_bookmark_id = " + safe.quoted_sql(book_id);
var oRs = Oracle.Execute(sql);
if (oRs.EOF)
{
Response.Write("Bookmark niet gevonden");
Response.End;
}
var path = oRs("fac_bookmark_path").Value;
var query = oRs("fac_bookmark_query").Value;
oRs.Close();
if (rooturl + path != Request.ServerVariables("SCRIPT_NAME"))
{
shared.internal_error("Invalid bookmark path");
}
//
// getQParam/getFParam onderscheppen en 'voeden' uit FAC_BOOKMARK_URL
//
// Simuleer een Request.Querystring compatible collection
function bmcoll(key)
{
var nn = 1;
var coll = Server.CreateObject("Scripting.Dictionary");
var params = query.split("&");
for (var i in params)
{
var xx = params[i].split("=");
if (xx[0].toUpperCase() == key.toUpperCase() && xx.length > 1)
{
coll.Add(nn++, unescape(String(xx[1]).replace(/\+/g, " "))); // spaties gaan niet vanzelf
}
}
return coll;
}
getQParam = function (pName, defVal)
{
return _get_Param(bmcoll, pName, defVal)
}
getQParamInt = function (pName, defVal)
{
return _get_ParamInt(bmcoll, pName, defVal)
}
getQParamDate = function (pName, defVal)
{
return _get_ParamDate(bmcoll, pName, defVal)
}
}
var p_autosortby = getQParam('autosortby', "") || getFParam('autosortby', "");
var autosortbyrev = false;
if (p_autosortby.substr(0,1) == '-')
{
var autosortbyrev = true;
p_autosortby = p_autosortby.substr(1);
}
// <form> printform is nodig bij printen reserveringen i.v.m. POST formulier
// maar <form> mag niet binnen een ander <form> voorkomen en moet eigenlijk wel binnen body staan
// Formulier als tekstring samenstellen en m.b.v. $(function(){}) binnen de body zetten (resultset_table_v2.js)
var postformHTML = '';
if (Request.ServerVariables("REQUEST_METHOD") == "POST")
{
var postformHTML = '<div id=\"postform\">'
+ '<form id=\"printform\" name=\"printform\" target=\"_blank\" rel=\"noopener noreferrer\" method=\"post\">'
+ '<input type=\"hidden\" id=\"outputmode\" name=\"outputmode\" value=\"0\">' // input outputmode wordt gezet in doOutput()
+ '<input type=\"hidden\" id=\"autosortby\" name=\"autosortby\" value=\"0\">' // input autosortby wordt gezet in doOutput()
+ '<input type=\"hidden\" id=\"showall\" name=\"showall\" value=\"1\">';
var items = new Enumerator(Request.Form());
while (!items.atEnd())
{
var itemName = items.item();
for (var i = 1; i <= Request.Form(itemName).count; i++)
{ // De input velden outputmode en showall zijn standaard al gedefinieerd. Niet dubbel defini<6E>ren
// Een eventuele submit ook niet doorgeven tijdens afdruk.
if (itemName != "outputmode" && itemName != "showall" && itemName != "do_submit")
postformHTML += '<input type=\"hidden\" name=\"' + safe.htmlattr(itemName)
+ '\" value=\"' + safe.htmlattr(Request.Form(itemName)(i)) + '\">';
}
items.moveNext();
}
postformHTML += '</form>'
+ '</div>';
}
var isPlain = false;
var isPrinting = false;
var isExcel = false;
var isCSV = false;
var isCSV2XLSX = false;
var isZIP = false;
var isGraph = false;
function ResultsetTable(params)
{
this.beforeEachRow = null;
this.rowClass = null;
this.rowData = null;
this.newHeader = null;
this.emptySetString = L("lcl_empty_rstable");
this.sql = null;
this.sqltotals = null;
this.dataset = null;
this.filter = "";
this.filterParams = null;
this.ID = null;
this.flexModule = null;
this.flexId = null;
this.flexGroupId = null;
this.flexParentGroupId = null;
this.flexChangeNiveau = null;
this.flexParams = null;
this.rowNum = 0;
this.keyColumn = null;
this.dblClick = null;
this.disableInlineActions = null;
this.rowActionEnabler = null;
this.multiActionEnabler = null;
this.inlineDetails = null;
this.hasInlineDetails = null;
this.inlineDetailsChanged = null;
this.summaryCalc = null;
this.summaryShow = null;
this.totalColumnText = null;
this.totalCalc = null;
this.totalShow = null;
this.summaryId = null;
this.noPrint = null; /* if true: suppress print/excel icons */
this.noExcel = null; /* if true: suppress excel icon */
this.outputmode = null; // print naar: 0 = screen, 1 = printer met flex, 2 = excel met flex, 3 = XML/XSL, 4 = CSV,
// 5 = printer zonder flex, 6 = excel zonder flex., 7 = zipfile met bijlagen
this.endText = null;
this.showAll = null;
this.showProperties = null;
this.propertiesColumn = null; // alleen nog maar in gebruik voor FIN flexkenmerken detailregels
this.addurl = null;
this.suppressKeyRepeat = null;
this.inline = null;
this.lastColKey = -1; // voor suppress (columns)
this.urllink = null;
this.subtabicon = null;
this.rstCheckboxes = null;
// multiple resultsets
this.rstableCount = 1;
this.rstableNr = 1;
this.buildHistogram = false; // over *alle* kolommen van de sql! Originele waarden!
this.Counter = {};
this.noSetSummary = false;
var param;
// Neem alle meegegeven parameters mee.
for (param in params)
this[param] = params[param];
isPlain = ((this.outputmode || 0) == 0);
isPrinting = (this.outputmode == 1 || this.outputmode == 5);
isExcel = ((this.outputmode == 2 || this.outputmode == 6) && S("excel_mode")==0);
isNativeExcel = ((this.outputmode == 2 || this.outputmode == 6 || this.outputmode == 8) && S("excel_mode")==2);
isXMLXSL = (this.outputmode == 3);
isCSV = ((this.outputmode == 4) || (((this.outputmode == 2 || this.outputmode == 6) && S("excel_mode")==1)));
//isCSV2XLSX = (this.outputmode == 8)
isZIP = (this.outputmode == 7);
isGraph = getQParam("asgraph", 0) == 1;
this.printFlex = (this.outputmode == 1 || this.outputmode == 2 || this.showProperties) && this.flexModule != null && this.flexId != null;
this.tableClassName = "rstable"
+ ("nofloating" in params && params.nofloating ? " no-floating" : "")
+ (!isExcel ? " sortable" : "");
if (isPrinting || isExcel)
{
this.inlineDetails = null;
this.hasInlineDetails = null;
this.inlineDetailsChanged = null;
}
this.columns = new Array();
this.actions = new Array();
this.lastVal = new Array(); // voor suppress (columns)
if (this.inline || isExcel)
{
this.noPrint = true; // Geen printer fuctionaliteit
this.noSetSummary = true; // Geen summary zetten in de titelbalk
this.noLoading = true; // Geen loading
}
}
ResultsetTable.prototype.processResultset = __rsProcessResultset;
ResultsetTable.prototype.startTable = __rsStartTable;
ResultsetTable.prototype.makeTableHeader = __rsMakeTableHeader;
ResultsetTable.prototype.makeTableRow = __rsMakeTableRow;
ResultsetTable.prototype.makeTableFootnote = __rsMakeTableFootnote;
ResultsetTable.prototype.endTable = __rsEndTable;
ResultsetTable.prototype.addColumn = __rsAddColumn;
ResultsetTable.prototype.startPrint = __rsStartPrint;
ResultsetTable.prototype.endPrint = __rsEndPrint;
ResultsetTable.prototype.addAction = __rsAddAction;
ResultsetTable.prototype.rowFilter = function (oRs) { return true };
function __rsAddAction(params)
{
/* Nu ook inline actions bij PDA (hamburger)
if (device.test(device.isTouch) && !params.isDefault) {
params.single = false; // touch heeft geen mouseover. Dan alleen de default onclick
}
*/
this.actions.push(params);
};
// JGL: O.a. UWVA smoelenboek
ResultsetTable.prototype.ProcessAsXMLXSL = function()
{
var xmlDoc = new ActiveXObject("MSXML2.DOMDocument.6.0");
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"windows-1252\""))
// MGE: De encoding komt niet in de xml te staan, maar alleen de version: < ?xml version="1.0"? >. MSXML print nooit de encoding.
// Kan dit problemen geven?
var FCLTElement = xmlDoc.createElement("facilitor");
var FCLTHeader = xmlDoc.createElement("header");
var param;
var info = { //ID: this.ID,
file: String(Request.ServerVariables("SCRIPT_NAME")).toLowerCase(),
dateTime: toDateTimeString(new Date(), true),
dateDay: (new Date).getDate(),
dateMonth: (new Date).getMonth()+1,
dateYear: (new Date).getFullYear(),
user: customerId,
rapportmode: getQParam("rapportmode", null), // internal abuse only
custId: customerId,
language: user.lang()
// ....
}
for (param in info)
{
if (info[param] != null)
{
var FCLTdata = xmlDoc.createElement(param);
FCLTdata.appendChild(xmlDoc.createTextNode(info[param]));
FCLTHeader.appendChild(FCLTdata);
}
}
FCLTElement.appendChild(FCLTHeader);
var rootElement = xmlDoc.createElement("resultset");
rootElement.setAttribute("id", this.ID);
with(this)
{
var oRs = Oracle.Execute(sql);
var theSqlFlex = "";
if (this.printFlex)
theSqlFlex = getSqlFlex(flexModule.toUpperCase(), flexId, this.myRs(flexParams, oRs));
for (var cnt = 0; !oRs.EOF; cnt++)
{
// Vooralsnog geen flex
var elementRecord = xmlDoc.createElement("data_row");
for (var i = 0; i < columns.length; i++)
{
var fieldname;
if (columns[i].orgContent instanceof Function)
{
fieldname = columns[i].orgContent.toString().match(/function\s*(\w*)/)[1];
if (!fieldname)
fieldname = columns[i].xmltag; // Bij anonieme contentfunctie moet je xmltag toevoegen
if (!fieldname)
INTERNAL_ERROR_MISSING_XMLTAG;
}
else
{
fieldname = columns[i].orgContent;
}
var elementField = xmlDoc.createElement(fieldname.toLowerCase() /*"field"*/);
try
{
var val = (columns[i].content != null ? columns[i].content(oRs, outputmode) : "");
}
catch (e)
{
__Log("resultset_table_v2.inc: Probleem met het ophalen van columns[" + i + "]: " + columns[i].caption);
throw(e);
}
var elementFieldText = xmlDoc.createTextNode(val);
elementField.appendChild(elementFieldText);
elementRecord.appendChild(elementField);
}
if (this.printFlex)
{
var flexKey = (!oRs.Fields(flexId).Value ? oRs.Fields("id").Value : oRs.Fields(flexId).Value); // primary key van tabel uit recordset of id uit dataset van api2-model
completeSqlFlex = "SELECT * FROM (" + theSqlFlex + ")"
+ " WHERE flexparentkey = " + flexKey // De flexKey invullen in de sqlFlex query
+ " ORDER BY volgnummer, omschrijving";
var oRsFlex = Oracle.Execute(completeSqlFlex);
while (!oRsFlex.EOF)
{
if (oRsFlex("waarde").Value)
{
var elementField = xmlDoc.createElement("kenmerk");
//completeSqlFlex bevat (helaas nog) geen "kenmerk_key"
var info = ["omschrijving", "kenmerktype", "nmin", "nmax", "volgnummer", "dimensie", "decimalen"];
for (var param in info)
{
if (oRsFlex(info[param]).Value)
elementField.setAttribute(info[param], oRsFlex(info[param]).Value);
}
var elementFieldText = xmlDoc.createTextNode(flexValue(oRsFlex));
elementField.appendChild(elementFieldText);
elementRecord.appendChild(elementField);
}
oRsFlex.MoveNext();
}
oRsFlex.Close();
}
rootElement.appendChild(elementRecord);
oRs.MoveNext();
}
oRs.close();
FCLTElement.appendChild(rootElement);
xmlDoc.appendChild(FCLTElement);
Response.ContentType = "text/xml";
Response.Clear();
if (__Logging & 1)
{
var in_file = shared.tempFolder() + "/";
in_file = in_file + customerId + this.ID + ".xml";
var fs = Server.CreateObject("Scripting.FileSystemObject");
var ts = fs.CreateTextFile(in_file, true);
ts.WriteLine (xmlDoc.xml);
ts.Close();
}
Response.ContentType = "text/html";
var xslfile = Server.MapPath(getCustXsl()); // FSN#39809
var xslt = new ActiveXObject("Msxml2.XSLTemplate.6.0");
var xsldoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0");
var xslproc;
xsldoc.async = false;
xsldoc.setProperty("AllowXsltScript", true);
xsldoc.load(xslfile);
xsldoc.resolveExternals = true; // XSL kan includes hebben
xsldoc.validateOnParse = true; // en moet correct zijn
xslt.stylesheet = xsldoc;
xslproc = xslt.createProcessor();
xslproc.input = xmlDoc;
//xslproc.addParameter("mode", mode);
//xslproc.addParameter("srtnotificatiecode", srtnotificatie);
xslproc.output = Response;
xslproc.transform();
Response.End;
}
}
ResultsetTable.prototype.ProcessAsCSV = function _ProcessAsCSV()
{
var oRs;
if (this.pRs)
oRs = this.pRs;
else if (this.dataset)
oRs = new data_recordset( this.dataset );
else
oRs = Oracle.Execute(this.sql);
// Header row
var safeheader = [];
for (var i = 0; i < this.columns.length; i++)
safeheader.push(this.columns[i].caption);
if (isCSV2XLSX) // dan maken een CSV bestand in de TEMP folder en leveren een JSON op
{
var fso = new ActiveXObject("Scripting.FileSystemObject")
var tmpcsv = "CSV_" + shared.random(16) +".csv"
var uitvoerstream = fso.CreateTextFile(shared.tempFolder() + "/" + tmpcsv, true);
Session.LCID = 1033; // English(United States) omdat csv2xlsx_386.exe dat verwacht voor floating points
}
else
{
var uitvoerstream = Response;
}
Response.Clear(); // ook voor csv
uitvoerstream.Write(safeheader.join(";") + "\r\n");
while (!oRs.EOF)
{
var saferow = [];
for (var i = 0; i < this.columns.length; i++)
{
try
{
var val = this.columns[i].content(oRs, this.outputmode);
}
catch (e)
{
__Log("resultset_table_v2.inc: Probleem met het ophalen van columns[" + i + "]: " + this.columns[i].caption);
throw(e);
}
saferow.push(safe.csv(val));
}
uitvoerstream.Write(saferow.join(";") + "\r\n");
oRs.MoveNext();
}
oRs.close();
if (isCSV2XLSX)
{
uitvoerstream.Close();
Response.ContentType = "application/json";
var result = {
"tmpcsv" : tmpcsv,
"columns" : this.columns,
"colspec" : [] // voor csv2xlsx
};
for (var i = 0; i < this.columns.length; i++)
{
// Type is one of: text|number|integer|currency|date|standard|percent|formula|format
var csvtype = "standard";
switch (this.columns[i].datatype)
{
// let op: format truc werkt alleen voor numbers (waar parseFloat op toegepast kan worden)
case "date" : csvtype = "date"; break; // kan dit beter? format:"d-m-jjjj" of zo?
case "datetime": csvtype = "date"; break; // kan dit beter? format:"d-m-jjjj uu:mm" of zo?
case "time" : csvtype = "standard"; break; // kan dit beter? format:"uu:mm" of zo?
case "currency": csvtype = "format:###0.00"; break;
case "float" : csvtype = "number"; break;
case "number" : csvtype = "integer"; break;
case "html" : return val;
}
result.colspec.push(String(i) + ":" + csvtype);
}
Response.Write(JSON.stringify(result));
}
else
{
Response.ContentType = "text/csv";
}
ASPPAGE_END();
Response.End;
}
ResultsetTable.prototype.excelTableHeader = function _excelTableHeader(oWs, row, oRs, oRsFlexData)
{
var maxlengths = [];
for (var i = 0; i < this.columns.length; i++)
{
var caption = this.columns[i].caption;
caption = caption.replace(/(<([^>]+)>)/ig,""); // strip html
caption = caption.replace(/\&nbsp\;/ig, " ");// &nbsp; naar spatie
var len = oWs.write_string(row, i, caption, 1); // 1 = bold
maxlengths.push(len);
oWs.set_column_width(i, 8.43 /* LXW_DEF_COL_WIDTH */, 1); // Forceer alvast 'wrap' omdat met constant memory het niet achteraf kan
}
if (this.printFlex)
{
for (var i_f=0; i_f < oRsFlexData.length; i_f++)
{
var caption = oRsFlexData[i_f].header;
var len = oWs.write_string(row, i + i_f, caption, 1); // 1 = bold
maxlengths.push(len);
}
}
return maxlengths;
}
ResultsetTable.prototype.ProcessAsNativeExcel = function _ProcessAsNativeExcel(formail)
{
Response.Clear(); // voor de zekerheid
var oRs;
if (this.pRs)
oRs = this.pRs;
else if (this.dataset)
oRs = new data_recordset( this.dataset );
else
oRs = Oracle.Execute(this.sql);
var oExcel = new ActiveXObject("SLNKXLSX.Excel");
var tmpxlsx = "XLSX_" + shared.random(16) +".xlsx"
var oWb = oExcel.workbook_new(shared.tempFolder() + "/" + tmpxlsx, 1); // 1==constant memory
oWb.set_property("author", user.naam());
oWb.set_property("title", this.title);
oWb.set_property("comments", "Created with Facilitor v{0}".format(FCLTVersion));
var oWs = oWb.add_worksheet("Sheet1");
var printedFirstHeader = false; // Is de eerste header afgedrukt?. Bij isExcel en isPrinting worden namelijk meerdere headers afgedrukt
var printMoreHeaders = false; // Wordt gebruikt bij isExcel en isPrinting om meerdere headers af te drukken, maar dan moet de flexModule en flexId wel gedefineerd zijn
// Alleen headers weergeven bij printen naar printer of excel
// en indien de flexkenmerkquery, flexid en flexgroupid is meegegeven
if (this.printFlex && this.flexGroupId)
printMoreHeaders = true;
var lastFlexGroupKey = -1; // Wordt gebruikt bij isExcel. Start without a previous flex group, the first one is new.
var lastFlexParentGroupKey = -1 // Wordt gebruikt bij isExcel. Start without a previous flex group, the first one is new.
var flexGroupChanged = false;
var theSqlFlex = "";
if (this.printFlex)
theSqlFlex = getSqlFlex(this.flexModule.toUpperCase(), this.flexId, (this.flexParams instanceof Function ? this.flexParams(oRs) : this.flexParams));
var lastHadFlex = false;
oWs.freeze_panes(1, 0);
// 1e Header row respecteren we maxlength's ook van.
var maxlengths = [];
// Ik wil altijd de originele waardes hebben. Binnen Excel is toch alles 'safe'
safe.html = safe.htmlattr = function (waarde, params)
{
return waarde || "";
}
safe.curr = function (waarde, params)
{
return waarde;
}
var rownum = 0;
while (!oRs.EOF)
{
if (!this.rowFilter(oRs)) // Vanuit MJOB en fin
{
oRs.MoveNext();
continue;
}
var oRsFlex = null;
if (this.printFlex)
{
var flexKey = (!oRs.Fields(this.flexId).Value ? oRs.Fields("id").Value : oRs.Fields(this.flexId).Value); // primary key van tabel uit recordset of id uit dataset van api2-model
var oRsFlexData = getFlexData(theSqlFlex, flexKey, { showProperties: this.showProperties }); // is een JSON
if (!oRsFlexData.length)
var noFlexResult = true; // Er zijn geen flexkenmerken
else
var noFlexResult = false; // Er zijn flexkenmerken
if (this.flexGroupId) // Is er een flexGroupId meegegeven
{
var flexGroupKey = this.myRs(this.flexGroupId, oRs);
flexGroupChanged = (lastFlexGroupKey != flexGroupKey); // Alleen bij printen naar excel moet er wellicht een nieuwe header boven i.v.m. andere flexkenmerken
var flexChanged = flexGroupChanged;
lastFlexGroupKey = flexGroupKey;
if (this.flexParentGroupId) // Is er een flexParentGroupId meegegeven
{
var flexParentGroupKey = this.myRs(this.flexParentGroupId, oRs);
flexParentGroupChanged = (lastFlexParentGroupKey != flexParentGroupKey); // Alleen bij printen naar excel moet er wellicht een nieuwe header boven i.v.m. andere flexkenmerken
if (!flexParentGroupChanged && flexGroupChanged && this.flexChangeNiveau && !noFlexResult && !flexChanged)
{ // Flexgroep is veranderd maar parentflexgroep niet. Alleen als er op flexgroep niveau flexkenmerken zijn gedefinieerd is er een nieuwe header nodig.
flexChanged = false;
for (var datai=0; i < oRsFlexData.length; i++)
{
var rec = oRsFlexData[datai];
var kenmerk_niveau = rec.niveau;
if (kenmerk_niveau == this.flexChangeNiveau)
{
flexChanged = true;
break;
}
}
}
flexChanged = flexParentGroupChanged || flexChanged; // Als parent group veranderd is zijn er waarchijnlijk ook andere kenmerken. Kan voor meldingen nog scherper i.v.m. nog een niveau (parent) hoger. Maar is in praktijk nog niet echt nodig.
lastFlexParentGroupKey = flexParentGroupKey;
}
}
}
if (!printedFirstHeader || (printMoreHeaders && flexChanged && (!noFlexResult || (lastHadFlex && noFlexResult))))
{
// Header van ResultsetTable
var ml = this.excelTableHeader(oWs, rownum++, oRs, oRsFlexData);
if (rownum == 1)
maxlengths = ml;
printedFirstHeader = true;
}
lastHadFlex = !noFlexResult;
var saferow = [];
for (var i = 0; i < this.columns.length; i++)
{
try
{
if (this.columns[i].orgContent instanceof Function)
{
var val = this.columns[i].orgContent(oRs, this.outputmode)
}
else
{
var val = oRs.Fields(this.columns[i].orgContent).Value;
}
}
catch (e)
{
__Log("resultset_table_v2.inc: Probleem met het ophalen van columns[" + i + "]: " + this.columns[i].caption);
throw(e);
}
// Zie ook api2_rest.inc function _json2xlsx
if (val != null && typeof val != "undefined")
{
if (typeof val == "object" && "name" in val)
{
val = val["name"];
this.columns[i].datatype = null; // default string
}
if (typeof val == "string" && (this.columns[i].orgContent instanceof Function || this.columns[i].datatype == 'html'))
{
val = val.replace(/(<([^>]+)>)/ig,""); // strip html
val = val.replace(/\&nbsp\;/ig, " ");// &nbsp; naar spatie;
val = val.replace(/\&amp;\;/ig, "&");// er zijn er nog meer maar dit vind ik genoeg
val = val.replace(/\&lt\;/ig, "<");
val = val.replace(/\&gt\;/ig, ">");
val = val.replace(/\&apos\;/ig, "'>'");
val = val.replace(/\&quot\;/ig, "\"");
// TODO: andere html-entities ook vertalen?
}
var len = 0;
if (typeof val == "string" && inArray(this.columns[i].datatype, ["date", "datetime", "time", "currency", "float", "number"]))
{
if (!(this.columns[i].orgContent instanceof Function))
__Log("Vreemd: kolom {0} is string en niet van het type {1}?".format(this.columns[i].caption, this.columns[i].datatype), "#ff0000");
len = oWs.write_string(rownum, i, val);
}
else
switch (this.columns[i].datatype)
{
case "date" : oWs.write_vardate(rownum, i, new Date(val).getVarDate(), 0); //TODO .midnight() toepassen eindigt in verkeerde tijdzone?
break;
case "datetime": oWs.write_vardate(rownum, i, new Date(val).getVarDate(), 1);
break;
case "time" : oWs.write_vardate(rownum, i, new Date(val).getVarDate(), 2);
break;
case "currency": oWs.write_number(rownum, i, val, 1);
break;
case "float" : oWs.write_number(rownum, i, val, 1);
break;
case "number": oWs.write_number(rownum, i, val, 0);
break;
case "processingtime":
if (val["duration"] != null)
val = val["duration"] + " " + (val["unit"]=='U'?L("lcl_mld_hours"):L("lcl_mld_days"));
else
val = "";
len = oWs.write_string(rownum, i, val);
break;
case "html" : // hij is hierboven al decoded
len = oWs.write_string(rownum, i, val);
break;
default:
// Autotypering "datum"
if (typeof val == "date" || val instanceof Date)
{
oWs.write_vardate(rownum, i, new Date(val).getVarDate(), 0); // params.prettydate toepassen?
}
else
{
len = oWs.write_string(rownum, i, String(val));
}
}
if (len > maxlengths[i])
maxlengths[i] = len;
}
}
if (this.printFlex)
{
// equivalent van html += addFlexKenmerkKolommen(oRsFlexData, this,
for (var i_f=0; i_f< oRsFlexData.length; i_f++)
{
var rec = oRsFlexData[i_f];
var val = rec.value; // altijd string!
if (val == null || val === "") // Leeg flexkenmerk is vreemd?
continue;
// Type 'C','N','D','T','R','X','L','Q','F','M','E','S','l','B','V'
// Sommige kunnen we slimmer
// Q/L en negatieve volgnummers heeft function getFlexData er al uit gestript
switch(rec.type)
{
case "E": // Encrypted
case "F": // Komen nog niet voor/gaan niet goed met kenmerk_niveau vanwege RWSN#78535
var flex_bijlagen = flexProps(this.flexModule, rec.key, rec.kenmerk_key, rec.kenmerk_niveau);
if (flex_bijlagen.files.length)
oWs.write_string(rownum, i + i_f, flex_bijlagen.files[0].name);
break;
case "N": // numeriek
var fval = parseFloat(val);
if (isNaN(fval)) // geeft ongeldige xlsx
{
__DoLog("NaN, waarde is geen float: " + fval);
}
if (rec.decimalen)
oWs.write_number(rownum, i + i_f, fval, 1); // Altijd 2 decimalen
else
oWs.write_number(rownum, i + i_f, fval, 0); // geen decimalen
break;
case "D": // datum
var a = /^(\d{2})-(\d{2})-(\d{4})$/.exec(val); // 27-02-2024
if (a) {
var dtval = new Date(+a[3], +a[2] - 1, +a[1]);
oWs.write_vardate(rownum, i + i_f, dtval.getVarDate(), 0);
}
break;
case "T": // tijd
var a = /^(\d{2}):(\d{2})$/.exec(val); // 13:35
if (a) {
var dtval = new Date(1970, 0, 1, +a[1], +a[2]);
oWs.write_vardate(rownum, i + i_f, dtval.getVarDate(), 2);
}
break;
case "C": // Character
case "R": // Referentie
case "S": // Suggest
case "X": // Bestandsnaam
case "V": // checkbox doorvallen naar default?
default:
oWs.write_string(rownum, i + i_f, String(val)); // Expliciete String
}
}
}
rownum++;
oRs.MoveNext();
}
oRs.close();
for (var i = 0; i < maxlengths.length; i++)
{
if (maxlengths[i] > 8.43 * 10) // LXW_DEF_COL_WIDTH, 8.43 is de default Excel cell width
{
oWs.set_column_width(i, 1 + Math.min(maxlengths[i] / 10, 50), 1); // als je (net) te krap instelt wordt de lineheight soms hoger
// omdat Excel toch bang is dat er iets wrapt?
}
}
oWb.workbook_close();
if (formail) // Putorders pakt de temp-file verder op
{
Response.ContentType = "application/json";
var result = {
"tmpxlsx" : tmpxlsx,
deletefile: __Logging == 0
};
Response.Write(JSON.stringify(result));
}
else
{
var mime = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
var filename = (this.filename ? this.filename : "Facilitor") + " {0}.xlsx".format(toISODateTimeString(new Date()));
var pcontentdp = "attachment";
Response.AddHeader("content-disposition", pcontentdp + "; filename= \"" + safe.ContentName(filename) + "\"")
StreamFile(shared.tempFolder(), tmpxlsx, { mime: mime ,
pcontentdp: "none", // geen pcontentdp, dat hebben we zelf gedaan
deletefile: __Logging == 0});
}
ASPPAGE_END();
Response.End;
}
// SQL Query moet een veld fac_bijlagen_key bevatten en optioneel fac_bijlagen_zippath
ResultsetTable.prototype.ProcessAsZIP = function _ProcessAsZIP()
{
var oRs;
if (this.pRs)
oRs = this.pRs;
else if (this.dataset)
oRs = new data_recordset( this.dataset );
else
oRs = Oracle.Execute(this.sql);
var has_path = false;
for (var i = 0; i < this.columns.length; i++)
{
if (this.columns[i].name == "fac_bijlagen_zippath")
has_path = true;;
}
var bijlagen_list = [];
while (!oRs.EOF)
{
if (oRs.Fields("fac_bijlagen_key").Value) {
var onefile = { fac_bijlagen_key: oRs.Fields("fac_bijlagen_key").Value.id };
if (has_path)
onefile.zippath = oRs.Fields("fac_bijlagen_zippath").Value;
bijlagen_list.push(onefile);
}
oRs.MoveNext();
}
oRs.close();
zipfacbijlagen("facilitor.zip", bijlagen_list);
ASPPAGE_END();
Response.End;
}
// We bouwen een api2-model van onze recordset
// en geven die door aan fac_usrrap_list_graph (zoals onze rapporten ook doen)
// Proof of concept, niet in gebruik
ResultsetTable.prototype.ProcessAsGraph = function _ProcessAsGraph()
{
var model = { fields: {} };
var scf_params = { list: { columns: [] }};
var oRs;
if (this.pRs)
oRs = this.pRs;
else if (this.dataset)
oRs = new data_recordset( this.dataset );
else
oRs = Oracle.Execute(this.sql);
// Header row
var safeheader = [];
for (var i = 0; i < this.columns.length; i++)
{
var typ = this.columns[i].datatype|| "varchar";
if (typ == "float" || typ == "currency")
{
this.columns[i].datatype = "number";
typ = "number"; // anders gaat het zo maar naar string
}
model.fields["col" + i] = { "label": this.columns[i].caption, "typ": typ };
scf_params.list.columns.push("col" + i); // TODO: welke kolommen?
}
var xxx_array = []; // met data
while (!oRs.EOF)
{
var saferow = {};
for (var i = 0; i < this.columns.length; i++)
{
try
{
var val = this.columns[i].content(oRs, this.outputmode);
}
catch (e)
{
__Log("resultset_table_v2.inc: Probleem met het ophalen van columns[" + i + "]: " + this.columns[i].caption);
throw(e);
}
saferow["col" + i] = val;
}
xxx_array.push(saferow);
oRs.MoveNext();
}
oRs.close();
scf_params.list.columns = getQParamArray("graphcols")// "col3,col4" --> ["col3", "col4"];
//__DoLog(model);
//__DoLog(scf_params);
//__DoLog(xxx_array);
fac_usrrap_list_graph (model, scf_params, xxx_array)
Response.End;
}
ResultsetTable.prototype.countHistogram = function(oRs)
{
var i, kolomnaam, kolomval, cnt;
for (i= 0; i < oRs.Fields.Count; i++)
{
kolomnaam = oRs.Fields(i).Name;
if (kolomnaam.toUpperCase() == this.keyColumn.toUpperCase())
continue;
kolomval = oRs.Fields(i).Value;
if (!this.Counter[kolomnaam])
this.Counter[kolomnaam] = {};
if (!this.Counter[kolomnaam][kolomval])
this.Counter[kolomnaam][kolomval] = 1;
else
this.Counter[kolomnaam][kolomval] += 1
}
}
function __rsProcessResultset(processParams) // processParams wordt blind aan alle callbackfuncties gegevens als tweede parameter
{
var result = { modified: false };
if (isPlain || isPrinting) {
if (this.tabs_code) {
result = reorderPerslidCols(this.tabs_code, this.columns);
this.columns = result.columns;
%> <!-- COLUMNS --> <%
if (!this.inline && isPlain) {
rs_columns(this.tabs_code, this.columns);
}
}
if (!this.tabs_code || !result.modified) { // Default kolommen
for (var i in this.columns) {
if (this.columns[i].showDefault === false) { // Onderdruk deze kolommen
this.columns[i].hidden = true;
}
}
}
}
if (this.sql == null && !this.dataset)
return;
this.processParams = processParams;
this.noPrint |= !device.test(device.canPrint);
this.noExcel |= !device.test(device.canExcel);
if (isXMLXSL)
{
this.ProcessAsXMLXSL();
return; // die is zo compleet anders....
}
if (isCSV || isCSV2XLSX)
{
this.ProcessAsCSV();
return; // die is zo compleet anders....
}
if (isNativeExcel)
{
this.ProcessAsNativeExcel(this.outputmode == 8);
return; // die is zo compleet anders....
}
if (isZIP)
{
this.ProcessAsZIP();
return; // die is zo compleet anders....
}
if (isGraph)
{
this.ProcessAsGraph();
return; // die is zo compleet anders....
}
if (this.canBookmark)
{
if (Request.ServerVariables("REQUEST_METHOD") == "POST") // POST is nog te lastig
INTERNAL_ERROR_CANNOT_BOOKMARK_POST;
if (book_id || getQParam("bybookmark",0)==1)
this.canBookmark = false;
}
with(this)
{
if (isPrinting)
startPrint();
// Print filter tabel met filterwaarden van het zoekscherm
var html_filter = "";
if (isPrinting == true)
{
if (filterParams)
html_filter = getRSFilterTable(filterParams);
}
Response.Write(html_filter);
// class moet hetzelfde zijn zodat summary text overal (incl inline overzichten) hetzelfde uitelijk krijgen
// id moet verschillend zijn omdat je meerdere rsSummary divs onafhankelijk van elkaar moet benaderen (vullen)
if (isPrinting)
{
%>
<div id="rsSummary<%=summaryId%>" class="rsSummary" style="display:none">
<span id="rsSummaryInfo<%=summaryId%>" class="rsSummaryInfo"></span>
</div>
<script>
function setSummary(html)
{
if (html != "")
{
var elm = document.getElementById("rsSummaryInfo<%=summaryId%>");
elm.innerHTML = html;
var elm = document.getElementById("rsSummary<%=summaryId%>");
elm.style.display='block';
}
}
</script>
<%
}
else if (isPlain)
{
if (this.rstableNr == 1)
{
%>
<script>
var postformHTML = '<%=safe.jsstring(postformHTML)%>'; <% /* postformHTML naar javascript voor gebruik in resultset_table_v2.js */ %>
var /*function*/ setSummary = FcltMgr.setHeaderExtraTitle;
var result_refresher_url = "<%= safe.jsstring(this.refresher_url) %>";
var result_refresher_url = <%= (this.refresher_timer||0) %>;
</script>
<%
}
if (this.canBookmark)
{
%>
<script>
function saveBookmark($dialog)
{
var bmtitel = $dialog.find("#bmtitel").val();
var data = { path: "<%=safe.jsstring(String(Request.ServerVariables("SCRIPT_NAME")))%>",
query: "outputmode=" + (<%=this.advancedprint?3:outputmode%>) + "<%=safe.jsstring(transitQS())%>",
naam: bmtitel
};
<% protectRequest.dataToken("data"); %>
$.post("../shared/create_bookmark.asp",
data,
FcltCallback, "json");
}
function createBookmark(evt, deze)
{
params = {oktekst: L("lcl_fac_bookmark"),
title: L("lcl_fac_bookmark"),
ishtmlsafe: true,
fncallback: saveBookmark,
buttons: [{ text: L("lcl_cancel"), icon: "fal fa-fw fa-undo", class: "alertCancel" }]
};
var page_content = "<input type='text' id='bmtitel' class='fld' value='<%=safe.htmlattr(this.title)%>'>";
FcltMgr.mydialog(page_content, params);
}
</script>
<%
}
if (!noPrint)
{
if (this.rstableNr == 1)
{
%>
<script>
function doPrint(poutputmode)
{
var autosortby = "";
var xx = $("th.sorttable_sorted,th.sorttable_sorted_reverse");
if (xx.length)
{
if (xx.html().split("<br>").length > 1)
{
autosortby = xx.html().split("<br>")[0];// Bij combined alleen de eerste
}
else // moeten we complexer strippen
{
autosortby = xx.text();
autosortby = autosortby.substring(0, autosortby.length - 1); // Spatie er af halen. Font Awsome teken is een html <i> tag/element en geen karakter.
}
}
if (xx.hasClass("sorttable_sorted_reverse"))
{
autosortby = "-" + autosortby;
}
<% if (Request.ServerVariables("REQUEST_METHOD") == "POST")
{ %>
document.printform.autosortby.value = autosortby;
document.printform.outputmode.value = poutputmode;
document.printform.submit();
<% }
else
{ %>
FcltMgr.windowopen("<%=Request.ServerVariables("SCRIPT_NAME")%>?outputmode=" + poutputmode + "&autosortby=" + escape(autosortby) + "<%=safe.jsstring(transitQS())%>");
<% } %>
}
function doOutput(poutputmode)
{
<% if (Request.ServerVariables("REQUEST_METHOD") == "POST")
{ %>
// Alle parameters zijn in een formulier gestopt als request methode POST is.
if (poutputmode == 0)
document.printform.target = "_self";
<% }
var hasFlex = this.flexModule && this.flexId;
%>
if (!<%=hasFlex?"true":"false"%> || !(poutputmode == 1 || (poutputmode == 2 && ("<%=S("excel_mode")%>" == "0" || "<%=S("excel_mode")%>" == "2"))))
{
doPrint(poutputmode);
return;
}
params = { oktekst: L("lcl_Yes"), title: L(poutputmode==1?"lcl_print":"lcl_export_to_excel") };
params.fncallback = function ()
{
doPrint(poutputmode); // poutputmode wordt 5 (printer zonder flex) of 6 (excel zonder flex);
// close gaat vanzelf;
}
params.buttons = [
{
text: L("lcl_No"),
icon: "fal fa-fw fa-times",
class: 'resultprintno',
click: function()
{
doPrint(poutputmode + 4);
}
},
{
text: L("lcl_cancel"),
icon: "fal fa-fw fa-undo",
class: 'resultprintcancel',
}];
FcltMgr.mydialog(L("lcl_print_properties"), params);
}
</script>
<%
}
}
if (this.dataset && this.urllink)
{
%>
<script>
function clickAction(urlkey, titel)
{
FcltMgr.openDetail("<%=safe.htmlattr(urllink)%>" + urlkey, "");
}
</script>
<%
}
var asSavedWidget = getQParamInt("asSavedWidget", 0) == 1;
if (asSavedWidget)
{ %>
<script>
function _toggleExpandIcon()
{
$("#searchBlockToggler > i").toggleClass("fa-search-plus fa-search-minus");
}
function toggleSearchBlock()
{
_toggleExpandIcon();
parent.toggleSearchBlock();
}
$(function() { // Ik zoek opnieuw (of ververs) en het zoekblok is opengeklapt, corrigeer dan het expand-icoontje
if (!$(parent.document.body).find(".container-fluid.hidden").length)
_toggleExpandIcon();
});
</script>
<% }
if (book_id)
{
this.actions = [];
this.buttons = [];
}
buttons = this.buttons || [];
if (this.roundtripCode) { %>
<script>
function doRoundtrip_<%=this.roundtripCode%>_exp()
{
var url = "../fac/fac_roundtrip_exp.asp?app_code=<%=this.roundtripCode%>";
FcltMgr.windowopen(url);
}
function doRoundtrip_<%=this.roundtripCode%>_imp()
{
var url = "appl/fac/fac_roundtrip_imp.asp?app_code=<%=this.roundtripCode%>";
FcltMgr.openDetail(url, L("lcl_import"));
}
</script>
<% buttons.push({ icon: "fa-file-import", title: L("lcl_scf_import"), action: "doRoundtrip_" + this.roundtripCode + "_imp()", order: 2 });
buttons.push({ icon: "fa-file-export", title: L("lcl_scf_export"), action: "doRoundtrip_" + this.roundtripCode + "_exp()", order: 3 });
buttons.push({ horizontalRule: true, order: 1 }); // Vanwege vieze CSS truukjes moet deze als laatste gepushed worden
}
if (!noPrint && Request.ServerVariables("REQUEST_METHOD") == "GET") // Alleen dan auto-refreshknop
{
var found = false;
for (var i=0; i < buttons.length; i++)
{
if (buttons[i].title == L("lcl_refresh") || buttons[i].action == "FcltMgr.reload()")
found = true;
}
if (!found)
buttons.push({ icon: "fa-fclt-refresh", title: L("lcl_refresh"), action: "FcltMgr.reload()", id: "btn_scf_refresh" });
}
if (!noPrint)
{
buttons = buttons.concat([ { icon: "fa-print", title: L("lcl_print_table"), action: "doOutput(1)" } ]);
if (!noExcel)
{
buttons = buttons.concat([ { icon: "fa-table", title: L("lcl_export_to_excel"), action: "doOutput(2)" } ]);
}
}
if (this.advancedprint)
{
buttons.push({ icon: "fa-address-card", title: advancedprint_title, action: "doOutput(3)" }); // advanced
}
if (this.canCSV && !noExcel)
{
buttons.push({ icon: "fa-file", title: L("lcl_export_to_csv"), action: "doOutput(4)" }); // CSV
}
if (this.canBookmark)
buttons.push({ icon: "fa-bookmark", title: L("lcl_fac_bookmark"), action: "createBookmark(window.event, this)" });
if (asSavedWidget)
this.buttons.push({ icon: "fa-search-plus", id: "searchBlockToggler", action: "toggleSearchBlock();", tooltip: L("lcl_search") });
if (this.title || buttons.length > 0 || (this.rstCheckBoxes && this.rstCheckBoxes.length > 0) )
IFRAMER_HEADER(
this.title || "",
buttons, { id: this.rstableNr,
inlineId: (this.inline && this.filterParams && this.filterParams.mld_key ? this.filterParams.mld_key : ""), collapsible: this.collapsible },
this.rstCheckBoxes
);
if (this.rstableNr == 1)
{ // collapseblock sluiten we nooit omdat we niet weten of er nog een volgende tabel komen.
// Een browser sluit dan vanzelf aan het einde en dan klopt het weer. Niet perfect maar ach..
%>
<div id="collapseblock">
<%
}
} // isPlain
var html = "";
if (isPlain)
{
// ========= ACTIONS =========
// == zijn er multi ACTIONS?
var anyMultiActions = false;
for (var i=0; i<this.actions.length; i++)
{
anyMultiActions |= this.actions[i].multi;
}
// Eerst: maak <20><>n div met alle acties.
var hasActionsCol = 0;
var skip = 0;
for (var i=0; i < columns.length; i++)
{
if (columns[i].combine)
skip ++;
if (columns[i].hasActions)
{
hasActionsCol = i - skip;
break;
}
}
if (anyMultiActions)
hasActionsCol++;
if (this.inlineDetails)
hasActionsCol++;
// Nu de inline buttons renderen. Ze zijn er <20><>n keer en worden voor alle regels hergebruikt
var actionsDiv = "";
var aantalInline = 0;
for (var i = 0; i < this.actions.length; i++)
{
if (disableInlineActions && !this.actions[i].isDefault)
continue;
if (this.actions[i].single === false || this.actions[i].onlyMulti) // triple '=' omdat undefined niet false mag zijn
continue; // niet ook nog inline
if (!this.actions[i].isDefault)
aantalInline++;
var def = (this.actions[i].isDefault? " isdefault='1'" : "")
+ (this.actions[i].onlyMulti? " onlymulti='1'" : "")
+ (this.actions[i].isDefault || this.actions[i].onlyMulti? " style='display:none'" : "");
var tooltip_actions = this.actions[i].tooltip? " title='" + safe.htmlattr(this.actions[i].tooltip) + "'" : "";
var disp = useHamburger != 0 ? " style='display: block;'" : "";
if (this.actions[i].multiOnce)
val = "<span class='ia2' " + def + " onclick='doAm(event, this, \"" + this.actions[i].action + "\")'" + disp + tooltip_actions + ">";
else
val = "<span class='ia2' " + def + " onclick='doA(event, this, \"" + this.actions[i].action + "\")'" + disp + tooltip_actions + ">";
actionsDiv += val + this.actions[i].caption + "</span>";
}
hasInlineActions = aantalInline > 0;
html += "\n<div id='allactions_" + ID + "' class='allactions' style='display:none;z-index:13' hasActionsCol='"+hasActionsCol+"' >" + actionsDiv + "</div>"
+ "\n<script type='text/javascript'>"
+ "\n initActions('" + this.ID + "', "+useHamburger+")"
+ "</script>";
}
html += startTable();
if (!Response.IsClientConnected)
{
__Log("Response.IsClientConnected false, Skipping sql query.", "#00FF00");
Response.End;
}
// read general totals and general averages, if any
if (this.sqltotals)
{
oRs_tot = Oracle.Execute(sqltotals);
if (!oRs_tot.EOF)
{
for (fld in columns)
{
var field = columns[fld];
if (field.generaltotal)
{
field.generaltotalsum = oRs_tot(field.name).Value;
}
else if (field.generalaverage)
{
field.generaltotalavg = oRs_tot(field.name).Value;
}
}
}
oRs_tot.Close();
}
// vanuit fac_usrrap_list krijgen we een open recordsset pRs door
// hij moest hem zelf al openen om de kolommen te bepalen
var oRs;
if (this.pRs)
oRs = this.pRs;
else if (this.dataset)
oRs = new data_recordset( this.dataset );
else
oRs = Oracle.Execute(sql);
if (!Response.IsClientConnected)
{ // Gebruiker was te ongeduldig. Hoeven we de rest ook niet meer te doen
__Log("Response.IsClientConnected false, discarding result.", "#FFFF00");
Response.End;
}
if (this.subtabicon)
{
var sti = (subtabicon instanceof Function ? subtabicon(oRs) : subtabicon);
if (sti && sti.icon)
{
var subtabicon = sti.icon;
var color = sti.color;
%> <script>
FcltMgr.setSubtabExtra("<span class='subtab-badge-icon' style='color:<%=color%>'>" + I("<%=subtabicon%> fa-lg", { "fastyle": "fas"}) + "</span>");
</script>
<% }
}
if (oRs == null || oRs.EOF)
{
Response.Write("<div id='rstable'><table><tr><td class='emptyset'>" + emptySetString + "</td></tr>");
endTable();
if (isPrinting)
endPrint();
if (oRs)
oRs.close();
var badgehtml = "";
if (this.required)
{
badgehtml = "<span class='subtab-badge-icon subtab-badge-missing'>"
+ I("fa-exclamation-triangle fa-lg", { "fastyle": "fas" })
+ "</span>"
}
if (!this.subtabicon) {
%> <script>
var prevent_badge_reset = false;
<% if (!badgehtml && this.rstableNr && this.rstableNr > 1)
{ /* Itereer over alle voorgaande resultsets, als er 1 bestaat hoeven we de spinner niet meer uit de badge te halen,
want dat is dan al gebeurd, en mogelijk staat er ook al een counter in. */
%> for (var i = <%=this.rstableNr-1%>; i && !prevent_badge_reset; i--) {
prevent_badge_reset = $("[id=rstable].rstable" + i).length > 0;
}
<% } %>
if (!prevent_badge_reset) {
FcltMgr.setSubtabExtra("<%=safe.jsstring(badgehtml)%>");
}
</script>
<% }
return -1;
}
else
{
%> <script>
FcltMgr.setSubtabExtra("");
</script>
<% }
var printedFirstHeader = false; // Is de eerste header afgedrukt?. Bij isExcel en isPrinting worden namelijk meerdere headers afgedrukt
var printMoreHeaders = false; // Wordt gebruikt bij isExcel en isPrinting om meerdere headers af te drukken, maar dan moet de flexModule en flexId wel gedefineerd zijn
// Alleen headers weergeven bij printen naar printer of excel
// en indien de flexkenmerkquery, flexid en flexgroupid is meegegeven
if ((isPrinting || isExcel || this.showProperties) && this.printFlex && this.flexGroupId)
printMoreHeaders = true;
var lastFlexGroupKey = -1; // Wordt gebruikt bij isExcel. Start without a previous flex group, the first one is new.
var lastFlexParentGroupKey = -1 // Wordt gebruikt bij isExcel. Start without a previous flex group, the first one is new.
var flexGroupChanged = false;
var theSqlFlex = "";
if (this.printFlex)
theSqlFlex = getSqlFlex(flexModule.toUpperCase(), flexId, (flexParams instanceof Function ? flexParams(oRs) : flexParams));
var lastHadFlex = false;
var nrOutOfFilter = 0;
for (var cnt = 0; (cnt < S("qp_maxrows") + nrOutOfFilter || isPrinting || isExcel || showAll || showProperties) &&
(cnt < S("qp_maxrows2") + nrOutOfFilter || isExcel) && // Naar excel altijd alle regels (meer dan S("qp_maxrows2")) weergeven.
!oRs.EOF; cnt++)
{
if (!Response.IsClientConnected)
{
__Log("Response.IsClientConnected false, Resultset aborted.", "#00FF00");
Response.End;
}
if (cnt && cnt % 1000 == 0)
__Log("Records: " + cnt, "#E0E0FF");
var oRsFlex = null;
if ((isPrinting || isExcel || showProperties) && this.printFlex)
{
var flexKey = (!oRs.Fields(flexId).Value ? oRs.Fields("id").Value : oRs.Fields(flexId).Value); // primary key van tabel uit recordset of id uit dataset van api2-model
var oRsFlexData = getFlexData(theSqlFlex, flexKey, { showProperties: showProperties }); // is een JSON
if (!oRsFlexData.length)
var noFlexResult = true; // Er zijn geen flexkenmerken
else
var noFlexResult = false; // Er zijn flexkenmerken
if (flexGroupId) // Is er een flexGroupId meegegeven
{
var flexGroupKey = this.myRs(flexGroupId, oRs);
flexGroupChanged = isExcel && (lastFlexGroupKey != flexGroupKey); // Alleen bij printen naar excel moet er wellicht een nieuwe header boven i.v.m. andere flexkenmerken
var flexChanged = flexGroupChanged;
lastFlexGroupKey = flexGroupKey;
if (flexParentGroupId) // Is er een flexParentGroupId meegegeven
{
var flexParentGroupKey = this.myRs(flexParentGroupId, oRs);
flexParentGroupChanged = isExcel && (lastFlexParentGroupKey != flexParentGroupKey); // Alleen bij printen naar excel moet er wellicht een nieuwe header boven i.v.m. andere flexkenmerken
if (!flexParentGroupChanged && flexGroupChanged && flexChangeNiveau && !noFlexResult && !flexChanged)
{ // Flexgroep is veranderd maar parentflexgroep niet. Alleen als er op flexgroep niveau flexkenmerken zijn gedefinieerd is er een nieuwe header nodig.
flexChanged = false;
for (var datai=0; i < oRsFlexData.length; i++)
{
var rec = oRsFlexData[datai];
var kenmerk_niveau = rec.niveau;
if (kenmerk_niveau == flexChangeNiveau)
{
flexChanged = true;
break;
}
}
}
flexChanged = flexParentGroupChanged || flexChanged; // Als parent group veranderd is zijn er waarchijnlijk ook andere kenmerken. Kan voor meldingen nog scherper i.v.m. nog een niveau (parent) hoger. Maar is in praktijk nog niet echt nodig.
lastFlexParentGroupKey = flexParentGroupKey;
}
}
}
if (!printedFirstHeader || (printMoreHeaders && flexChanged && (!noFlexResult || (lastHadFlex && noFlexResult))))
{
// Header van ResultsetTable
html += makeTableHeader(oRs, oRsFlexData, anyMultiActions);
html += "\n<tbody>";
printedFirstHeader = true;
}
lastHadFlex = !noFlexResult;
// Een row van ResultsetTable
if (rowFilter(oRs)) {
html += makeTableRow(oRs, oRsFlexData, rowNum, anyMultiActions, noFlexResult);
rowNum = rowNum + 1;
if (this.buildHistogram)
this.countHistogram(oRs);
// Voer berekeningen uit i.v.m. extra info die moet komen in de regel waar ook de print en excel iconen staan
if (summaryCalc)
summaryCalc(oRs, this.processParams);
if (totalCalc)
totalCalc(oRs, this.processParams);
}
else
nrOutOfFilter++;
if (isExcel) // Excel heeft geen S("qp_maxrows2") bescherming. Extreem grote rapportages leiden
{ // tot een out-of-memory. Omdat bij Excel verderop toch niets wordt gedaan met html
// gooien we die hier alvast naar buiten zodat Response Buffer Exceeded wel ingrijpt.
Response.Write(html);
html = "";
}
oRs.MoveNext();
}
html += "</tbody>";
if ((!oRs.EOF || this.hasMore) && !isPrinting && !isExcel)
{
var a_element = "";
if (Request.ServerVariables("REQUEST_METHOD") == "POST")
{
// Inline details met POST methode en meer dan max regels tonen werkt niet. Komt ook niet voor.
a_element = "<a href='javascript:doOutput(0)'>";
}
else
{
a_element = "<a href='"
+ (inline // Voor inline details moet niet gehele window vervangen worden omdat je dan ook de hoofd regels kwijt bent (dan alleen de <td> cell vervangen)
? "javascript:loadInlineDetails(\""
+ safe.jsstring(Request.ServerVariables("SCRIPT_NAME") + "?showall=1" + transitQS())
+ "\");"
: safe.jsstring(Request.ServerVariables("SCRIPT_NAME") + "?showall=1" + transitQS()) + "' target='_self")
+ "'>";
}
a_element += L("lcl_qp_maxrows1").format(S("qp_maxrows")) + "</a>";
// Op regel klikken om de overige regels op te halen, boven de tabel
html = "<div id='rsMaxHistoryB'><span id='rsMaxHistoryInfoB'>"
+ (cnt <= S("qp_maxrows") + nrOutOfFilter
? a_element.replace(/&collapsed=1/gi, "") // Als er op deze regel wordt geklikt moet IFRAMER niet meer dichtgeklapt worden, dus &collapsed=1 verwijderen uit de link.
: L("lcl_qp_maxrows2").format(S("qp_maxrows2"))
)
+ "</span></div>" + html;
}
// Footnote van ResultsetTable
// Footnote hoort eigenlijk voor de tbody (HTML4.0) maar dan weten we het totaal nog niet.
// MGE: TODO: Footnote kan hier nog voor de body gezet worden want Response.Write(html) heeft nog niet plaatsgevonden!
// Echter bij (printMoreHeaders && flexGroupChanged) worden er meerdere headers geprint op verschillende plekken.
// Dit hoort eigenlijk niet zo.
var htmlFoot = "";
if (oRs.EOF)
htmlFoot += makeTableFootnote(anyMultiActions, oRsFlexData);
if (anyMultiActions && !inline)
{
appender = "\n<div id='multiactiondiv'><span id='multilabel'>" + safe.html(L("lcl_with_selected").format(0)) + "</span>";
var multiActions = 0;
// Geen inline acties, dus ook geen rowEnabler, dus is okformulti ook nog niet bepaald, dan doen we dat hier
if (disableInlineActions && multiActionEnabler)
{
var validateAction = multiActionEnabler();
for (var i=0; i < actions.length; i++)
{
if (!actions[i].okformulti && // No double check
(actions[i].multi && !(actions[i].onlyMulti || actions[i].single === false)) && // No unnecessary check
actions[i].enabler && validateAction && validateAction[actions[i].enabler]) // Check
{
actions[i].okformulti = true;
}
}
}
for (var i=0; i < actions.length; i++)
{
/////
//
// Een bulk-actie wordt weergegeven indien:
//
// - multi = true, EN:
//
// - okformulti = true (oftewel, de enabler is succesvol)
// - OF: het is uitsluitend een multi actie, dan altijd weergeven. Oftewel: (onlyMulti || single === false)
//
/////
if (actions[i].multi && (actions[i].okformulti || actions[i].onlyMulti || actions[i].single === false))
{
multiActions++;
appender += "<span onClick='javascript:doMulti(\"" + this.ID + "\", \"" +
actions[i].action + "\", \"" +
safe.jsstring(actions[i].caption) + "\", " +
actions[i].multiOnce + ");" +
"FcltMgr.stopPropagation(event);' class='button footerbutton'>"+(actions[i].icon?I(actions[i].icon):"")+safe.html(actions[i].caption)+"</span>";
}
}
if (multiActions == 0)
appender += "<i style=\"padding-left: 9px\">" + L("lcl_no_multi_actions") + "</i>";
appender += "</div>";
var flexColumns = 0; /* Afgekeken van addFlexKenmerkFooter; bepaal het aantal columns dat nodig is voor de kenmerken */
if ((isPrinting || showProperties) && this.printFlex) {
flexColumns = 1;
} else if (isExcel && this.printFlex) {
for (var i=0; i < oRsFlexData.length; i++) {
flexColumns++;
}
}
htmlFoot += "<tr><td class='rsfooter' colspan=" + (columns.length + flexColumns + ((useHamburger && hasInlineActions) ? 1 : 0) + (!isPrinting && !isExcel && anyMultiActions && !inline? 1 : 0) + (inlineDetails? 1 : 0)) + ">" + appender + "</td></tr>";
}
if (htmlFoot != "")
htmlFoot = "<tfoot>" + htmlFoot + "</tfoot>";
html += htmlFoot;
Response.Write(html);
endTable();
// 'Klik voor meer' onderaan de tabel
if (!oRs.EOF || this.hasMore)
{
var a_element = "";
if (Request.ServerVariables("REQUEST_METHOD") == "POST")
{
// Inline details met POST methode en meer dan max regels tonen werkt niet. Komt ook niet voor.
a_element = "<a href='javascript:doOutput(0)'>";
}
else
{
a_element = "<a href='"
+ (inline // Voor inline details moet niet gehele window vervangen worden omdat je dan ook de hoofd regels kwijt bent (dan alleen de <td> cell vervangen)
? "javascript:loadInlineDetails(\""
+ safe.jsstring(Request.ServerVariables("SCRIPT_NAME") + "?showall=1" + transitQS())
+ "\");"
: safe.jsstring(Request.ServerVariables("SCRIPT_NAME") + "?showall=1" + transitQS()) + "' target='_self")
+ "'>";
}
a_element += L("lcl_qp_maxrows1").format(S("qp_maxrows")) + "</a>";
// Op regel klikken om de overige regels op te halen, onder de tabel
html = "\n<div id='rsMaxHistoryE'><span id='rsMaxHistoryInfoE'>"
+ (cnt <= S("qp_maxrows") + nrOutOfFilter
? a_element
: L("lcl_qp_maxrows2").format(S("qp_maxrows2"))
)
+ "</span></div>";
Response.Write(html);
}
if ("auditcount" in this && rowNum >= this.auditcount)
{
shared.registeraction("audit", {info: L("fac_audit_listrequested").format(this.title, rowNum), daily: 0 });
}
// default summary text
if (rowNum == 1)
summaryInfo = L("lcl_nr_lines_resultone");
else
summaryInfo = L("lcl_nr_lines_result").format(rowNum);
if (summaryShow)
{
var summaryInfo = ((!oRs.EOF || this.hasMore)? "<span class='summaryincomplete'>" + L("lcl_suminfo_incomplete") + "</span>&nbsp;" : "") + (summaryShow(rowNum) || "");
}
if (!this.noSetSummary)
{
%> <script>
setSummary("<%=safe.jsstring(summaryInfo)%>");
var do_sum_lines = false;
<% if (this.rstableNr && this.rstableNr > 1)
{ %>
for (var i = <%=this.rstableNr-1%>; i && !do_sum_lines; i--) {
do_sum_lines = $("[id=rstable].rstable" + i).length;
}
<% } %>
FcltMgr.setSubtabLines(<%=rowNum%>, { add: do_sum_lines, hasMore: <%=(!oRs.EOF || this.hasMore) ? "true" : "false"%> });
</script>
<% }
// Eventueel doortellen tot het einde. Dat doen we maximaal 1 seconde! (zo'n 3200 records)
var tmStart = (new Date).getTime();
var teller = 0;
while (!oRs.EOF && this.buildHistogram && ((new Date).getTime() - tmStart) < 1000)
{
teller ++;
this.countHistogram(oRs);
oRs.MoveNext();
}
if (!oRs.EOF && this.buildHistogram)
{ // Niet gered binnen een seconde
__Log("Histogram niet binnen 1000ms klaar. Reset histogram");
this.Counter = {};
}
else if (teller > 0)
{
__Log("Histogram afgerond ("+teller+" extra items) in " + ((new Date).getTime() - tmStart) + "ms");
}
oRs.close();
if (endText)
{
var endTextInfo = (endText instanceof Function ? endText(oRs, this.processParams) : endText);
if (endTextInfo != "")
{
%>
<div id="rsEndText">
<span id="rsEndTextInfo"><%=endTextInfo%></span>
</div>
</div>
<%
}
}
if (isPrinting)
endPrint();
if (this.buildHistogram)
return this.Counter;
else
return rowNum; // simpel return aantal rows
} // with(this)
}
function __rsStartTable()
{
var html = "";
with (this)
{
html = "<div id='rstable' class='rstable" + this.rstableNr + "'>";
html += "<table cellspacing='0' cellpadding='0' ";
if (getQParamInt("noqfilter", 0) == 1)
html += " noqfilter='1'";
if (isPrinting == true) {
html += " isPrinting='TRUE' ";
}
if (ID != null)
html += " ID='" + ID + "' ";
if (tableClassName != null)
html += " class='" + tableClassName + "' ";
html += ">";
rowNum = 0;
}
return html;
}
function __rsMakeTableHeader(oRs, oRsFlexData, anyMultiActions)
{
var html = "";
with(this)
{
html += "\n<thead><tr>";
if (!isPrinting && !isExcel)
{
// ========= ACTIONS =========
// == zijn er multi ACTIONS?
if (anyMultiActions && !inline)
{
html += "<th class='multiselect sorttable_nosort'><input type=checkbox class='master' onclick='checkAll(\"" + ID + "\", this)'></th>";
}
if (useHamburger && hasInlineActions)
{
html += "<th class='sorttable_nosort'></th>";
}
if (inlineDetails)
{
html += "<th>"+I("fa-plus-square")+"</th>";
}
}
// ========= COLUMNS/THEADER =========
for (var i=0; i < columns.length; i++)
{
if (propertiesColumn == i)
// Nog kolommen toevoegen voor de flexkenmerken
html += addFlexKenmerkHeader(oRsFlexData, this);
if ((isPlain && (columns[i].purpose & VIEW_ONLY)) ||
((!isPlain || showProperties) && (columns[i].purpose & PRINTING_ONLY)))
{
if ((isPrinting || showProperties || isExcel || !columns[i].combine) && !(isExcel && columns[i].hidden))
{
if (isExcel)
{
html += "<th>";
}
else
{
if (columns[i].hidden)
{
html += "<th style='display:none'>";
}
else
{
html += "<th";
if (columns[i].caption == p_autosortby)
{
html += " id='autosortbyme'";
}
var sort_class = "";
if (columns[i].datatype == "currency" ||
columns[i].datatype == "float" ||
columns[i].datatype == "number")
{
html += " style='text-align:right;'";
if (safe.curr(1.5).indexOf(",") == -1)
sort_class += " sortable_numeric";
else
sort_class += " sorttable_numericcomma";
}
else if (columns[i].datatype == "varchar" ||
columns[i].datatype == "html")
{
sort_class += " sorttable_alpha";
}
if (columns[i].align)
html += " style='text-align:" + columns[i].align + "'";
var theClass = sort_class
+ (columns[i].thClass ? " " + columns[i].thClass : "")
+ (columns[i].classList ? " " + columns[i].classList : "");
if (theClass != null && theClass != "")
html += " class='" + theClass + "' ";
if (inlineDetails)
html += " preSorttable='hideAllInlineDetails(\""+ID+"\")'";
var ctitle = columns[i].title == null ? "" : (" title='" + safe.htmlattr(columns[i].title) + "'");
html += ctitle + ">"
}
}
}
if (!(isExcel && columns[i].hidden))
{
var combine_caption = columns[i].caption.replace(/^\s+|\s+$/g,""); // trim spaces: functie trim() werkt niet server-side!
if (columns[i].combine && combine_caption && !isPrinting)
html += "<br>";
html += columns[i].caption;
}
// Is de volgende kolom een combine. LET OP!!!: PRINTING_ONLY kolommen niet meerekenen (overslaan) in niet print uitvoer.
var combine = false;
for (var c = i + 1; c < columns.length; c++)
{
if (columns[c].purpose != PRINTING_ONLY)
{
combine = columns[c].combine;
break;
}
}
if ((!isPrinting && !isExcel && (i < columns.length - 1) && combine) || (isExcel && columns[i].hidden))
{
// html += "<br>";
}
else
html += "</th>";
}
}
if (propertiesColumn == null)
// Nog header toevoegen voor de flexkenmerken.
html += addFlexKenmerkHeader(oRsFlexData, this);
html += "</tr></thead>";
}
return html;
}
var lastRowKey = -1; // voor suppress
function __rsMakeTableRow(oRs, oRsFlexData, cnt, anyMultiActions, noFlexResult)
{
var html = "";
// Pas op: dit komt voor elke regel terug, dus hou het kort!
with(this)
{
if (beforeEachRow)
beforeEachRow(oRs, this.processParams);
var thisKey = -1;
if (suppressKeyRepeat)
thisKey = oRs(suppressKeyRepeat).Value;
// HIER START EEN NIEUWE REGEL
var appender = ("\n<tr");
var OddRowClass = ""; // was:(cnt & 1)? "O " : "E "; maar dat kan inmiddels met css clientside beter
if (suppressKeyRepeat)
if (lastRowKey!=thisKey)
OddRowClass += "firstRow ";
else
OddRowClass += "suppressRow ";
if (!isExcel)
{
if (rowClass)
appender += " class='" + OddRowClass + rowClass(oRs, this.processParams) + "' ";
else
appender += " class='" + OddRowClass + "' ";
}
if (keyColumn != null && !isPrinting && !isExcel)
{
appender += " ROWKEY='" + safe.htmlattr(this.myRs(keyColumn, oRs)) + "'";
}
if (!isPrinting && !isExcel && rowData != null)
appender += " ROWDATA='" + safe.htmlattr(rowData(oRs, this.processParams)) + "'";
if (!isPrinting && dblClick != null)
appender += " onDblClick='" + safe.htmlattr(dblClick) + "'";
if (!isPrinting && !isExcel && this.actions && this.actions.length)
{
if (!keyColumn)
INTERNAL_ERROR_ACTION_ZONDER_KEYCOLUMN; // dat kan niet echt, we hebben een ROWKEY nodig
if (rowActionEnabler)
var validator = rowActionEnabler(oRs, this.processParams);
var actionbits = "";
var noActionBit = "";
for (var i = 0; i < actions.length; i++)
{
if (actions[i].single === false || actions[i].onlyMulti) // triple '=' omdat undefined niet false mag zijn
{
// die negeren we altijd actionbits += "0";
continue; // niet ook nog inline
}
if (actions[i].enabler && validator && !validator[actions[i].enabler])
{
actionbits += "0";
noActionBit += "0";
continue; // niet enabled
}
actionbits += "1"; // Enabled
noActionBit += actions[i].isDefault ? "1" : "0";
actions[i].okformulti = true;
}
appender += " ACTIONBITS='" + safe.htmlattr(actionbits) + "'";
}
appender += (">");
// Het <TR> start element is nu klaar
// ========= COLUMNS =========
if (!isPrinting && !isExcel && anyMultiActions && !inline) // Checkboxje erbij voor 'select all'
{
var isChecked = this.rowChecked && this.rowChecked(oRs, this.processParams);
appender += "<td class='multiselect'><input type=checkbox class='multiselect'" + (isChecked?' checked=1':'') + "></td>";
}
if (useHamburger && hasInlineActions)
{
if (actionbits == noActionBit) // No inline actions
{
appender += "<td></td>";
}
else
{
appender += "<td class=\"hambCont\"><div class=\"hamburger\">" + I("fa-bars fa-lg") + "</div></td>";
}
}
if (!isPrinting && !isExcel && inlineDetails)
{
var ttl = null;
if (hasInlineDetails) ttl = hasInlineDetails(oRs, this.processParams);
if (!hasInlineDetails || ttl)
{
var opdr_gewijzigd = (inlineDetailsChanged ? oRs("isGewijzigd").Value == 1 : false);
if (typeof ttl == 'string')
ttl = " title ='" + safe.htmlattr(ttl) + "'"
else
ttl = "";
appender += "<td class='inlinedetails closed' onclick='return showInlineDetails(this, \"" + inlineDetails+"\")'" + ttl + ">"
+ (opdr_gewijzigd ? I("fa-square-exclamation") : I("fa-plus-square")) + "</td>";
}
else
appender += "<td>"+L("lcl_inlinecolumnnone")+"</td>";
}
// ========= De echte waarde =========
var colHasVal;
for (var i = 0; i < columns.length; i++)
{
if (propertiesColumn == i)
// Nog kolommen toevoegen voor de flexkenmerken
appender += addFlexKenmerkKolommen(oRsFlexData, this,
{ lastRowKey: lastRowKey,
thisKey: thisKey
});
if ((isPlain && (columns[i].purpose & VIEW_ONLY)) ||
((!isPlain || showProperties) && (columns[i].purpose & PRINTING_ONLY)))
{
if (!columns[i].combine)
colHasVal = false;
try
{
var val = (columns[i].content != null ? columns[i].content(oRs, this.processParams) : "");
}
catch (e)
{
__Log("resultset_table_v2.inc: Probleem met het ophalen van columns[" + i + "]: " + columns[i].caption);
throw(e);
}
if (columns[i].image)
{
var imgval = "<img src='" + columns[i].image + "'";
if (val) imgval += " alt='" + safe.htmlattr(val) + "'";
val = imgval + ">";
}
if (val == null) val = "&nbsp;";
if (suppressKeyRepeat && lastRowKey == thisKey && !columns[i].keepKeyRepeat)
val = "&nbsp;";
// just in case?
val = String(val);
// Klik actie op de waarde.
var urlkey = -1;
// urlkey (columns[i].urlkey) is altijd een functie of -1 als er geen functie is gedefinieerd.
var urlkey = columns[i].urlkey instanceof Function? columns[i].urlkey(oRs, this.processParams, this) : -1;
var clickaction = urlkey == -1? "" : " class='clickaction' OnClick=' clickAction(" + urlkey + ")'";
// Tooltip voor de kolom
var tooltip = columns[i].tooltip == null ? null : this.myRs(columns[i].tooltip, oRs);
if (!tooltip && columns[i].prettydate)
{
tooltip = toDateString(oRs(columns[i].orgContent).Value, isExcel, false);
}
tooltip = (tooltip == null? "" : " title='" + safe.htmlattr(tooltip) + "'");
// Class voor de kolom
var columnClass = columns[i].columnClass == null ? (columns[i].tdClass instanceof Function ? columns[i].tdClass(oRs) : columns[i].tdClass) : this.myRs(columns[i].columnClass, oRs);
if (i <= lastColKey)
{
if (lastVal[i] == null || lastVal[i] != val)
lastVal[i] = val;
else if (val != "&nbsp;" && val !== "")
columnClass = (columnClass == null ? "dupe" : columnClass + " dupe");
}
columnClass = (columnClass == null ? "" : " class='" + columnClass + "'");
// custom sort key voor de kolom
var customSort = columns[i].customSort == null ? null : this.myRs(columns[i].customSort, oRs);
if (!customSort && columns[i].prettydate)
{
customSort = toDateString(oRs(columns[i].orgContent).Value, isExcel, false);
}
customSort = (customSort == null? "" : " sorttable_customkey='" + customSort + "'"); // pikt sorttable.js vanzelf op
// Uitlijning voor de kolom
var align = "";
var style = "";
if (columns[i].align)
align = " align='" + columns[i].align + "'";
else
{
if (columns[i].datatype == "currency" ||
columns[i].datatype == "float" ||
columns[i].datatype == "number")
style += "text-align:right;";
}
// Niet zichtbare kolom
style += (columns[i].hidden ? " display:none;" : "");
// Prevent wrapping if required
var nowrap = columns[i].nowrap ? " class='nowrap'" : "";
// Opbouw cell
style = (style ? " style='" + style + "'" : "");
if ((isPrinting || showProperties || isExcel || !columns[i].combine) && !(isExcel && columns[i].hidden))
{
if (isExcel)
appender += "<td";
else
appender += "<td" + align + style + columnClass + customSort + nowrap;
if (isExcel && val != null && val.length > 0 && val.match(/[0-9]/)
&& !inArray(columns[i].datatype, ["date", "currency", "datetime", "float", "number"]))
{
appender += " style='mso-number-format:\"\@\"'";
}
appender += (columns[i].classList ? " CLASS='" + columns[i].classList + "'" : "") + ">";
}
else
{ // Combine maar geen <br> voor lege val
if (val != "&nbsp;" && val !== "" && colHasVal)
{
appender += "<br>"
}
else
appender = appender.replace(/\&nbsp\;$/,"") // "Vorige" &nbsp; er af strippen
}
if (!(isExcel && columns[i].hidden))
if (tooltip || clickaction) // show tooltip on field, not on <td>
appender += "<span " + tooltip + clickaction + ">" + val + "</span>";
else
appender += val;
// Is de volgende kolom een combine. LET OP!!!: PRINTING_ONLY kolommen niet meerekenen (overslaan) in niet print uitvoer.
var combine = false;
for (var c = i + 1; c < columns.length; c++)
{
if (columns[c].purpose != PRINTING_ONLY)
{
combine = columns[c].combine;
break;
}
}
if ((!isPrinting && !isExcel && (i < columns.length - 1) && combine) || (isExcel && columns[i].hidden))
;/* appender += "<br>"; */
else
appender += "</td>";
// Hebben we al een echt waarde gehad?
colHasVal = colHasVal || (val != "&nbsp;");
// Als totaal van de kolom weergegeven moet worden dan waarden optellen.
// amount is altijd een functie
if (columns[i].total || columns[i].average)
{
var amount = (columns[i].amount != null ? columns[i].amount(oRs, this.processParams) : null)
if (amount != null && !isNaN(amount))
columns[i].totalsum += amount;
}
if (columns[i].average) // only on the last iteration is this needed
{
if (!columns[i].totalRows)
columns[i].totalRows = 0;
columns[i].totalRows++;
}
}
}
html += appender;
if (propertiesColumn == null)
// Nog kolommen toevoegen voor de flexkenmerken
html += addFlexKenmerkKolommen(oRsFlexData, this,
{ lastRowKey: lastRowKey,
thisKey: thisKey
});
html += "</tr>";
// rowNum = cnt + 1;
}
lastRowKey = thisKey;
return html;
}
function __rsMakeTableFootnote(anyMultiActions, oRsFlexData)
{
var html = "";
with(this)
{
var total = false;
var average = false;
// Kijk eerst of er een totaalregel toegevoegd moet worden
for (var i=0; i < columns.length; i++)
{
if (columns[i].total || columns[i].generaltotal) total = true;
if (columns[i].average || columns[i].generalaverage) average = true;
}
if ((total || average) && !isExcel)
{
html += "<tr>";
if (!isPrinting && anyMultiActions && !inline) // Kolom i.v.m. checkboxje erbij voor 'select all'
html += "<td></td>";
if (hasInlineDetails && !isPrinting && !isExcel && inlineDetails)
html += "<td></td>"; // Kolom i.v.m. inlinedetails
if (useHamburger && hasInlineActions)
html += "<td></td>"; // Ook nog kolom i.v.m. hamburger die er sowieso mogelijk alleen is als er acties zijn
var html_f = "";
var once = true; // Indien totalColumnText is gedfinieerd, eenmalig de text van totalColumnText tonen in de kolom voor de eerste totaal kolom.
for (var i = 0; i < columns.length; i++)
{
if ((isPlain && (columns[i].purpose & VIEW_ONLY)) ||
((!isPlain || showProperties) && (columns[i].purpose & PRINTING_ONLY)))
{
if (!columns[i].combine || isPrinting || showProperties || isExcel) // Bij isPrinting, isExcel of showProperties niet combineren.
{
// Nog kolommen toevoegen voor flexkenmerken
if (propertiesColumn == i)
html_f += addFlexKenmerkFooter(oRsFlexData, this);
html_f += "<td";
var sort_class = columns[i].thClass ? " " + columns[i].thClass : "";
if (sort_class != null)
html_f += " CLASS='" + sort_class + "' ";
// Uitlijning voor de kolom
var style = "";
var align = "";
if (totalColumnText && once && (i + 1) < columns.length && columns[i + 1].total)
style = "text-align: right;";
else if (columns[i].align)
align = " align='" + columns[i].align + "'";
else
{
if (columns[i].datatype == "currency" ||
columns[i].datatype == "float" ||
columns[i].datatype == "number")
style = "text-align: right;";
}
if (columns[i].hidden) style += "display: none;";
html_f += align + (style ? " style='" + style + "'" : "") + ">";
}
if (totalColumnText && once && (i + 1) < columns.length && columns[i + 1].total)
{
once = false;
html_f += totalColumnText();
}
// Weergeven als integer of als getal met twee decimalen.
if (columns[i].total)
{
if (totalShow)
{
html_f += totalShow(columns[i], rowNum);
}
else
{
html_f += ResultsetTable.formatValue(columns[i].totalsum, columns[i]);
}
}
else if (columns[i].generaltotal)
{
html_f += ResultsetTable.formatValue(columns[i].generaltotalsum, columns[i]);
}
else if (columns[i].generalaverage)
{
html_f += ResultsetTable.formatValue(columns[i].generaltotalavg, {datatype: "float", decimals: 2});
}
else if (columns[i].average && columns[i].totalRows > 1) // geen gemiddelde tonen van 1 resultaat
html_f += ResultsetTable.formatValue((columns[i].totalsum / columns[i].totalRows), {datatype: "float", decimals: 2});
else
html_f += "";
if ((i < columns.length - 1) && !columns[i + 1].combine)
html_f += "</td>";
}
}
// Nog extra kolom headers voor de flexkenmerken
// Flexkenmerken tonen bij isPrinting, isExcel of showProperties
if (this.printFlex && this.propertiesColumn == null)
{
html_f += "<td></td>";
}
html_f = balanceCloseTag("td", html_f);
html += html_f + "</tr>";
}
}
return html;
}
function balanceCloseTag(tagname, chtml)
{ // Als het aantal tag-open groter is dan het aantal tag-close dan een tag-close toevoegen.
var tag_open = chtml.toLowerCase().split("<"+tagname.toLowerCase());
var tag_close = chtml.toLowerCase().split("/"+tagname.toLowerCase()+">");
if (tag_open.length > tag_close.length)
{
chtml += "</"+tagname+">";
}
return chtml;
}
function __rsEndTable()
{
Response.Write("\n</table>");
Response.Write("\n</div> <!-- for DIV id='rstable' -->");
}
function __rsAddColumn(column)
{
this.columns.push(column);
}
function __rsStartPrint()
{
if (!isPrinting) return;
if (getQParamInt("formail", 0) == 1)
{
var logo_fileName = "cid:" + S("fac_logo_file");
}
else
{
var logo_fileName = custpath + "/" + S("fac_logo_file");
}
Response.Write('\n<div id="printheader">');
Response.Write('\n<table id="head"><tr>');
Response.Write('\n<td align="left">');
Response.Write('<img alt="' + L("lcl_photos") + '" src="' + logo_fileName+ '"></TD>');
Response.Write('\n<td align="right">');
Response.Write('\n<table id="right">');
Response.Write('\n <tr><td colspan="2" id="titel">' + (this.title||"") + '</td></tr>');
Response.Write('\n <tr><td>' + L("lcl_name") + ' :</td><td>' + safe.html(user.naam()) + ' </td></tr>');
Response.Write('\n <tr><td>' + L("lcl_date") + ' :</td><td>' + toDateString(new Date()) + ' </td></tr>');
Response.Write('\n</table>');
Response.Write('\n</td>');
Response.Write('\n</tr></table>');
Response.Write('\n</div>');
}
function __rsEndPrint()
{
if (isPrinting)
{
var prtDate = toDateTimeString(new Date());
Response.Write('\n<div id="printfooter">');
Response.Write('\n<table id="foot"><tr>');
Response.Write( '\n<td>' + (this.title||"") + '</td>'); // deze this.title lijkt intussen verloren gegaan
Response.Write( '\n<td align="right">' + toDateTimeString(new Date()) + '</td>');
Response.Write( '\n</tr></table>');
Response.Write('\n</div>');
if (p_autosortby)
{
var sortfn = autosortbyrev?"sorttable.doSortRev":"sorttable.doSort";
Response.Write('<script>$(function () { if ($("#autosortbyme").length) { '+sortfn+'.apply($("#autosortbyme")[0]) };window.print() });</script>');
}
else
Response.Write('<script>window.print();</script>'); // Zonder jQuery
}
}
///////////
// Column
///////////
var PRINTING_ONLY = 1;
var VIEW_ONLY = 2;
var PRINT_AND_VIEW = PRINTING_ONLY + VIEW_ONLY;
function Column(params)
{
if (!params) params = {};
this.caption = params.caption;
this.title = params.title;
this.filter = params.filter;
this.content = params.content;
this.image = params.image;
this.action = params.action;
this.tooltip = params.tooltip;
this.thClass = params.thClass;
this.columnClass = params.columnClass;
this.classList = params.classList;
this.customSort = params.customSort;
this.align = params.align;
this.purpose = params.purpose ? params.purpose : PRINT_AND_VIEW;
this.hidden = params.hidden;
this.showDefault = "showDefault" in params ? params.showDefault : true;
this.datatype = params.datatype;
this.decimals = params.decimals;
this.trimZeros = params.trimZeros;
this.total = params.total;
this.average = params.average;
this.amount = null; // Voor INTERN gebruik: is de integerwaarde van content, indien de kolomwaarden opgeteld moeten worden.
this.urlkey = null; // Voor INTERN gebruik: als er een urlkey is meegegeven.
this.totalsum = 0;
this.average = 0.00;
this.generaltotalsum = 0;
this.generaltotalavg = 0.00;
this.name = params.name;
this.nowrap = params.nowrap;
this.orgContent = params.content;
this.nomidnight = params.nomidnight;
this.filename = params.filename; // voor csv/xlsx
// Neem alle meegegeven parameters mee.
for (param in params)
{
if (param == "content" && params.content)
{
if (params.content instanceof Function)
{
this.content = params.content;
this.amount = params.fnAmount || params.content;
this.urlkey = params.fnUrlkey || -1;
}
else
{
this.content = function (oRs) { return ResultsetTable.formatValue(oRs.Fields(params.content).Value, this) } ;
this.amount = function (oRs) { return oRs.Fields(params.content).Value };
this.urlkey = function (oRs, processParams, params) { return params.dataset? ResultsetTable.getUrlKey(oRs.Fields("scf_urlkey").Value, params.content) : -1; };
}
}
else
this[param] = params[param];
}
if (!isPlain && this.prettydate)
this.prettydate = false;
}
// Levert een html-safe waarde op
ResultsetTable.formatValue = function (val, params) //datatype, decimals)
{
if (val == null)
{
if (isXMLXSL || isCSV || isCSV2XLSX)
return "";
else
return "&nbsp;";
}
// Vanuit API2 model
if (typeof val == "object" && "name" in val)
{
val = val["name"];
params.datatype = null; // default string
}
// Eerst de geforceerde datatypes
switch (params.datatype)
{
case "date" : return toDateString(val, isExcel||isCSV || isCSV2XLSX, params.prettydate); // isExcel-->noDay
case "datetime": return toDateTimeString(val, params.withSeconds, isExcel||isCSV || isCSV2XLSX, params.prettydate, params.nomidnight);
case "time" : { val = toTimeString(val, params.withSeconds);
if (params.datatype == "time" && params.nomidnight && val == "00:00")
val = "";
return val;
}
case "processingtime": { if (val["duration"] == null)
val = "";
else
val = val["duration"] + " " + (val["unit"]=="U"?L("lcl_mld_hours"):L("lcl_mld_days"));
return val;
}
case "currency": return safe.curr(val);
case "float" : return safe.displayfloat(val, params.decimals, params.trimZeros);
case "number" : return val;
case "html" : return val;
}
// Autotypering "datum"
if (typeof val == "date" || val instanceof Date)
return toDateString(val, isExcel, params.prettydate);
if (!val)
return "";
if (typeof val != "string")
{ // Je raakt bijvoorbeeld de rechtse uitlijning van number-velden kwijt
__Log("Ongespecificeerd datatype van veld '{0}'{1} is {2}, fallback naar string".format(params.caption, typeof params.orgContent=='string'?' (' + params.orgContent + ')':"", typeof val), "#FF0");
val = String(val);
}
if (params.secret)
return "<span title='{0}'>".format(safe.htmlattr(val)) + I("fa-eye fa-lg") + "</span>";
val = shared.stripbbcodes(val);
if (isXMLXSL || isCSV || isCSV2XLSX)
return val; // DOM lost encoding wel op of we doen safe.csv.
// default datatype is "string"
val = String(val).replace(/[\n\r]+/g,"\n"); // Compact, geen lege regels tonen
var safeval = __rsTruncMore(val, {isPrinting: isPrinting, isExcel: isExcel}); // Zorgt voor het afkappen van de tekst en het toevoegen van ... meer.
return safeval;
}
ResultsetTable.getUrlKey = function (urlval, contenttext)
{
var urlkey = urlval? urlval[contenttext] || -1 : -1;
return urlkey;
}
ResultsetTable.prototype.truncMore = function __rsTruncMore(pval, pparams)
{
if (pparams.isExcel)
{ // Hier geen safe.html omdat we voor Excel de <br> naar \n vertaling niet kunnen hebben.
// Met <br> krijg je een nieuwe rij in excel.
return Server.HTMLEncode(pval);
}
if (pparams.isPrinting || S("rs_maxchar") < 0 || pval.length < S("rs_maxchar") * 1.20) // 'Meer' moet minstens 20% extra tekst opleveren.
return safe.html(pval); // simpelweg hele tekst
// Oke, op scherm afkappen na S("rs_maxchar") karakters.
// Probeer op de eerste spatie maar die moet wel binnen 20% karakters komen
var fullval = pval;
var spatie = String(pval).substr(S("rs_maxchar")).indexOf(" ");
if (spatie < 0 || spatie > S("rs_maxchar")/5)
spatie = 0;
pval = fullval.substr(0, S("rs_maxchar") + spatie + 1);
// Pas op: pval is al "html-safe" terwijl we dat voor afkappen niet kunnen hebben?
// In ieder geval geen safe.htmlattr.
var safeval = safe.html(pval)
+ "<span class='rsTruncmore' " // Dubbel encoderen hieronder, anders html-injections was achter de Meer... mogelijk
+ " resttxt='" + safe.htmlattr(safe.html(fullval.substr(S("rs_maxchar") + spatie + 1))) + "'"
+ " title='" + L("lcl_rs_truncmore") + "'"
+ " onclick='return expandTruncate(event, this)'"
+ ">" + L("lcl_rs_truncated") + "</span>";
return safeval;
}
function ResultsetTable.prototype.myRs(fn, oRs)
{
if (fn instanceof Function)
{
return fn(oRs, this.processParams);
}
else
{
return oRs.Fields(fn).Value;
}
}
%>