diff options
Diffstat (limited to 'public/app/controllers')
| -rw-r--r-- | public/app/controllers/JsonToForm.php | 685 |
1 files changed, 685 insertions, 0 deletions
diff --git a/public/app/controllers/JsonToForm.php b/public/app/controllers/JsonToForm.php new file mode 100644 index 0000000..9e305ce --- /dev/null +++ b/public/app/controllers/JsonToForm.php @@ -0,0 +1,685 @@ +<?php + +class JsonToForm +{ + /** + * ## Help Constants and Functions ------------------------------------------------ + * //////////////////////////////////////////////////////////////////////////////// + * + * // Cache fields options (json format) //////////////////////////////////////// + * // --------------------------------------------------------------------------- + * $formJSON = file_get_contents('config/kallassa.json'); + * define("FORMJSON", $formJSON); + * + * // Cache CCODE attributes (json format) ////////////////////////////////////// + * // --------------------------------------------------------------------------- + * $codeJSON = file_get_contents('config/ccode.json'); + * define("CODEJSON", $codeJSON); + * + * // Parse anythig from a field //////////////////////////////////////////////// + * // ARGS: + * // $fkey = keyname (as in json fields oprions) + * // $inp = input value (string) + * // RETURN: array( + * // 'label' = field label, + * // 'multi' = (true|false) is multiple choice (select|radio|check) or not, + * // 'value' = human readable value (or array of values if multi) + * // ) ------------------------------------------------------------------------- + */ + public static function parse_any($fkey, $inp ="") + { + $formARRAY = json_decode(FORMJSON); + + foreach ($formARRAY as $key => $section) { + foreach ($section->childs as $kk => $field) { + + // find the field + if ($field->nam == $fkey) { + + $values = array(); // human readble values if select (comma separated) + + if ($field->typ == 'select') { + $multi = true; + + if ($inp !='') { + $codes = explode(",", $inp); // split coded values + foreach ($field->opt as $kkk => $v) { + if (in_array($v->id, $codes)) { // check if option is in array + $values[] = ($field->nam == 'ccode') ? ($v->id.": ".$v->tag) : $v->tag; + } + } + } + + } + else $multi = false; + + // return everything in an array + return array( + 'label' => $field->lab, + 'multi' => $multi, + 'value' => ($multi ? $values : $inp) + ); + } + } + } + + // if not escaped already, then name return same + return array('label' => $fkey, 'multi' => false, 'value' => $inp ); + } + + + + // Parse anythig from ccode + public static function parse_ccode($ckey) { + $ccARRAY = json_decode(CODEJSON); + + foreach ($ccARRAY as $key => $val) { + // find the field + if ($val->id == $ckey) { + // return everything in an array + return $val; + } + } + } + + + // Get totals of alla categories ///////////////////////////////////////////// + // RETURN array of items (value) per category (array key) + // --------------------------------------------------------------------------- + public static function get_totals() { + $result = array(); + $sum = 0; + + $dbc = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBMS); + if ($dbc->connect_errno) { + echo "Database connection failed; Please try in a few minutes. "; + if (TESTING) echo $dbc->connect_error; + $dbc->close(); die(); + } + $dbc->set_charset("utf8"); + + // prepare statemet + $stm = $dbc->prepare("SELECT ccode, count(id) total FROM `items` GROUP BY ccode"); + $stm->execute(); // execute query + $stm->store_result(); // store result + $stm->bind_result($c, $tot); + while ($stm->fetch()) { + // using md5() you can have any unicode string as key ;) + // credit: https://stackoverflow.com/questions/10696067/characters-allowed-in-php-array-keys -> Rob's answer + // but newer versions of php (v7+) seem to handle unicide keys nicely + $result[$c] = $tot; + $sum += $tot; + } + + $result['all'] = $sum; + + return $result; + } + + + // Preview Local Datetime //////////////////////////////////////////////////// + // (in Greek format and names ) + // --------------------------------------------------------------------------- + public static function local_dt($t) { + $day = array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); + $dayL = array("Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"); + $mon = array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + $monL = array("Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαϊ", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"); + $tm = array("am", "pm"); + $tmL = array("πμ", "μμ"); + $r = date("D. j M. Y, h:i:sa", $t); + $r = str_replace($day, $dayL, $r); + $r = str_replace($mon, $monL, $r); + $r = str_replace($tm, $tmL, $r); + return $r; + } + + + // Part of string + // UTF-8 SAFE + public static function str_part($str, $len) { + return (mb_strlen($str) > $len) ? mb_substr($str, 0, $len-1) ."…" : $str; + } + + + public static function make_a_form() + { + + // Script Workflow: + // --------------------------------------------------------------------------- + // 1. read fields options + // 2. generate HTML + // 3. generate JS needed + + // the UI + // --------------------------------------------------------------------------- + // Fields are grouped in sections + // These sections presented in tabs (or accordion if mobile device) + // Two (2) sections incduded to inform the user of empty fields or errors + + // Libraries and FrameWorks used + // --------------------------------------------------------------------------- + // Bootstrap 4.3 is used for easy responsive HTML code + // JQuery 3.3 is used to handle user interation + // Select2 is used to make select-boxes (single or multiple) easier to use + + // read fields options (json format) ///////////////////////////////////////// + // --------------------------------------------------------------------------- + $formJSON = file_get_contents('config/kallassa.json'); + $formARRAY = json_decode($formJSON); + + + // Init strigns for JS generator (needed to handle everything) /////////////// + // --------------------------------------------------------------------------- + $checkFilledJS = ""; // JS for checking empty fields + $ref2Select2JS = ""; // references to Select2-controls Javascript + $initSelectsJS = ""; // js to initialize select fields (single or multiple) + + + + $html = ' + <div class="pi-container"> + <h2>Εισαγωγή Εγγραφής</h2>'; + + $i = 1; + foreach ($formARRAY as $key => $section) { // only one section + + $html = '<hr />'; + + foreach ($section->childs as $kk => $field) { + + + // get attributes + + $atrs = explode('|', $field->attr); // attributes array + $appendKey = in_array('append-key', $atrs) ? true : false; // append key (for selects) + $required = in_array('required', $atrs) ? 'required' : ''; // required + $asterisn = in_array('required', $atrs) ? '*' : ''; // asterisk in label if required + $class = (isset($field->len)) ? ' col-md-'.$field->len : 'col-md-12'; // column class (for width) + $name = $field->name; + $label = $field->label; + + + $html .= " + <div class='form-group {$class}'> + <label for='{$name}'>{$label} {$asterisk}</label> + "; + + switch ($field->typ) { + + case 'select': + + if (in_array('multiple', $atrs)) { // if select is multiple + + $html .=" + <select id='{$name}$' class='select-field' name='{$name}[]' multiple='multiple' style='width:100%'>"; + + // prepare initialization of select2 (multiple) + $initSelectsJS .= " + var {$name} = $('#{$name}'); + {$name}.select2({ width: '100%' });"; + + // prepare check if empty field + $checkFilledJS .= " + if (getValues({$name}) =='') { empty += '{$label} {$asterisk}<br />'; } + values.{$name} = getValues($name);"; + + + } else { // select is single; draw select + add empty option + + $html .=" + <select id='{$name}$' class='select-field' name='{$name}' style='width:100%'> + <option></option>"; + + // prepare initialization of select2 (single) + $initSelectsJS .= " + var {$name} = $('#{$name}'); + {$name}.select2({ allowClear: true });"; + + // prepare check if empty field + $checkFilledJS .= " + if (getValues({$name}) =='') { empty += '{$label} {$asterisk}<br />'; } + values.{$name} = getValues($name);"; + + } + + // inject options + foreach ($field->options as $key => $val) { + $html .= " + <option value='{$val->id}'>{$val->tag}</option>"; + } + + // close select + $html .= "</select>"; + + break; + + + case 'text': + + $html .= " + <input type='text' class='form-control' name='{$name}' {$required}>"; + + $checkFilledJS = " + if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; } + values.{$name} = $('input[name={$name}]').val();"; + + break; + + + case 'integer': + + $html .= " + <input type='number' class='form-control' name='{$name}' min='0' step='1' {$required}>"; + + $checkFilledJS .= " + if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; } + values.{$name} = $('input[name={$name}]').val();"; + + break; + + + case 'textarea': + + $html .= " + <textarea class='form-control' name='{$name}' {$required}></textarea>"; + + $checkFilledJS .= " + if ($('textarea[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; } + values.{$name} = $('textarea[name={$name}]').val();"; + + case 'date': + + $html .= " + <input type='date' class='form-control' name='{$name}' {$required}>"; + + $checkFilledJS .= " + if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; } + values.{$name} = $('input[name={$name}]').val();"; + + break; + + + case 'email': + + $html .= " + <input type='email' class='form-control' name='{$name}' {$required}>"; + + $checkFilledJS .= " + if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; } + values.{$name} = $('input[name={$name}]').val();"; + + break; + + + default: // label, acts as common text + + $html .= "<label>{$label}</label"; + + + } + } + } + } + +} + + + + + /***** + // Script Workflow: + // --------------------------------------------------------------------------- + // 1. read fields options + // 2. generate HTML + // 3. generate JS needed + + // the UI + // --------------------------------------------------------------------------- + // Fields are grouped in sections + // These sections presented in tabs (or accordion if mobile device) + // Two (2) sections incduded to inform the user of empty fields or errors + + // Libraries and FrameWorks used + // --------------------------------------------------------------------------- + // Bootstrap 4.3 is used for easy responsive HTML code + // JQuery 3.3 is used to handle user interation + // Select2 is used to make select-boxes (single or multiple) easier to use + + + // read fields options (json format) ///////////////////////////////////////// + // --------------------------------------------------------------------------- + $formJSON = file_get_contents('config/kallassa.json'); + $formARRAY = json_decode($formJSON); + + + // Init strigns for JS generator (needed to handle everything) /////////////// + // --------------------------------------------------------------------------- + $checkFilledJS = ""; // JS for checking empty fields + $ref2Select2JS = ""; // references to Select2-controls Javascript + $initSelectsJS = ""; // js to initialize select fields (single or multiple) + */ + + + + /** document header + * + * <!DOCTYPE html> + * <html prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB" dir="ltr"> + * <head> + * <!-- Metas + Title --> + * <meta http-equiv="X-UA-Compatible" content="IE=edge"> + * <meta name="viewport" content="width=device-width, initial-scale=1"> + * <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + * + * <title><?=PROJECT?> : Εισαγωγή Εγγραφής</title> + * + * <!-- CSS needed --> + * <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,700&display=swap" rel="stylesheet"> + * <link rel="stylesheet" href="/css/bootstrap.min.css" /><!-- v4.4.1 --> + * <link rel="stylesheet" href="/css/select2.min.css" /><!-- v4.0.10 --> + * <link rel="stylesheet" href="/css/pi.css" /> + * </head> + * <body> + */ + + + /** form footer + * <!-- footer of form --> + * <div class="row"> + * + * <div class="col-md-4 line-right"> + * <h3>Δεν έχουν συμπληρωθεί:</h3> + * <div id="empty-fields"></div> + * </div> + * + * <div class="col-md-8"> + * + * <!-- custom field --> + * <div class="form-group"> + * <label for="more">Συμπληρωματική Πληροφορία</label> + * <textarea name="note" class="form-control tall"></textarea> + * <?php + * // append js code + * // for checking if field is empty + * // and attaching value to json data + * $checkFilledJS .= " + * if ($('textarea[name=note]').val() =='') { + * empty += '<span>Γενικά:</span>Συμπληρωματική Πληροφορία<br />'; + * } + * values.note = $('textarea[name=note]').val(); + * "; + * ?> + * </div> + * + * <div class="form-group"> + * <input class="btn btn-primary" type="submit" value="Καταχώρηση Εγγραφής"> + * </div> + * </div> + * </div> + */ + + + /** post-DOM-end + scripts + * + * </form> + * </div> + * <!-- DOM ENDS HERE --> + * + * <!-- scripts and libraries + * load and register one by one, so you don't need to worry about if they are ready --> + * <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> + * <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-migrate/1.4.1/jquery-migrate.min.js"></script> + * <script src="/js/bootstrap.min.js"></script> + * <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.full.min.js"></script> + * <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/i18n/el.js"></script> + * <script> + * // NOW RUN EVERYTHING AFTER JQUERY (AND DOM ready) + * // ----------------------------------------------------------------------------- + * //////////////////////////////////////////////////////////////////////////////// + * + * // 00. FLAGS and NEEDED FUNCTIONS + * // --------------------------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * var waitingResponse = false; // flag for an ajax request that was sent and still waiting response + * + * // pure JS ajax GET request + * // return data as JSON + * // no fancy things like UTF8; if needed use base64 --------------------------- + * function ajax_get(url, callback) { + * var xmlhttp = new XMLHttpRequest(); + * xmlhttp.onreadystatechange = function() { + * if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + * + * try { + * var data = JSON.parse(xmlhttp.responseText); + * } catch(err) { + * console.log(err.message + ' in ' + xmlhttp.responseText); + * return; + * } + * callback(data); + * } + * }; + * + * xmlhttp.open("GET", url, true); + * xmlhttp.send(); + * } + * + * + * // 01. MENU MANAGEMENT + * // --------------------------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * // menu management + * // --------------------------------------------------------------------------- + * $('.dropdown-item').on('click', function(e){ + * e.preventDefault(); + * + * if (!waitingResponse) { + * waitingResponse = true; + * + * var r = confirm('Δεν έχετε αποθηκεύσει το τρέχον αντικείμενο!\nΕίστε σίγουροι ότι θέλετε να εγκαταλείψετε τη σελίδα;'); + * if (r == true) { + * + * // all data-goto have the format: 'method,uri_address' + * // uri_address is the url to call + * // method options: + * // * url : means goto url (redirect) + * // * ajax : means call url via ajax; if 'success = true' then goto '/' after that + * // ----------------------------------------------------------------------- + * var opt = $(this).data('goto').split(','); // split data-goto + * + * if (opt[0] == 'url') { // if method = url + * window.location.href = opt[1]; + * } + * else { // else, method = ajax + * ajax_get(opt[1], function(response) { + * if (response.success) { + * window.location.href = '/'; + * } + * }); + * } + * + * } + * else { + * // user did not confirmed the selection; do nothing + * } + * + * waitingResponse = false; + * } + * + * }); + * + * // 02. USER INTERFACE + * // --------------------------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * // tabs to accorderon -------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * // FUNCTION: Set tabsContainer height + * // acording to which tab is visible + * // and tab mode (tabs|acordeon) + * // --------------------------------------------------------------------------- + * function set_tabsContainer_height() { + * var ch_; // content height + * var tc_base; // tabs-container base height + * tc_base = ($(window).width() > 650) ? 100 : 400; + * if ($('#content1').is(':visible')) ch_ = $('#content1').height(); + * if ($('#content2').is(':visible')) ch_ = $('#content2').height(); + * if ($('#content3').is(':visible')) ch_ = $('#content3').height(); + * if ($('#content4').is(':visible')) ch_ = $('#content4').height(); + * if ($('#content5').is(':visible')) ch_ = $('#content5').height(); + * if ($('#content6').is(':visible')) ch_ = $('#content6').height(); + * + * $('#tabsContainer').height(ch_ + tc_base); + * + * } + * set_tabsContainer_height(); // init (run for 1st time) + * + * // on tab selection + * // calculate tabsContainer height + * $('input:radio[name="tabs"]').change( function(){ + * set_tabsContainer_height() + * }); + * + * // on window change + * // set tabsContainer height + * $( window ).resize(function() { + * set_tabsContainer_height(); + * }); + * + * + * + * // 03. FORM-CONTROLS + * // --------------------------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * // Select2 controls + * ////////////////////////////////////////////////////////////////////////////// + * + * // FUNCTION: Get selected value(s) of Select2 control + * // pass arg: source-element + * // return: value(s) comma-separated + * // --------------------------------------------------------------------------- + * function getValues(srcElm) { + * var res; + * var obj = srcElm.select2('data'); // get delected data array + * + * if (obj.length === 0) return ''; // if empty list then nothig is selected + * else { + * var i = 0; + * obj.forEach(function(elm){ // loop through object elements array + * + * if (i) res += ',' + elm.id; // if not first item, prepend ',' befor value(id) + * else res = elm.id; // else set (first) checked value + * + * i++; + * }); + * } + * return res; + * } + * + * // patch select2-multiple widths + * // --------------------------------------------------------------------------- + * $('.select-field').select2({ width: '100%' }); + * + * // init select2 fields + * // (embed from php) + * // --------------------------------------------------------------------------- + * <?=$initSelectsJS?> + * + * + * // 04. FORM-LOGIC + * // --------------------------------------------------------------------------- + * ////////////////////////////////////////////////////////////////////////////// + * + * // FUNCTION: Report empty fields + * // --------------------------------------------------------------------------- + * function reportEmpty() { + * var empty = ''; + * var needit = []; + * var values = {}; + * + * // embed if-conditions from php + * <?=$checkFilledJS?> + * + * $("#empty-fields").html(empty); // render empty fields + * + * // console.log(JSON.stringify(values)); + * + * return { need : needit, data: values }; // return all fields + * } + * reportEmpty(); + * + * $('form').on('keyup change paste', 'input, select, textarea', function(){ + * console.log('Form changed!'); + * reportEmpty(); + * }); + * + * // validation? + * // check: https://www.sitepoint.com/instant-validation/ + * + * + * $('#post-form').on('submit', function(e){ + * e.preventDefault(); + * if (!waitingResponse) { + * waitingResponse = true; + * var resp = reportEmpty(); + * + * if (resp.need.length > 0) alert("Tα πεδία:\n\n" + resp.need.join(',\n') + "\n\nείναι υποχρεωτικά!"); + * else { + * // alert('sending: '+JSON.stringify(resp.data)); + * var postUrl = "/ajax.php?do=additem"; // url to post form + * var data2send = resp.data; // parse data to send + * + * $.ajax({ + * type: 'POST', + * url: postUrl, // make sure you respect the same origin policy with this url + * data: data2send, + * dataType: "text", + * + * success: function(data) { // server replies + * var json = $.parseJSON(data); + * if (json.success == true) { // good! post accepted + * // alert(json.id) + * window.location.href = '/ui-show-item.php?id='+ json.id; + * } + * else { + * alert("Post not accepted.\nPlease check the data you submit."); + * // $('#oc-company-form')[0].reset(); + * } + * }, + * + * error: function() { + * alert('Some ajax error! :('); + * } + * }); + * } + * + * waitingResponse = false; + * } + * + * }); + * + * <?php + * // bibliography and References + * // + * // WHICH JQUERY: + * // read: https://jquery.com/download/ + * // + * // SELECT2 + * // https://stackoverflow.com/questions/12889309/get-selected-value-from-multi-value-select-boxes-by-jquery-select2 + * // + * // tests: + * // https://jsfiddle.net/3nd1gL8o/1/ + * // https://jsfiddle.net/3nd1gL8o/5/ + * // + * // EXAMPLE with ALL CASES NEEDed: + * // https://jsfiddle.net/v684h0g2/2/ + * ?> + * </script> + * </body> + * </html> + */ |
