Files
Facilitor/APPL/PDA/resultset_table.inc
Koen Reefman f656e1a392 MRUS#90018 SAYT filter terug in mobile lijsten
svn path=/Website/branches/v2025.2/; revision=69913
2025-08-05 09:09:53 +00:00

574 lines
18 KiB
HTML

<% /*
File: PDA/resultset_table.inc
$Revision$
$Id$
PAS OP: Soms gebruikt in combinatie met shared/data_recordset.inc.
Zie het commentaar daarin met betrekking tot het case-sensitive
zijn van bijvoorbeeld oRs.EOF
*/
%>
<%
function ResultsetTable(params)
{
this.emptySetString = L("lcl_empty_rstable");
this.sql = null;
this.dataset = null; // of sql of dataset meegeven. Data is dan een array van objecten met properies
this.ID = null;
this.rowNum = 0;
this.showAll = null;
// Mobile params
this.noSearch = null;
this.searchInputHtml = "<input type='search' class='list-group-filter " + MOBILE_UI_CLASSES.input + "' placeholder='Filter items...'>";
this.inset = false;
this.Counter = {};
// Card layout params
this.wrapper = { "layout": "vertical" };
var param;
// Neem alle meegegeven parameters mee.
for (param in params) {
this[param] = params[param];
}
}
/*
ResultsetTable heeft overigens niets meer met <table>'s te maken
De rows zijn dan ook geen <tr>'s, maar list items (<li>)
*/
ResultsetTable.prototype.processResultset = __rsProcessResultset;
ResultsetTable.prototype.makeTableRow = __rsMakeTableRow;
ResultsetTable.prototype.countHistogram = __rsCountHistogram;
ResultsetTable.prototype.enableMultiactions = __rsEnableMultiactions;
/*global*/ isData = false;
function __rsProcessResultset(processParams)
{
this.processParams = processParams;
var copy;
if (this.sql)
{
var oRs = Oracle.Execute(this.sql);
}
else
{
/*global*/isData = true;
var oRs = new data_recordset( this.dataset );
}
if (oRs == null || oRs.EOF)
{
if (!this.emptyWhenNoResult)
Response.Write("<p>" + this.emptySetString + "</p>");
if (this.sql) {
oRs.Close();
}
return -1;
}
var lastGroup, lastDivider, lastIconHtml = null;
var html = "";
var filterCutOff = S("pda_list_show_filter_from");
var lines = [];
// Heeft groupSelect een waarde, dan wordt voor deze group de lijst getoond.
if (this.groupSelect == "") {
html += __multiActions()
+ "<section class='list-group'" + (this.ID ? " id='" + this.ID + "'" : "") + ">";
}
var cnt = 0;
var trueCount = 0;
var hasResults = false;
var initKeyDone = this.initKey == null;
if (this.groupColumn && this.groupSelect == "")
{ // we tonen alleen het aantal regels. Laat dan alle complexe processing achterwege
ResultsetTable.prototype.makeTableRow = function __rsCountTableRow(oRs, cnt) { return "dummy" };
} else if (this.layout === "card") {
ResultsetTable.prototype.makeTableRow = __rsMakeCard;
}
if (this.multiactions && this.multiactions.length > 0) {
this.hasMultiactions = true;
for (var i = 0; i < this.multiactions.length; i++) {
if (this.multiactions[i].fnCheckIfAny) { // Conditioneel aan? Begin dan eerst uit
this.multiactions[i].enabled = false;
} else {
this.multiactions[i].enabled = true;
}
}
}
for (cnt = 0; (cnt < (S("qp_maxrows_mobile")) || this.showAll ) &&
(cnt < S("qp_maxrows2")) &&
!oRs.EOF; cnt++)
{
if (this.fnDataFilter && !this.fnDataFilter(oRs))
{
oRs.MoveNext();
continue;
}
else if (!hasResults)
hasResults = true;
if (this.dividerColumn)
{
var safenextDivider = __fnContent(this.dividerColumn)(oRs);
if (safenextDivider != lastDivider) {
lines.push("<div class='list-group-item list-group-header'><h2>" + safenextDivider + "</h2></div>");
}
lastDivider = safenextDivider;
}
if (!initKeyDone && this.initKey && this.keyColumn && this.initKey == __fnContent(this.keyColumn)(oRs))
{
lines.unshift(this.makeTableRow(oRs, cnt, false));
initKeyDone = true;
}
else
lines.push(this.makeTableRow(oRs, cnt, false));
trueCount++;
if (this.buildHistogram)
this.countHistogram(oRs);
if (this.multiactions) {
this.enableMultiactions(oRs);
}
if ((this.groupColumn || (this.singleLink && trueCount < 2)) && this.linkColumn)
var lastLink = __fnContent(this.linkColumn)(oRs);
var numberInGroup = -1;
if (this.groupColumn)
{
lastGroup = __fnContent(this.groupColumn)(oRs);
if (this.iconColumn) {
lastIconHtml = "";
var icon = __fnContent(this.iconColumn)(oRs, this.processParams)
if (icon) {
var iconHtml = "";
if (icon.match(/^</)) { // Ik ben al een plaatje :) of safe html, bv een <div> of <i>
iconHtml = icon;
} else if (icon.match(/^fa-/)) {
iconHtml = I(icon + " fa-2x");
} else {
iconHtml = '<img loading="lazy" src="' + safe.htmlattr(icon) + '" alt="' + L("lcl_photos") + '">';
}
lastIconHtml = "<div class='list-illustration flex-center'>" + iconHtml + "</div>";
}
}
if (this.numberInGroup)
numberInGroup = __fnContent(this.numberInGroup)(oRs);
}
oRs.MoveNext();
if (trueCount === 1 && oRs.EOF && this.singleLink && this.linkColumn && lastLink)
{
trueCount = -1;
break;
}
if (this.groupColumn)
{
var overLimit = (cnt+1 >= (S("qp_maxrows_mobile")) && !this.showAll ) ||
(cnt+1 >= S("qp_maxrows2"))
if (!oRs.EOF)
var nextGroup = __fnContent(this.groupColumn)(oRs);
// In jquery-mobile-1.4.2 zijn geneste lijsten niet meer toegestaan.
// De *_list.asp wordt nu geplitst: is groupSelect leeg dan worden de groepen getoond
// Heeft groupSelect een waarde, dan wordt voor deze group de lijst getoond.
if (this.groupSelect == "")
{ // Toon de groepen
if (oRs.EOF || overLimit || nextGroup != lastGroup)
{
html += "<a href='" + lastLink + "' class='list-group-item list-group-item-action'>"
+ (this.iconColumn ? lastIconHtml : "")
+ "<h6 class='limit-lines-2'>" + lastGroup + "</h6>"
+ "<div class='list-aside badge text-bg-secondary'>" + (numberInGroup > 0 ? numberInGroup : lines.length) + "</div>"
+ "</a>";
lines = [];
}
}
else
{ // Toon de lijst van een geselecteerde groep
if (oRs.EOF || overLimit)
{
html += __multiActions()
if (!this.noSearch) {
html += this.searchInputHtml;
}
html += "<section class='list-group'" + (this.ID ? " id='"+this.ID + "'" : "") + ">"
+ lines.join("\n")
+ "</section>";
lines = [];
}
}
}
}
if (trueCount === -1) // 1 result in list, which we should click instantly
{
Response.Write("<script>$(function() { window.location.href = \""+ lastLink.replace(new RegExp("\"", "g"), "'") +"\"; })</script>"); // " (even aantal aanhalingstekens i.v.m. formatting editter).
if (this.sql) {
oRs.Close();
}
return -1;
}
if (cnt === 0 || !hasResults)
{
Response.Write("<p>" + this.emptySetString + "</p>");
if (this.sql) {
oRs.Close();
}
return -1;
}
if (this.groupSelect == "")
html += "</section>";
if (this.layout === "card") {
html += CARDS_WRAPPER_START_HTML(this.wrapper)
+ lines.join("")
+ CARDS_WRAPPER_END_HTML(this.wrapper);
} else if (!this.groupColumn) {
var html = __multiActions();
if (!this.noSearch && cnt > filterCutOff) {
html += this.searchInputHtml;
}
html += "<section class='list-group'" + (this.ID ? " id='" + this.ID + "'" : "") + ">"
+ lines.join("\n")
+ "</section>";
}
if (!oRs.EOF) // en dus overLimit
{
var maxrows = (this.showAll ? S("qp_maxrows2") : S("qp_maxrows_mobile"));
html += __multiActions()
+ "<section class='list-group'><div class='list-group-item'>" + L("lcl_max_lines_reached").format(maxrows) + "</div></section>";
} else if (false && /* future-use */ cnt > 5) {
Response.Write('<script>$(function() { $(".count-badge").text("' + cnt + '"); });</script>');
}
Response.Write(html);
if (this.sql) {
oRs.close();
}
if (this.buildHistogram)
return this.Counter;
else
return this.rowNum; // simpel return aantal rows
}
function __multiActions() {
var html = "";
var multiactionCount = 0;
for (var i in this.multiactions) {
multiactionCount = multiactionCount + (this.multiactions[i].enabled ? 1 : 0);
}
if (multiactionCount) {
html += "<script>"
+ " function doAm(event, fnAction) {"
+ " var key_arr = [];"
+ " $('.bulkable.bulk-selected').each((i, elem) => {"
+ " key_arr.push($(elem).data('row-key'));"
+ " });"
+ " if (key_arr.length === 0) {"
+ " return;"
+ " }"
+ " var confirm_text = key_arr.length === 1 ? L(\"lcl_shared_doaction1\") : L(\"lcl_shared_doaction\");"
+ " confirm_text = confirm_text.format(event.currentTarget.dataset.title, key_arr.length);"
+ " FcltMgr.confirm(confirm_text, _ => window[fnAction](key_arr));"
+ " }"
+ "</script>"
+ "<div class='multiactions'>"
+ " <span class='left multiaction-wrapper'>"
+ " <span class='cancel multiaction tappable'>" + I("fa-times fa-lg") + "</span>"
+ " <span class='multiaction-count' data-count='0'></span>"
+ " </span>"
+ " <span class='right multiaction-wrapper'>"
for (var i in this.multiactions) {
if (this.multiactions[i].enabled) {
html += "<span class='multiaction tappable' onclick='doAm(event, \"" + safe.htmlattr(this.multiactions[i].action) + "\")' data-title='" + safe.htmlattr(this.multiactions[i].caption) + "'>"
+ I(this.multiactions[i].icon + " fa-lg") + "</span>"
}
}
html += " </span>"
+ "</div>";
}
return html;
}
function __rsMakeCard(oRs) {
// HIER START EEN NIEUWE REGEL
var data = {};
if (this.data) {
for (var i in this.data) {
data[this.data[i]] = oRs(this.data[i]).Value;
}
}
var icon = "";
var cardClass = "";
if (this.hasMultiactions) {
cardClass = "bulkable";
}
if (this.swipeable) {
cardClass = cardClass + (cardClass ? " " : "") + "swipeable";
}
if (this.iconColumn) {
icon = __fnContent(this.iconColumn)(oRs, this.processParams);
if (icon) {
if (icon.match(/^fa-/)) {
icon = I(icon);
} else if (!icon.match(/^</)) { // Zal wel een src van een plaatje zijn dan
icon = '<img loading="lazy" src="' + safe.htmlattr(icon) + '" alt="' + L("lcl_photos") + '">';
}
cardClass = cardClass + (cardClass ? " " : "") + "with-icon icon-color";
}
}
var horiz = this.wrapper.layout === "horizontal";
var line = "";
if (horiz) {
line += "<div class='row g-0 h-100 flex-nowrap'>";
}
if (icon) {
line += " <div class='col card-illustration flex-center'>" + icon + "</div>";
}
line += " <div class='col " + (horiz ? "card-content" : "card-body") + "'>";
line += " <div class='card-title'>";
if (this.headerColumn) {
line += __fnContent(this.headerColumn)(oRs, this.processParams);
}
line += " </div>";
line += " <div class='card-descr'>";
if (this.contentColumn) {
line += __fnContent(this.contentColumn)(oRs, this.processParams);
}
line += " </div>";
line += " </div>";
if (horiz) { // Sluit de row af
line += "</div>";
}
var cardParams = {
data: data,
cls: cardClass,
noPadding: true
};
// Klikbaar als <a>nchor
if (this.linkColumn) {
var lnk = __fnContent(this.linkColumn)(oRs, this.processParams);
if (lnk) {
line = "<a href='" + safe.htmlattr(lnk) + "' class='card-link' data-ajax='false'>" + line + "</a>";
cardParams.card_class = "tappable";
}
}
// Wrap het in een CARD
line = CARD_START_HTML(cardParams)
+ line
+ CARD_END_HTML(cardParams);
this.rowNum++;
return line;
}
function __rsMakeTableRow(oRs)
{
// HIER START EEN NIEUWE REGEL
var line = "";
/* Layout;
___________________________
| | headerColumn |
| Icon | contentColumn |
|______|___________________|
*/
this.rowNum ++;
// Icon
var iconHtml = "";
if (this.iconColumn) {
var icon = __fnContent(this.iconColumn)(oRs, this.processParams)
if (icon) {
if (icon.match(/^<img/)) { // Ik ben al een plaatje :)
iconHtml = icon;
} else if (icon.match(/^fa-/)) {
iconHtml = '<span class="pda-list-icon">' + I(icon + " fa-2x") + '</span>';
} else if (icon.match(/^</)) { // safe html, bv een <div> of <i>
iconHtml = '<span class="pda-list-icon">' + icon + '</span>';
} else {
iconHtml = '<img loading="lazy" src="' + safe.htmlattr(icon) + '" alt="' + L("lcl_photos") + '">';
}
iconHtml = "<div class='list-illustration flex-center'>" + iconHtml + "</div>";
}
}
// Header
var headerHtml = "<div class='list-header text-primary'>";
if (this.headerColumn) {
var headerText = __fnContent(this.headerColumn)(oRs, this.processParams);
if (headerText) {
headerHtml += "<h6 class='limit-lines-2'>" + headerText + "</h6>";
}
}
if (this.detailColumn) {
var detailText = __fnContent(this.detailColumn)(oRs, this.processParams);
if (detailText) {
headerHtml += "<div class='list-header-detail text-secondary'>" + detailText + "</div>";
}
}
headerHtml += "</div>";
if (this.subheaderColumn) {
var subheaderText = __fnContent(this.subheaderColumn)(oRs, this.processParams);
if (subheaderText) {
headerHtml += "<div class='subheader'>" + subheaderText +"</div>";
}
}
// Body
var contentHtml = "<div class='list-body'>";
if (this.asideColumn) {
var asideText = __fnContent(this.asideColumn)(oRs, this.processParams);
if (asideText) {
contentHtml += "<div class='list-aside badge text-bg-secondary'>" + asideText + "</div>";
}
}
contentHtml += "</div>";
line = iconHtml + "<div class='list-content flex-column'>" + headerHtml + contentHtml + "</div>";
var thisRowClass = "flex-center-y gap-3 list-group-item";
if (this.hasMultiactions) {
thisRowClass += " bulkable";
}
if (this.rowClass) {
thisRowClass += " " + __fnContent(this.rowClass)(oRs, this.processParams);
}
var thisRowDataAttribute = "";
if (this.multiactions && this.keyColumn) {
thisRowDataAttribute = " data-row-key='" + oRs(this.keyColumn).Value + "'";
}
var linkAttrHtml = null;
if (this.linkColumn) {
linkAttrHtml = "href='" + safe.htmlattr(__fnContent(this.linkColumn)(oRs, this.processParams)) + "'";
} else if (this.click) {
linkAttrHtml = "href='#' onclick='" + safe.htmlattr(__fnContent(this.click)(oRs, this.processParams)) + "'";
}
if (linkAttrHtml) {
thisRowClass += " list-group-item-action";
return "<a " + linkAttrHtml + " class='" + thisRowClass + "'" + thisRowDataAttribute + ">" + line + "</a>";
}
return "<div class='" + thisRowClass + "'" + thisRowDataAttribute + ">" + line + "</div>";
}
function __rsCountHistogram(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 __rsEnableMultiactions(oRs) {
for (var i = 0; i < this.multiactions.length; i++) {
if (this.multiactions[i].enabled === false) {
this.multiactions[i].enabled = this.multiactions[i].fnCheckIfAny(oRs);
}
}
}
// Levert een html-safe waarde op
ResultsetTable.formatValue = function (val, params) //datatype, decimals)
{
if (val == null)
{
return "";
}
if (typeof val == "object" && "name" in val) // Vanuit API2
val = val["name"];
// Eerst de geforceerde datatypes
switch (params.datatype)
{
case "date" : return toDateString(val);
case "datetime": return toDateTimeString(val, false);
case "time" : { val = toTimeString(val);
if (params.datatype == "time" && params.nomidnight && val == "00:00")
val = "";
return val;
}
case "currency": return safe.curr(val);
case "float" : return safe.displayfloat(val, params.decimals);
case "number" : return val;
case "html" : return val;
}
// Autotypering "datum"
if (typeof val == "date" || val instanceof Date)
return toDateTimeString(val); // PF: heb ik ff getweakt, moet natuurlijk niet zo (date vs datetime)
if (!val)
return "";
// default datatype is "string"
val = String(val);
val = shared.stripbbcodes(val);
return safe.html(val); // altijd simpelweg hele tekst
}
function __fnContent(fnContent)
{
if (fnContent instanceof Function)
return fnContent;
return function (oRs)
{
return ResultsetTable.formatValue(oRs.Fields(fnContent).Value, {datatype: this.datatype, decimals: this.decimals, nomidnight: this.nomidnight})
} ;
}
%>