diff options
| author | Niklas Olmes <niklas@olmes.de> | 2026-04-24 19:30:00 +0200 |
|---|---|---|
| committer | Niklas Olmes <niklas@olmes.de> | 2026-04-24 19:30:00 +0200 |
| commit | cdea8caa5617f0cb77bcbc9803759abd2df50644 (patch) | |
| tree | 2f7f1bd3af3b2396baf5403ad1a7ad00bcb7fae9 /autotable.php | |
Diffstat (limited to 'autotable.php')
| -rw-r--r-- | autotable.php | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/autotable.php b/autotable.php new file mode 100644 index 0000000..93307f7 --- /dev/null +++ b/autotable.php @@ -0,0 +1,1103 @@ +<?php +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +?> +<? +/* vim: set ts=4 sw=4 et : */ + +require_once __DIR__ . "/auto_common.php"; + +(function () use ($r, $id, $title, $subtitle, &$num_rows, $top, $bottom, $alwaysbottom, $off, $order, $checkboxes, $links, $rowcallback, $norefresh, $editable, $types, $entrytable, $callback, $callback_heading, $json, $jsoncallback, $pii, $nospinner, $ajax, $sql, $colsql, $makeseq, $thdef, $nochosen, $idcell, $idcellreal, $nofilter, $getthdef, $insert, $noautolinks, $nodefaultlinks) { + if (!isset($id) || $id == "") { + $pwsql = stristr($sql, ' WHERE ', true); + if ($pwsql === false || $pwsql === '') { + $pwsql = $sql; + } + $id = substr(sha1($pwsql), 0, 16); + } + + if (!isset($order) || $order == "") + $order = '[[1, "desc"]]'; + + if (!isset($colsql) || $colsql == "") + $colsql = $sql . " LIMIT 1"; + + if (!isset($nospinner)) + $nospinner = false; + + if (!isset($ajax)) + $ajax = false; + + if (!isset($thdef)) + $thdef = false; + + if (!isset($nochosen)) + $nochosen = false; + + if (!isset($nofilter)) + $nofilter = false; + + if (!$nospinner) + include_once __DIR__ . '/loading_modal.php'; + + if (!isset($editable)) + $editable = []; + if (!isset($types)) + $types = []; + if (!isset($json)) + $json = []; + if (!isset($off)) + $off = false; + if (!isset($makeseq)) + $makeseq = false; + if (!isset($alwaysbottom)) + $alwaysbottom = false; + + $pii = getPii($pii); + + if (!isset($nodefaultlinks)) + $nodefaultlinks = false; + + if (!$nodefaultlinks) + $links = getLinks($links); + + if (!isset($idcell)) + $idcell = false; + + if (!isset($idcellreal)) + $idcellreal = $idcell; + + if (isset($getthdef) && $getthdef) { + global $mysqli; + $stmt = $mysqli->prepare($sql); + $stmt->execute(); + $r = $stmt->get_result(); + } + + if (!isset($noautolinks)) + $noautolinks = false; + + if (!isset($insert)) + $insert = pathinfo(basename(__FILE__), PATHINFO_FILENAME); +?> + + <div class="autotable_containment" id="autotable_containment_<?=$id?>"> + <div style="padding: 0; margin: 0;"></div> + +<? + if (isset($title)) { +?> + <h2 id="anchor_<?=$id?>" data-table="<?=$id?>" class="prevent autotable_title" onclick="toggleTable('<?=$id?>');" style="cursor: pointer;"> + <?=$title?> + <span id="<?=$id?>Count"></span> + <i <? if ($off) { echo 'style="display: none;"'; } ?> id="<?=$id?>Table_off" class="fas fa-toggle-on"></i> + <i <? if (!$off) { echo 'style="display: none;"'; } ?> id="<?=$id?>Table_on" class="fas fa-toggle-off"></i> + </h2> + + <script> +<? minStart(); ?> + function toggleTable(id, forceon) { + if (typeof forceon === 'undefined') + forceon = false; + + if (forceon) { + $('#' + id + 'Table').show(); + $('#' + id + 'Table_on').hide(); + $('#' + id + 'Table_off').show(); + } else { + $('#' + id + 'Table').toggle(); + $('#' + id + 'Table_on').toggle(); + $('#' + id + 'Table_off').toggle(); + } + $('#' + id).trigger('resize'); + + if ($('#' + id + 'Table:visible')[0]) localStorage.setItem(location.href + '_' + id + 'Table', 'true'); + else localStorage.setItem(location.href + '_' + id + 'Table', 'false'); + + setTimeout(function () { + $(window).resize(); + }, 100); + } + + $(document).ready(function () { +<? if ($off) { ?> + if (localStorage.getItem(location.href + '_<?=$id?>Table') == 'true') + toggleTable('<?=$id?>'); +<? } else { ?> + if (localStorage.getItem(location.href + '_<?=$id?>Table') == 'false') + toggleTable('<?=$id?>'); +<? } ?> + }); +<? minEnd(); ?> + </script> +<? + } +?> + + <div <? if ($off) { echo 'style="display: none;"'; } ?> id="<?=$id?>Table"> +<? if (isset($subtitle)) { ?> + <?=$subtitle?> +<? } ?> + <span id="<?=$id?>Empty" style="display: none; padding-left: .5em;">Keine Ergebnisse!</span> + <div id="<?=$id?>TableInner"> + <progress id="<?=$id?>TableProgress"></progress> + +<? + if (isset($top)) echo $top; + + if ((!($ajax && $thdef)) && ($r->num_rows < 1)) { +?> + <span style="padding-left: .5em;">Keine Ergebnisse!</span> + <script> +<? minStart(); ?> + $('#<?=$id?>TableProgress').hide(); + $('#<?=$id?>Count').html('<sup><small>(0/0)</small></sup>'); + $('body').css('overflow', 'auto'); + $(document).ready(function () { $('#<?=$id?>Actions').hide(); }); +<? if (!$nospinner) { ?> + $('#loading_modal').hide(); +<? } ?> +<? minEnd(); ?> + </script> +<? + if ($alwaysbottom) { +?> + <?=$bottom?> +<? + } +?> + </div> + </div> +<? + } else { + if (!$norefresh) { +?> + <div class="small" id="tablereordered-<?=$id?>" style="display: none; color: darkred; margin-top: .5em; margin-bottom: .5em;"> + <b>Spalten neu geordnet. Für die Filterfunktionen muss anschließend die <button class="small" style="background: orange;" onclick='window.location = window.location;'>Seite neu geladen werden</button></b> + </div> + + <button class="small" id="tablereload-<?=$id?>"><i class="fas fa-sync-alt"></i> Aktualisieren</button> + <button class="small" id="tablereset-<?=$id?>"> + <div class="tooltip"> + <span class="tooltiptext">Alle Einstellungen und Filter verwerfen, anschließend Tabelle neuladen</span> + <i class="fas fa-undo-alt"></i> Reset + </div> + </button> + <button class="small lila" id="tableexcel-<?=$id?>"> + <div class="tooltip"><span class="tooltiptext">Aktuelle Seite nach Excel exportieren</span><i class="fas fa-magic"></i> <i class="fas fa-eye"></i> <i class="fas fa-file-excel"></i></div> + </button> +<? if ($checkboxes) { ?> + <button class="small lila" id="tableexcelsel-<?=$id?>"> + <div class="tooltip"><span class="tooltiptext">Markierte nach Excel exportieren</span><i class="fas fa-magic"></i> <i class="fas fa-check"></i> <i class="fas fa-file-excel"></i></div> + </button> +<? } ?> +<? +include __DIR__ . '/autotable_fontsettings.php'; +include __DIR__ . '/autotable_explain.php'; +?> + + <div style="display: none;"> + <form id="<?=$id?>Excel" action="/db/main/excel.php" method="post"> + <input id="<?=$id?>ExcelName" name="name" type="hidden" value=""> + <input id="<?=$id?>ExcelHeading" name="heading" type="hidden" value=""> + <input id="<?=$id?>ExcelLines" name="lines" type="hidden" value=""> + </form> + </div> + +<? + } +?> + <style> + #<?=$id?>_wrapper .dataTables_scrollBody { + max-height: calc(100vh - 16em); + } + </style> + + <table id="<?=$id?>" border="0" class="autotable display nowrap" style="width: 100%; display: none;"> + <thead> + <tr> +<? + if ($checkboxes || $ajax) { +?> + <th></th> +<? + } + if ($makeseq) { +?> + <th>#</th> +<? + } + + $autotable_i = 0; + if (!$thdef) { + $l = $r->fetch_object(); + foreach ($l as $k => $v) { + $bk = str_replace(' ', '<br />', $k); + if (substr($k, 0, 1) === '%') { + $k = substr($k, 1); + } + + if ($editable[$k]) { +?> + <th data-realname="<?=$editable[$k]?>" data-displayname="<?=$k?>" class="autotable_<?=$id?>_<?=$editable[$k]?> at_col_<?=$editable[$k]?> editable <? if (isset($types[$k]) && is_array($types[$k])) { ?>select no-sort<? } ?>"><?=$bk?>✎</th> +<? + } else { +?> + <th data-displayname="<?=$k?>" class="autotable_<?=$id?>_<?=$k?> at_col_<?=$k?> <? if (in_array($k, $editable)) { ?>editable<? } ?> <? if (isset($types[$k]) && is_array($types[$k])) { ?>select no-sort<? } ?>"><?=$bk?><? if (in_array($k, $editable)) { ?>✎<? } ?></th> +<? + } + } + if ($callback) { +?> + <th><?=$callback_heading?></th> +<? + } + } else { + foreach ($thdef as $k) { + $bk = str_replace(' ', '<br />', $k); + if ($editable[$k]) { +?> + <th data-realname="<?=$editablele[$k]?>" data-displayname="<?=$k?>" class="autotable_<?=$id?>_<?=$editable[$k]?> at_col_<?=$editable[$k]?> editable"><?=$bk?>✎</th> +<? + } else { +?> + <th data-displayname="<?=$k?>" class="autotable_<?=$id?>_<?=$k?> at_col_<?=$k?> <? if (in_array($k, $editable)) { ?>editable<? } ?>"><?=$bk?><? if (in_array($k, $editable)) { ?>✎<? } ?></th> +<? + } + } + } +?> + </tr> + </thead> + +<? if (!$ajax) { ?> + <script> + $('#<?=$id?>TableProgress').prop('max', <?=$r->num_rows?>); + $('#<?=$id?>TableProgress').prop('value', 0); + </script> + <tbody> +<? + do { + $autotable_i++; + if (!$nospinner && $autotable_i % 100 == 0) { +?> + <script>$('#progress').html('<?=$autotable_i?> Einträge von <?=$r->num_rows?> verarbeitet'); $('#<?=$id?>TableProgress').prop('value', <?=$autotable_i?>);</script> +<? + } + if (!$nospinner && $autotable_i % 100 == 0 && $autotable_i + 350 >= $r->num_rows) { +?> + <script>$('#progress').html('<?=$autotable_i?> Einträge von <?=$r->num_rows?> verarbeitet, initialisiere Tabelle'); $('#<?=$id?>TableProgress').prop('value', <?=$autotable_i?>);</script> +<? + } + if (!$nospinner && $autotable_i == $r->num_rows) { +?> + <script>$('#progress').html('Alle <?=$r->num_rows?> Einträge verarbeitet, initialisiere Tabelle'); $('#<?=$id?>TableProgress').prop('value', <?=$autotable_i?>);</script> +<? + } + if ($nospinner) { +?> + <script>$('#<?=$id?>TableProgress').prop('value', <?=$autotable_i?>);</script> +<? + } + + $dataid = ""; + if ($idcell) $dataid = $l->$idcell; + else if (isset($l->ID)) $dataid = $l->ID; + else if (isset($l->uid)) $dataid = $l->uid; + else if (isset($l->UID)) $dataid = $l->UID; + else if (isset($l->id)) $dataid = $l->id; + else if (isset($l->PersID)) $dataid = $l->PersID; + else if (isset($l->StipID)) $dataid = $l->StipID; + else if (isset($l->EventID)) $dataid = $l->EventID; + else if (isset($l->FoerdID)) $dataid = $l->FoerdID; + else if (isset($l->OrgaID)) $dataid = $l->OrgaID; + else if (isset($l->NotizID)) $dataid = $l->NotizID; + else if (isset($l->EmailID)) $dataid = $l->EmailID; + else if (isset($l->AppNewsID)) $dataid = $l->AppNewsID; + else if (isset($l->AppSettingID)) $dataid = $l->AppSettingID; + else if (isset($l->AppProfileID)) $dataid = $l->AppProfileID; + else if (isset($l->ETID)) $dataid = $l->ETID; + + if ($makeseq) $dataid = $autotable_i; + + $persid = ""; + if (isset($l->PersID)) $persid = $l->PersID; + + $stipid = ""; + if (isset($l->StipID)) $stipid = $l->StipID; + + $orgaid = ""; + if (isset($l->OrgaID)) $orgaid = $l->OrgaID; + + $foerdid = ""; + if (isset($l->FoerdID)) $foerdid = $l->FoerdID; + + $eventid = ""; + if (isset($l->EventID)) $eventid = $l->EventID; +?> + <tr data-seq="<?=$autotable_i?>" data-id="<?=$dataid?>" data-persid="<?=$persid?>" data-stipid="<?=$stipid?>" data-orgaid="<?=$orgaid?>" data-foerdid="<?=$foerdid?>" data-eventid="<?=$eventid?>"> +<? + if ($checkboxes) { +?> + <td></td> +<? + } + if ($makeseq) { +?> + <td><a href="#<?=$autotable_i?>"><?=$autotable_i?></a></td> +<? + } + + foreach ($l as $k => $v) { + if (substr($k, 0, 1) === '%') { + $v = utf8_encode(urldecode($v)); + $k = substr($k, 1); + } + if (isset($links[$k])) { +?> + <td class="autotable_<?=$id?>_<?=$k?>"><? if ($v != 0 || $v != '') { ?><a class="autolink" href="<?=$links[$k]?><?=$v?><? if (isset($_GET['iframe'])) { ?>?iframe<? } ?>"><?=$v?></a><? } ?></td> +<? + } else { +?> + <td class="autotable_<?=$id?>_<?=$k?> <? if (in_array($k, $pii)) { echo "pii"; } ?>" data-n="<? if ($editable && $editable[$k]) { echo $editable[$k]; } else { echo $k; } ?>"> +<? + if (in_array($k, $editable) || $editable[$k]) { + if (!isset($types[$k])) { +?> + <input type="text" class="editable" style="width: auto; font-size: 1em; border: 0; padding: 0; margin: 0; background: rgba(255, 255, 255, 0.1);" size="<?=strlen($v)?>" value="<?=$v?>"><span style="display: none;" class="indicator"><?=$v?></span> +<? + } else if ($types[$k] == 'date') { +?> + <input type="date" class="editable" value="<?=$v?>"><span style="display: none;" class="indicator"><?=$v?></span> +<? + } else if ($types[$k] == 'checkbox') { +?> + <input type="checkbox" class="editable" <? if ($v) { echo "checked"; } ?>><span style="display: none;" class="indicator"><?=$v?></span> +<? + } else if ($types[$k] == 'checkboxinverse') { +?> + <input type="checkbox" class="editable inverse" <? if ($v) { echo "checked"; } ?>><span style="display: none;" class="indicator"><?=$v?></span> +<? + } else if (is_array($types[$k])) { +?> + <select class="editable <? if ($types[$k][0] == 'reload') { ?>reload<? } ?>"> + <option value=""></option> +<? + foreach($types[$k][1] as $a => $b) { +?> + <option value="<?=$b['id']?>" <? if ($b['id'] == $v) { ?>selected<? } ?>><?=$a?><? if (isset($b['cn'])) { ?> - <?=$b['cn']?><? } ?></option> +<? + } +?> + </select> +<? + } + } else if (in_array($k, $json)) { + $jsoncallback($k, json_decode($v)); + } else { +?> + <?=$v?> +<? + } +?> + + </td> +<? + } + } + + if ($callback) { +?> + <td> +<? + $callback($dataid); +?> + </td> +<? + } +?> + </tr> +<? + } while (($l = $r->fetch_object())) +?> + </tbody> +<? } else { /* !$ajax */ ?> + <script>$('#progress').html('Initialisiere Tabelle');</script> +<? } ?> + + <tfoot> + <tr></tr> + </tfoot> + </table> + + <script>$('#<?=$id?>TableProgress').removeProp('value');</script> + <script>$('#<?=$id?>TableProgress').hide();</script> + +<? + if (isset($bottom)) echo $bottom; +?> + + </div> + </div> + </div> + + <script> +<? minStart(); ?> + $('.prevent').on('mousedown', function (e) { + var doc = $(document); + e.preventDefault(); + var handler = function () { + e.preventDefault(); + }; + doc.on('mousemove', handler); + doc.one('mouseup', function (e) { + doc.off('mousemove', handler); + }); + }); + + (function () { +<? if ($ajax) { + $ajaxsql = ['sql' => $sql, 'colsql' => $colsql]; +?> + var cDefs = []; +<? + if (!$thdef) { +?> + $.ajaxSetup({async:false}); + $.ajax({ + type: 'POST', + url: '/db/json/<?=$id?>?columns', + data: <?=json_encode($ajaxsql)?>, + success: function (d, s, x) { + try { + cDefs = JSON.parse(d); + } catch (e) { + alert("Interner Fehler. Kann Tabellenspaltendefinition nicht erzeugen."); + $('#loading_modal').hide(); + $('body').css('border', '10px dashed red'); + } + } + }); + $.ajaxSetup({async:true}); +<? + } else { + $columns = []; + $col = new stdClass(); + $col->data = 'ajaxident'; + $columns[] = $col; + + foreach ($thdef as $k) { + $col = new stdClass(); + $col->data = $k; + $columns[] = $col; + } +?> + cDefs = <?=json_encode($columns)?>; +<? + } +?> +<? } ?> + var tf = $('#<?=$id?> tfoot tr'); + $('#<?=$id?> thead th').each(function (i) { + var classes = "filter"; + if ($(this).hasClass('editable')) classes += " editable"; + if ($(this).hasClass('select')) classes += " select"; + if ($(this).hasClass('no-sort')) classes += " no-sort"; + tf.append('<th class="' + classes + '"></th>'); + }); + + var writeChanges = function (id, n, v, num) { + var table = '<?=$entrytable?>'; + var noerror = false; + $.ajaxSetup({async:false}); + $.ajax({ + type: 'POST', + url: '/db/main/update.php', + data: { + table: table, + id: id, + n: n, + v: v, + num: num + <? if ($idcellreal) { ?>, idcell: "<?=$idcellreal?>"<? } ?> + }, + success: function (d, s, x) { + if (d == "true") noerror = true; + } + }); + $.ajaxSetup({async:true}); + + if (noerror) { + return true; + } else { + alert(unescape('Wert\n "' + v + '"\nfür das Feld\n "' + n + '"\nin der Tabelle\n "' + table + '"\nkonnte nicht gespeichert werden.')); + return false; + } + }; + + var setupEditableChange = function () { + $('#<?=$id?> tbody input.editable, #<?=$id?> tbody select.editable').on('change', function () { + $(this).parent().addClass('changed'); + console.debug('some change handler just fired'); + var id = $(this).parent().parent().attr('data-id'); + var n = $(this).parent().attr('data-n'); + var v = $(this).val(); + num = false; + if ($(this).is('input[type=checkbox]')) { + num = true; + v = $(this).prop('checked') ? 1 : 0; + } + + if (writeChanges(id, n, v, num)) { + $(this).parent().removeClass('changed'); + $(this).parent().removeClass('changesFailed'); + $(this).parent().addClass('changesCommitted'); + if ($(this).hasClass('reload')) + location.href = location.href; + } else { + $(this).parent().removeClass('changed'); + $(this).parent().removeClass('changesCommitted'); + $(this).parent().addClass('changesFailed'); + } + }); + }; + + var scramblePii = function () { + $('#<?=$id?> td.pii').each(function (i, e) { + e.innerHTML = nrot3(nshuffle(e.innerHTML)); + }); + }; + + var updateCount = function () { + var t = '' + dt.page.info().recordsDisplay + ''; + t += '/' + dt.rows().count() + ''; + // t += '/' + dt.rows(':selected').count() + ''; + $('#<?=$id?>Count').html(' <sup><small>(' + t + ')</small></sup>'); + if (ajaxdone && dt.rows().count() < 1) { + $('#<?=$id?>TableInner').hide(); + $('#<?=$id?>Empty').show(); + } else { + $('#<?=$id?>TableInner').show(); + $('#<?=$id?>Empty').hide(); + } + }; + + var inputTriggers = function () { + $('#<?=$id?> tbody td input[type=checkbox]').one('click', function () { + $(this).next().html($(this).prop('checked') ? 1 : 0); + }); + } + + var restoreState = function () { + var state = dt.state.loaded(); + if (state) { + dt.columns().eq(0).each(function (colIdx) { + var colSearch = state.columns[colIdx].search; + var realIdx = state.ColReorder.indexOf(colIdx); + + if (colSearch.search) { + dt.columns().footer()[realIdx].getElementsByTagName('input')[0].value = colSearch.search; + dt.columns().footer()[realIdx].classList.add('filteron'); + dt.columns().header()[realIdx].classList.add('filteron'); + + $('tfoot th', dt.columns().footer()).eq(realIdx).find('input') + .val(colSearch.search) + .trigger('keyup') + .parent().addClass('filteron'); + } + }); + dt.draw(); + } + } + window.restorestate = restoreState; + + $.fn.dataTable.ext.buttons.selectFiltered = { + className: 'select_filtered' + }; + + $('#<?=$id?>').show(); + var ajaxdone = false; + var dt = $('#<?=$id?>').DataTable({ + "language": { + url: "/3rdparty/German.json", + processing: '<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i><span class="sr-only">Lade...</span>' + }, + "order": <?=$order?>, + "scrollX": true, + "colReorder": { + 'enable': true, +<? if ($checkboxes) { ?> + 'fixedColumnsLeft': 1 +<? } ?> + }, + "lengthMenu": [5, 10, 20, 50, 100, 500, 1000], + "stateSave": true, + "dom": 'Blfrtip', +<? if ($checkboxes) { ?> + "buttons": ['columnsToggle', 'selectAll', { text: 'selectFiltered', extend: 'selectFiltered', action: function (e, dt) { dt.rows({filter: 'applied'}).select(); }}, 'selectNone'], +<? } else { ?> + "buttons": ['columnsToggle'], +<? } ?> + "processing": true, +<? if ($ajax) { + ?> + "ajax": { + 'url': '/db/json/<?=$id?>', + 'type': 'POST', + 'data': <?=json_encode($ajaxsql)?>, + 'dataSrc': function (d) { + ajaxdone = true; + return d.data; + }, + }, + columns: cDefs, +<? } ?> + "initComplete": function () { + console.log('init complete <?=$id?>'); + + this.api().columns().every(function () { + var column = this; + var idx = column.index(); + + var title = dt.columns().header()[idx].innerHTML.replaceAll('<br>', ' '); + var header = dt.columns().header()[idx]; + if (title == "") return; + + if (dt.columns().header()[idx].classList.contains('select')) return; + +<? if (!$nofilter) { ?> + var input = $('<input type="text" data-index="' + idx + '" placeholder="ᗊ ' + title + '" class="filter"><br />') + .appendTo($(column.footer()).empty()) + .on('change keyup', function () { + $(this).next().next().val('').removeClass('filteron'); + column.search(this.value, true).draw(); + + if (this.value != '') { + this.parentElement.classList.add('filteron'); + header.classList.add('filteron'); + } else { + this.parentElement.classList.remove('filteron'); + header.classList.remove('filteron'); + } + }); +<? } ?> + + if (title.match(/ID$/)) return; + if (title.match(/^id$/)) return; + if (title.match(/^uid$/i)) return; + +<? if (!$nochosen) { ?> + var entries = column.data(); + entriesclean = []; + $.each(entries, (function (i, d) { + if (d === "") return; + if ($('<div />').html(d).find('select').length > 0) { + entriesclean.push($('<div />').html(d).find('select option:selected').text()); + } else { + entriesclean.push($('<div />').html(d).text()); + } + })); + + var uni = _.uniq(entriesclean).sort(function (a, b) { + if (a.toLowerCase() < b.toLowerCase()) return -1; + if (a.toLowerCase() > b.toLowerCase()) return 1; + return 0; + }); + if (uni.length > 600) return; + + var select = $('<select data-index="' + idx + '" class="filter" multiple><option value=""></option><option value="{{{}}}">[leere]</option><option value="}}}{{{">[nicht leere]</option></select>') + .appendTo($(column.footer())) + .on('change select', function () { + var v = $(this).val(); + var val = ""; + if (typeof v === 'string') { + if (v == '{{{}}}') + val = '^$'; + else if (v == '}}}{{{') + val = '.+'; + else + val = $.fn.dataTable.util.escapeRegex(v); + } else if (typeof v === 'object') { + $.each(v, function (i, e) { + console.log(e); + if (val != "") + val += '|'; + if (e == '{{{}}}') + val += '^$'; + else if (e == '}}}{{{') + val += '.+'; + else + val += $.fn.dataTable.util.escapeRegex(e); + }); + } + + console.log(val); + if ($(this).parent().hasClass('select')) { + column.search(val ? val : '', true, true).draw(); + } else { + column.search(val ? '^' + val + '$' : '', true, false).draw(); + } + + $(this).siblings().val(''); + $(this).siblings().removeClass('filteron'); + $(this).parent().removeClass('filteron'); + + if (this.value != '') { + this.classList.add('filteron'); + header.classList.add('filteron'); + } else { + this.classList.remove('filteron'); + header.classList.remove('filteron'); + } + }); + + $.each(uni, function (i, d) { + if (d == "") return; + var t = $('<div />').html(d).text(); + if (t == "") return; + select.append('<option value="' + t + '">' + t + '</option>'); + }); +<? } ?> + +<? if (true || !$ajax) { ?> + this.on('column-reorder', function () { + $('div#<?=$id?>Table table tfoot').hide(); + $('div#tablereordered-<?=$id?>').show(); + console.log('reordered'); + }); +<? } ?> + + }); + console.log('after auto search setup <?=$id?>'); + +<? if ($_SESSION['scramble']) { ?> + scramblePii(); +<? } ?> + + + updateCount(); + $('body').css('overflow', 'auto'); +<? if (!$nospinner) { ?> + $('#loading_modal').hide(); + $('#progress').html(''); +<? } ?> + + $('#<?=$id?>_wrapper .dt-buttons').before('<div style="display: inline-block; float: left; padding-right: .5em; cursor: pointer;" id="<?=$id?>_column_toggle_on"><div class="tooltip"><span class="tooltiptext">Spaltenauswahl ein-/ausblenden</span><i class="fas fa-toggle-off"></i> <small><i class="fas fa-columns"></i></small> <span></span></div></div>'); + $('#<?=$id?>_wrapper .dt-buttons').children().first().before('<div style="display: inline-block; float: left; padding-right: .5em; cursor: pointer;" id="<?=$id?>_column_toggle_off"><i class="fas fa-toggle-on"></i> <small><i class="fas fa-columns"></i></small> <span class="column_count"></span> [alle <span id="<?=$id?>_column_all_off"><i class="fas fa-eye-slash"></i></span> <span id="<?=$id?>_column_all_on"><i class="fas fa-eye"></i></span>]</div>'); + +<? if ($checkboxes) { ?> + var btall = $('#<?=$id?>_wrapper .dt-buttons button.buttons-select-all'); + var btnone = $('#<?=$id?>_wrapper .dt-buttons button.buttons-select-none'); + var btfiltered = $('#<?=$id?>_wrapper .dt-buttons button.select_filtered'); + btall.detach(); + btnone.detach(); + btfiltered.detach(); + btall.html('<div class="tooltip"><span class="tooltiptext">Alle auswählen - unabhängig von Filter</span><i class="fas fa-check-double"></i></span></div>'); + btnone.html('<div class="tooltip"><span class="tooltiptext">Nichts auswählen</span><i class="far fa-square"></i></span></div>'); + btfiltered.html('<div class="tooltip"><span class="tooltiptext">Alle gefilterten auswählen</span><i class="fas fa-filter"></i><i class="fas fa-check"></i></span></div>'); + + btall.removeClass().addClass('medium'); + btnone.removeClass().addClass('medium'); + btfiltered.removeClass().addClass('medium'); + btnone.insertAfter('#<?=$id?>_wrapper'); + btall.insertAfter('#<?=$id?>_wrapper'); + btall.after(' '); + btfiltered.insertAfter('#<?=$id?>_wrapper'); + btfiltered.after(' '); +<? } ?> + + $('#<?=$id?>_column_toggle_on').on('click', function () { + $('#<?=$id?>_wrapper .dt-buttons').show(); + $('#<?=$id?>_column_toggle_on').hide(); + localStorage.setItem('table_<?=$id?>_column_toggles_on', 'true'); + }); + $('#<?=$id?>_column_toggle_off').on('click', function () { + $('#<?=$id?>_wrapper .dt-buttons').hide(); + $('#<?=$id?>_column_toggle_on').show(); + localStorage.setItem('table_<?=$id?>_column_toggles_on', 'false'); + }); + + $('#<?=$id?>_column_all_off').on('click', function (ev) { + $('#<?=$id?>Table .dt-buttons button.active').click(); + setTimeout(function () { + $('#<?=$id?>_wrapper .dt-buttons').show(); + $('#<?=$id?>_column_toggle_on').hide(); + }, 10); + }); + + $('#<?=$id?>_column_all_on').on('click', function () { + $('#<?=$id?>Table .dt-buttons button').not('.active').click(); + setTimeout(function () { + $('#<?=$id?>_wrapper .dt-buttons').show(); + $('#<?=$id?>_column_toggle_on').hide(); + }, 10); + }); + + if (localStorage.getItem('table_<?=$id?>_column_toggles_on') == 'true') { + $('#<?=$id?>_wrapper .dt-buttons').show(); + $('#<?=$id?>_column_toggle_on').hide(); + } else { + $('#<?=$id?>_wrapper .dt-buttons').hide(); + $('#<?=$id?>_column_toggle_on').show(); + } + + var updCount = function () { + var t = $('#<?=$id?>_wrapper .dt-buttons').children('.dt-button.buttons-columnVisibility').length; + var a = $('#<?=$id?>_wrapper .dt-buttons').children('.dt-button.buttons-columnVisibility.active').length; + $('#<?=$id?>_column_toggle_on span.column_count, #<?=$id?>_column_toggle_off span.column_count').html('(' + a + '/' + t + ')'); + if (a != t) $('#<?=$id?>_column_toggle_on span.column_count, #<?=$id?>_column_toggle_off span.column_count').css('color', 'orange'); + else $('#<?=$id?>_column_toggle_on span.column_count, #<?=$id?>_column_toggle_off span.column_count').css('color', ''); + }; + updCount(); + $('#<?=$id?>_wrapper .dt-buttons .dt-button').on('click', function () { + setTimeout(updCount, 200); + }); + + $(window).trigger('resize'); + +<? if (!$nochosen) { ?> + $('#<?=$id?>Table .dataTables_scrollFoot select').chosen({allow_single_deselect:true}); + $('#<?=$id?>Table .dataTables_scrollFoot div.chosen-container').click(function () { + $(this).find('.chosen-drop').css('left', $(this).position().left + 12); + var h = $(this).find('.chosen-drop').height(); + $(this).find('.chosen-drop').css('top', Math.abs($(document).scrollTop() - $(this).offset().top + h)); + //console.log($(this).offset().top + ' ' + $(document).scrollTop() + ' ' + $(this).position().top); + }); +<? } ?> + + restoreState(); + } + + <? if ($checkboxes) { ?>, + /* fixedColumns: { + leftColumns: 1, + rightColumns: 0 + }, */ + columnDefs: [ { + orderable: false, + searchable: false, + className: 'select-checkbox', + targets: 0 + }, { targets: 'no-sort', searchable: false, orderable: false } + <? if ($ajax) { ?>, + { + render: function (data, type, row, meta) { + var s = '<span style="display: none;" class="ajaxident" data-id="' + data['dataid'] + '"'; + + if (data['persid']) s += ' data-persid="' + data['persid'] + '"'; + if (data['stipid']) s += ' data-stipid="' + data['stipid'] + '"'; + if (data['orgaid']) s += ' data-orgaid="' + data['orgaid'] + '"'; + if (data['foerdid']) s += ' data-foerdid="' + data['foerdid'] + '"'; + if (data['eventid']) s += ' data-eventid="' + data['eventid'] + '"'; + + s += '>' + JSON.stringify(data) + '</span>'; + return s; + }, targets: 0 + }, + /* -------------- */ + <?=ajaxLinks();?> + /* -------------- */ + <? } ?> + ], + select: { + style: 'os', + selector: 'td:first-child' + } + <? } else { ?> + <? if ($ajax) { ?>, + columnDefs: [ { + visible: false, + searchable: 'false', + targets: 0 + }, + /* -------------- */ + <?=ajaxLinks();?> + /* -------------- */ + ] + <? } ?> + <? } ?>, + rowCallback: function (a, b, c, d, e, f, g, h, i, j) { + updateCount(); + //inputTriggers(); + <? if ($rowcallback) { ?> + <?=$rowcallback?>(a, b, c, d, e, f, g, h, i, j); + <? } ?> + <? if ($_SESSION['scramble']) { ?> + scramblePii(); + <? } ?> + <? if ($ajax) { ?> + <? } ?> + } + }); + if (typeof window.autotables === 'undefined') + window.autotables = []; + window.autotables['<?=$id?>'] = dt; + + + $('.autotable th').each(function (i) { + if ($(this).text().includes("AnfrageWF")) $(this).attr('title', 'Anfrage (Weiter-)-finazierung'); + if ($(this).text().includes("apstip")) $(this).attr('title', 'Ansprechpartner beim Förderer für die Stipendiaten'); + if ($(this).text().includes("apsf")) $(this).attr('title', 'Ansprechpartner beim Förderer für den Studienfonds OWL'); + if ($(this).text().includes("apop")) $(this).attr('title', 'Ansprechpartner operativ'); + if ($(this).text().includes("apstr")) $(this).attr('title', 'Ansprechpartner strategisch'); + if ($(this).text().includes("apfi")) $(this).attr('title', 'Ansprechpartner beim Förderer für Finanzen'); + + if ($(this).text().includes("elsv")) $(this).attr('title', 'Einladung Stipendienvergabe'); + if ($(this).text().includes("elfa")) $(this).attr('title', 'Einladung Fördereraustausch'); + if ($(this).text().includes("elsft")) $(this).attr('title', 'Einladung SFT'); + if ($(this).text().includes("elosv")) $(this).attr('title', 'Einladung Online-Stipendienvergabe'); + + if ($(this).text().includes("ernl")) $(this).attr('title', 'Erhalten Newsletter'); + if ($(this).text().includes("erwk")) $(this).attr('title', 'Erhalten Weihnachtskarte'); + if ($(this).text().includes("erjb")) $(this).attr('title', 'Erhalten Jahresbericht'); + if ($(this).text().includes("erwm")) $(this).attr('title', 'Erhalten Willkommensmail Förderjahresbeginn'); + + }); + + $('#tablereset-<?=$id?>').click(function () { + localStorage.removeItem('table_<?=$id?>_column_toggles_on'); + dt.state.clear(); + window.location.reload(); + }); + $('#tablereload-<?=$id?>').click(function () { +<? if (!$ajax) { ?> + window.location.reload(); +<? } else { ?> + window.ajaxSpSec = setTimeout(function () { $('#ajaxspinner').show(); }, 800); + dt.ajax.reload(); + $(this).fadeToggle().fadeToggle(); +<? } ?> + }); + + var tableexcel = function (sel) { + if (typeof sel === 'undefined') + sel = false; + + var heading = []; + $('#<?=$id?> thead tr').first().find('th').not('.select-checkbox').each(function (i, e) { + //heading.push(e.textContent.trim()); + heading.push(e.getAttribute('data-displayname')); + }); + + var lines = []; + var selector = '#<?=$id?> tbody tr'; + if (sel) { + selector = $.grep(autotables['<?=$id?>'].table().rows().nodes(), function (e) { + return e.classList.contains('selected'); + }); + } + $(selector).each(function (i, e) { + var line = []; + $(this).find('td').not('.select-checkbox').each(function (ii, ee) { + if (ee.getElementsByTagName('select')[0]) { + var sel = ee.getElementsByTagName('select')[0]; + line.push(sel.options[sel.selectedIndex].innerText.trim()); + } else { + line.push(ee.textContent.trim()); + } + }); + lines.push(line); + }); + + $('#<?=$id?>ExcelName').val("<?=$id?>"); + $('#<?=$id?>ExcelHeading').val(JSON.stringify(heading)); + $('#<?=$id?>ExcelLines').val(JSON.stringify(lines)); + $('#<?=$id?>Excel').submit(); + }; + +<? if ($checkboxes) { ?> + $('#tableexcelsel-<?=$id?>').click(function () { + tableexcel(true); + }); +<? } ?> + + $('#tableexcel-<?=$id?>').click(function () { + tableexcel(false); + }); + + $('#<?=$id?>').on('draw.dt', setupEditableChange); + setInterval(updateCount, 2000); + + $('#<?=$id?> tbody').on('mouseenter', 'td', function () { + var cidx = dt.cell(this).index().column; + var ridx = dt.cell(this).index().row; + + console.log(cidx); + console.log(ridx); + + $(dt.cells().nodes()).removeClass('highlight'); + $(dt.rows().nodes()).removeClass('highlight'); + + $(dt.column(cidx).nodes()).addClass('highlight'); + $(dt.row(ridx).nodes()).addClass('highlight'); + }); + $('#<?=$id?> tbody').on('mouseleave', function () { + $(dt.cells().nodes()).removeClass('highlight'); + $(dt.rows().nodes()).removeClass('highlight'); + }); + /* XXX: + * $('.dataTables_scrollBody').offset() .left .top + * $('.dataTables_scrollBody').scrollLeft(20); .scrollTop; + */ + + var setupAutolinks = function () { +<? +(function () use ($id, $noautolinks) { + if ($noautolinks) return; + $sel_id = $id; + include __DIR__ . "/auto_windowing.php"; +})(); +?> + }; + $('#<?=$id?>').on('draw.dt', setupAutolinks); + + })(); + + function getIDs_<?=$id?>() { + var ids = []; + var g = $.grep(autotables['<?=$id?>'].table().rows().nodes(), function (e) { + return e.classList.contains('selected'); + }); + $.each(g, function (i, e) { + var ee = false; + try { ee = e.getElementsByClassName('ajaxident')[0].getAttribute('data-id'); } catch (e) { e; } + if (ee) ids.push(ee); + else ids.push(e.getAttribute('data-id')); + }); + return ids; + } + + if ($('#insert_<?=$insert?>')) { + $('#insert_<?=$insert?>').replaceWith($('#autotable_containment_<?=$id?>')); + } + + if (window.location !== window.parent.location) { + $('body').css('margin', '0'); + var s = document.createElement('style'); + s.type = "text/css"; + s.innerHTML += '.dataTables_scrollBody { max-height: calc(100vh - 11em) !important; }'; + document.getElementsByTagName('head')[0].appendChild(s); + } + +<? minEnd(); ?> + </script> + +<? + } + + $num_rows = -1; + if (isset($r) && isset($r->num_rows)) + $num_rows = $r->num_rows; + if (isset($stmt)) + $stmt->reset(); +})(); +?> |
