diff options
Diffstat (limited to 'autoform.php')
| -rw-r--r-- | autoform.php | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/autoform.php b/autoform.php new file mode 100644 index 0000000..21f9caa --- /dev/null +++ b/autoform.php @@ -0,0 +1,646 @@ +<?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__ . "/lookup_more.php"; +require_once __DIR__ . "/auto_common.php"; + +(function () use ($id, $simple, $def, $links, $l, $entrytable, $pii, $bottom, $updater) { + $pii = getPii($pii); + $links = getLinks($links); + if (!isset($updater) || $updater == "") + $updater = '/db/main/update.php'; +?> + +<span class="prevent" style="margin 0; padding: 0; vertical-align: bottom;"> + <i style="cursor: pointer;" onclick="toggleForm('<?=$id?>', 0);" id="<?=$id?>Form_off" class="fas fa-toggle-on"></i> + <i style="cursor: pointer; display: none;" onclick="toggleForm('<?=$id?>', 1);" id="<?=$id?>Form_on" class="fas fa-toggle-off"></i> +</span> + +<div style="padding: .15em; margin: 0;"></div> + +<script> +<? minStart(); ?> + function toggleForm(id, state) { + if (state == 1) { + $('#' + id + 'Form').show(); + $('#' + id + 'Form_on').hide(); + $('#' + id + 'Form_off').show(); + setTimeout(function () { + $(window).resize(); + }, 10); + return; + } + $('#' + id + 'Form').hide(); + $('#' + id + 'Form_on').show(); + $('#' + id + 'Form_off').hide(); + setTimeout(function () { + $(window).resize(); + }, 10); + return; + } +<? minEnd(); ?> +</script> + +<form id="<?=$id?>Form" class="grid-form" style="background: silver; max-width: 1200px;" autocomplete="off"> + +<fieldset id="<?=$id?>App" ng-controller="<?=$id?>Ctrl" style="display: none;"> + +<? + if ($simple) { + foreach ($l as $k => $v) { +?> + <div data-row-span="1"> + <div data-field-span="1" class="editable"> + <label><?=$k?></label> + <input type="text" name="<?=$k?>" value="<?=str_replace('"', '"', $v)?>"> + </div> + </div> +<? + } + } +?> + +<? + foreach ($def as $line) { + if (is_string($line)) { +?> + <legend><?=$line?></legend> +<? + } else { +?> + <div data-row-span="<? if (is_numeric($line[0])) { echo $line[0]; array_shift($line); } else { echo count($line); } ?>"> +<? + foreach ($line as $e) { + $label = ""; + $e_split = explode('~', $e); + $e = $e_split[0]; + if (count($e_split) > 1) + $label = $e_split[1]; + + $dis = false; + if ($e[0] === '_') { + $e = substr($e, 1); + $dis = true; + } + + $verbatim = false; + if ($e[0] === '!') { + $e = substr($e, 1); + $verbatim = true; + } + + $code = false; + if ($e[0] === '{') { + $e = substr($e, 1); + $code = true; + } + + $html = false; + if ($e[0] === '[') { + $e = substr($e, 1); + $html = true; + } + + $emailhtml = false; + if ($e[0] === '@') { + $e = substr($e, 1); + $emailhtml = true; + } + + $quill = false; + if ($e[0] === '*') { + $e = substr($e, 1); + $quill = true; + } + + $ace = false; + if ($e[0] === '}') { + $e = substr($e, 1); + $ace = true; + } + + $boolean = false; + if ($e[0] === '+') { + $e = substr($e, 1); + $boolean = true; + } + + $btn = false; + if ($e[0] === '^') { + $e = substr($e, 1); + $btn = true; + } + + $cpick = false; + if ($e[0] === '"') { + $e = substr($e, 1); + $cpick = true; + } + + $udecode = false; + if ($e[0] === '%') { + $e = substr($e, 1); + $udecode = true; + } + + $e_split = explode('|', $e); + $e = $e_split[0]; + + $lookup = false; + if (count($e_split) > 1) + $lookup = $e_split[1]; + + $class = ""; + $e_split = explode('#', $e); + $e = $e_split[0]; + if (count($e_split) > 1) + $class = $e_split[1]; +?> +<? + if (substr($e, 0, 1) === '=') { +?> + <div data-field-span="<? echo substr($e, 1, 1); $e = substr($e, 2); ?>" class="<? if (!$dis) { echo "editable"; } else { echo "disabled"; }?> <?=$class?>"> +<? + } else { +?> + <div data-field-span="1" class="<? if (!$dis) { echo "editable"; } else { echo "disabled"; }?> <?=$class?>"> +<? + } + if ($udecode) { + //$l->$e = html_entity_decode(preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;", urldecode($l->$e)), null, 'UTF-8'); + $l->$e = utf8_encode(urldecode($l->$e)); + } +?> +<? + if ($e !== '=') { + if ($btn) { +?> + <label></label> +<? + } else { +?> + <label title="<?=$e?>"><? if ($label) { echo $label; } else { echo $e; } ?></label> +<? + } + } +?> +<? + if (isset($links[$e])) { +?> + <? if ($l->$e != 0) { ?><a class="autolink" href="<?=$links[$e]?><?=$l->$e?>" style="color: blue !important; font-weight: bold;"><?=$l->$e?></a><? } ?> +<? + } else if (isset($links[$label])) { +?> + <? if ($l->$e != 0) { ?><a class="autolink" href="<?=$links[$label]?><?=$l->$e?>" style="color: blue !important; font-weight: bold;"><?=$l->$e?></a><? } ?> +<? + } else { + if (in_array($e, $pii)) + $class .= ' pii'; + + if ($lookup) { + global $$lookup; +?> + <select class="<?=$class?>" name="<?=$e?>"> + <option value="null"></option> +<? + + $_found = false; + foreach ($$lookup as $k => $v) { +?> + <option value="<?=str_replace('"', '"', $k)?>" <? if ($l->$e == $k) { $_found = true; echo "selected"; } ?>><?=$v?></option> +<? + } + if (!$_found && $l->$e !== null) { +?> + <option value="invalid" disabled selected style="color: red!important;">[Unzulässiger Wert!] {<?=$l->$e?>}</option> +<? + } +?> + </select> +<? + } else if ($boolean) { +?> + <input class="<?=$class?>" name="<?=$e?>" type="checkbox" <? if ($l->$e) { echo "checked"; } ?>> +<? + } else if ($e === '=') { +?> +<? + } else if ($verbatim) { +?> + <?=$l->$e?> +<? + } else if ($code) { +?> + <pre ng-non-bindable style="display: inline-block; background: #eee; color: black; margin: 0; padding: .2em; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word;"><?=$l->$e?></pre> +<? + } else if ($html) { +?> + <iframe style="background: #eee; color: black; margin: 0; padding: .2em; border: 0; width: 100%; height: 100%;" + onload="this.style.height = this.contentWindow.document.documentElement.scrollHeight + 15 + 'px'; $(this).parent().resize();" + csrc="/db/main/reflector.php?foo=<?=urlencode($l->$e)?>"></iframe> +<? + } else if ($emailhtml) { +?> + <iframe style="background: #eee; color: black; margin: 0; padding: .2em; border: 0; width: 100%; height: 100%;" + onload="this.style.height = this.contentWindow.document.documentElement.scrollHeight + 15 + 'px'; $(this).parent().resize();" + src="/db/main/reflector.php?emailid=<?=$l->$e?>"></iframe> +<? + } else if ($quill) { +?> + <div ng-non-bindable class="editorcontainer" style="background: white; color: black;"> + <div class="editor <? if (in_array($e, $pii)) { echo "pii"; } ?>" name="<?=$e?>" id="editor_<?=$e?>"><?=str_replace("\r", " ", str_replace("\n", " ", trim($l->$e)))?></div> + </div> +<? + } else if ($ace) { +?> + <div ng-non-bindable class="editorcontainer ace" style="background: white; color: black;"> + <div class="ace <? if (in_array($e, $pii)) { echo "pii"; } ?>" style="resize:vertical; overflow:auto; min-height: 16em;" name="<?=$e?>" id="ace_<?=$e?>"><?=str_replace(" ", " ", str_replace("\t", ' ', str_replace(' ', ' ', str_replace('<br>', "\n", str_replace('</p>', " ", str_replace('<p>', "\n", trim($l->$e)))))))?></div> + </div> +<? + } else if ($btn) { +?> + <button class="formbtn btn_<?=$e?>"><?=$label?></button> +<? + } else if ($cpick) { +?> + <input class="<?=$class?>" type="color" name="<?=$e?>" value="<?=$l->$e?>"> +<? + } else { +?> + <input class="<?=$class?>" type="text" name="<?=$e?>" value="<?=str_replace('"', '"', $l->$e)?>"> +<? + } + } +?> + </div> +<? + } +?> + </div> +<? + } + } +?> +</fieldset> + +<?=$bottom?> + +<button style="display: none;" class="savebutton" onclick="return writeChanges();"><i class="fas fa-save"></i> Speichern</button> +<button style="display: none; position: fixed; top: 2em; left: min(1150px, calc(100vw - 2.5em)); opacity: .8;" class="savebutton floating" onclick="return writeChanges();"><i class="fas fa-save"></i></button> +</form> + +<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); + }); + }); + + var Delta = Quill.import('delta'); + var Break = Quill.import('blots/break'); + var Embed = Quill.import('blots/embed'); + + function lineBreakMatcher() { + var newDelta = new Delta(); + newDelta.insert({'break': ''}); + return newDelta; + } + + class SmartBreak extends Break { + length () { + return 1; + } + value () { + return '\n'; + } + insertInto(parent, ref) { + Embed.prototype.insertInto.call(this, parent, ref); + } + } + SmartBreak.blotName = 'break'; + SmartBreak.tagName = 'BR' + Quill.register(SmartBreak); + + var editors = []; + $('.editorcontainer .editor').each(function () { + var that = this; + var quill = new Quill(this, { + theme: 'snow', + modules: { + toolbar: [ + [{ header: [1, 2, 3, false] }], + [{'size': ['small', false, 'large', 'huge']}], + ['bold', 'italic', 'underline', 'strike'], + [{ 'color': [] }, { 'background': [] }], + ['link', 'blockquote', 'image'], + [{'list': 'ordered'}, {'list': 'bullet'}], + [{'script': 'sub'}, {'script': 'super'}], + [{'indent': '-1'}, {'indent': '+1'}], + [{'align': []}], + ['clean'] + ], + clipboard: { + matchers: [ + ['BR', lineBreakMatcher] + ] + }, + keyboard: { + bindings: { + linebreak: { + key: 13, + shiftKey: true, + handler: function (range) { + var currentLeaf = this.quill.getLeaf(range.index)[0]; + var nextLeaf = this.quill.getLeaf(range.index + 1)[0]; + + this.quill.insertEmbed(range.index, 'break', true, 'user'); + + if (nextLeaf === null || (currentLeaf.parent !== nextLeaf.parent)) { + this.quill.insertEmbed(range.index, 'break', true, 'user'); + } + + this.quill.setSelection(range.index + 1, Quill.sources.SILENT); + } + } + } + } + } + }); + //that.firstChild.innerHTML = that.firstChild.innerHTML.trim().replace(/<p><br><\/p>$/, "").replace(/<br>/g, "\n"); + setTimeout(function () { + quill.on('text-change', function () { + that.firstChild.classList.add('changed'); + $('#<?=$id?>Form .savebutton').show(); + $('#<?=$id?>Form').trigger('resize'); + }); + }, 100); + editors.push(quill); + }); + + var aceeditors = []; + $('.editorcontainer .ace').each(function () { + var that = this; + var editor = ace.edit(this); + editor.session.setMode("ace/mode/match"); + editor.setTheme("ace/theme/monokai"); + editor.setAutoScrollEditorIntoView(true); + editor.setShowPrintMargin(false); + editor.setShowInvisibles(false); + editor.setOption('highlightActiveLine', true); + editor.getSession().setTabSize(4); + editor.getSession().setUseSoftTabs(true); + editor.getSession().setUseWrapMode(true); + + setTimeout(function () { + editor.on('change', function () { + that.classList.add('changed'); + $('#<?=$id?>Form .savebutton').show(); + $('#<?=$id?>Form').trigger('resize'); + return false; + }); + }, 100); + + var lastHeight = 0; + setInterval(function () { + if (lastHeight != that.clientHeight) { + editor.resize(); + if (that.clientHeight < lastHeight) { + editor.renderer.updateFull(); + } + } + lastHeight = that.clientHeight; + }, 100); + + $(window).on('resize', function() { + editor.resize(); + editor.renderer.updateFull(); + }); + + aceeditors.push(editor); + }); + +// $(document).ready(function () { + setTimeout(function() { + var app = angular.module('<?=$id?>App', []); + app.controller('<?=$id?>Ctrl', ['$scope', function ($scope) { + }]); + angular.bootstrap($('#<?=$id?>App'), ['<?=$id?>App']); + $('#<?=$id?>App').show(); + +<? if ($_SESSION['scramble']) { ?> + $('#<?=$id?>App input.pii').each(function (i, e) { + e.value = nrot3(nshuffle(e.value)); + }); + $('#<?=$id?>App select.pii option').each(function (i, e) { + e.innerHTML = nrot3(nshuffle(e.innerHTML)); + }); + $('#<?=$id?>App .editor.pii').each(function (i, e) { + e.innerHTML = nrot3(nshuffle(e.innerHTML)); + }); +<? } ?> + $('#<?=$id?>Form .savebutton').hide(); + + $('.disabled input, .disabled select').prop('disabled', true); + + $('.editable input, .editable select:not(.ql-background, .ql-color, .ql-header, .ql-size, .ql-picker .ql-formats)').on('change input cut paste', function () { + if ($(this).parent().hasClass('ql-formats') || $(this).parent().hasClass('ql-toolbar')) + return; + if ($(this).parent().hasClass('ql-tooltip')) + return; + + $(this).parent().addClass('changed'); + $('#<?=$id?>Form .savebutton').show(); + }); + + $('.editable.date input, .editable.isodate input').datepicker(); + /* + flatpickr({ + weekNumbers: true, + shorthandCurrentMonth: true, + locale: { + firstDayOfWeek: 1, + weekdays: { + shorthand: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], + longhand: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], + }, + months: { + shorthand: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], + longhand: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'] + }, + }, + }); + */ + + $('.editable.isodatetime input').datepicker(); + /*flatpickr({ + enableTime: true, + time_24hr: true, + weekNumbers: true, + shorthandCurrentMonth: true, + locale: { + firstDayOfWeek: 1, + weekdays: { + shorthand: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], + longhand: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], + }, + months: { + shorthand: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], + longhand: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'] + }; + }, + }); + */ + +<? + (function () use ($id) { + $sel_id = $id . "Form"; + include __DIR__ . "/auto_windowing.php"; + })(); +?> + + setTimeout(function () { + $('#<?=$id?>Form').trigger('resize'); + }, 50); + }, 10); + // }); + + e_invalid = "Ungültige Eingaben gefunden."; + + function writeChanges() { + if (!ckvalid()) return false; + + $('.changed input, .changed select').not('.ql-tooltip').not('.ql-hidden').each(function () { + var n = $(this).attr('name'); + var v = $(this).val(); + if ($(this).is('input[type=checkbox]')) + v = $(this).prop('checked') ? 1 : 0; + + var noerror = false; + var number = $(this).is('select') || $(this).parent().hasClass('number') || $(this).is('input[type=checkbox]'); + if ($(this).parent().hasClass('string')) number = false; + + $.ajaxSetup({async:false}); + $.ajax({ + type: 'POST', + url: '<?=$updater?>', + data: { + table: '<?=$entrytable?>', + id: '<?=$l->ID?>', + n: n, + v: v, + num: number + }, + success: function (d, s, x) { + if (d == "true") noerror = true; + } + }); + $.ajaxSetup({async:true}); + + if (noerror) { + $(this).parent().removeClass('changed'); + } else { + alert(unescape('Wert für das Feld "' + n + '" konnte nicht gespeichert werden.')); + } + }); + + $('.ql-editor.changed').each(function () { + var n = $(this).parent().attr('name'); + var v = $(this).html(); + + var noerror = false; + $.ajaxSetup({async:false}); + $.ajax({ + type: 'POST', + url: '<?=$updater?>', + data: { + table: '<?=$entrytable?>', + id: '<?=$l->ID?>', + n: n, + v: v.trim().replace(/<p><br><\/p>$/, ""), + num: false + }, + success: function (d, s, x) { + if (d == "true") noerror = true; + } + }); + $.ajaxSetup({async:true}); + + if (noerror) { + $(this).removeClass('changed'); + } else { + alert(unescape('Text im Feld ' + n + ' konnte nicht gespeichert werden.')); + } + }); + + $('.editorcontainer.ace .changed').each(function () { + var n = $(this).attr('name'); + var v = aceeditors[0].getSession().getValue(); + + var noerror = false; + $.ajaxSetup({async:false}); + $.ajax({ + type: 'POST', + url: '<?=$updater?>', + data: { + table: '<?=$entrytable?>', + id: '<?=$l->ID?>', + n: n, + v: v.trim().replace(/<p><br><\/p>$/, ""), + num: false + }, + success: function (d, s, x) { + if (d == "true") noerror = true; + } + }); + $.ajaxSetup({async:true}); + + if (noerror) { + $(this).removeClass('changed'); + } else { + alert(unescape('Text im Feld ' + n + ' konnte nicht gespeichert werden.')); + } + }); + + if ($('.changed input, .changed select, .ql-editor.changed').length === 0) { + $('#<?=$id?>Form .savebutton').hide(); + location.reload(); + } + + return false; + } +<? minEnd(); ?> +</script> + +<style> +.ql-editor { + padding: 0.3em !important; +} +.ql-toolbar.ql-snow { + padding: 0.1em !important; + background: lightgrey; +} +</style> + +<? +})(); +?> |
