summaryrefslogtreecommitdiff
path: root/autoform.php
diff options
context:
space:
mode:
Diffstat (limited to 'autoform.php')
-rw-r--r--autoform.php646
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('"', '&quot;', $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('"', '&quot;', $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('&nbsp;', ' ', 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('"', '&quot;', $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>
+
+<?
+})();
+?>