6 * @link http://www.open-emr.org
7 * @author Rod Roark <rod@sunsetsystems.com>
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2014-2017 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2017 Jerry Padgett <sjpadgett@gmail.com>
12 * @copyright Copyright (c) 2017 Brady Miller <brady.g.miller@gmail.com>
13 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 require_once("../globals.php");
17 require_once("$srcdir/acl.inc");
18 require_once("$srcdir/log.inc");
20 use OpenEMR\Core\Header
;
22 function collectLayoutNames($condition, $mapping = '')
25 $gres = sqlStatement("SELECT grp_form_id, grp_title, grp_mapping " .
26 "FROM layout_group_properties WHERE " .
27 "grp_group_id = '' AND grp_activity = 1 AND $condition " .
28 "ORDER BY grp_mapping, grp_seq, grp_title");
29 while ($grow = sqlFetchArray($gres)) {
30 $tmp = $mapping ?
$mapping : $grow['grp_mapping'];
32 $tmp = '(' . xl('No Name') . ')';
34 $layouts[$grow['grp_form_id']] = array($tmp, $grow['grp_title']);
38 collectLayoutNames("grp_form_id NOT LIKE 'LBF%' AND grp_form_id NOT LIKE 'LBT%'", xl('Core'));
39 collectLayoutNames("grp_form_id LIKE 'LBT%'", xl('Transactions'));
40 collectLayoutNames("grp_form_id LIKE 'LBF%'", '');
42 // Include predefined Validation Rules from list
43 $validations = array();
44 $lres = sqlStatement("SELECT * FROM list_options " .
45 "WHERE list_id = 'LBF_Validations' AND activity = 1 ORDER BY seq, title");
46 while ($lrow = sqlFetchArray($lres)) {
47 $validations[$lrow['option_id']] = xl_list_label($lrow['title']);
50 // Field modifier objects in script
51 // array of the data_types of the fields
53 "1" => xl("List box"),
55 "3" => xl("Textarea"),
56 "4" => xl("Text-date"),
57 "10" => xl("Providers"),
58 "11" => xl("Providers NPI"),
59 "12" => xl("Pharmacies"),
61 "14" => xl("Organizations"),
62 "15" => xl("Billing codes"),
63 "16" => xl("Insurances"),
64 "18" => xl("Visit Categories"),
65 "21" => xl("Checkbox(es)"),
66 "22" => xl("Textbox list"),
67 "23" => xl("Exam results"),
68 "24" => xl("Patient allergies"),
69 "25" => xl("Checkboxes w/text"),
70 "26" => xl("List box w/add"),
71 "27" => xl("Radio buttons"),
72 "28" => xl("Lifestyle status"),
73 "31" => xl("Static Text"),
74 "32" => xl("Smoking Status"),
75 "33" => xl("Race/Ethnicity"),
76 "34" => xl("NationNotes"),
77 "35" => xl("Facilities"),
78 "36" => xl("Multiple Select List"),
79 "40" => xl("Image canvas"),
90 function nextGroupOrder($order)
94 } else if ($order == 'Z') {
97 $order = chr(ord($order) +
1);
103 // This returns HTML for a <select> that allows choice of a layout group.
104 // Included also are parent groups containing only sub-groups. Groups are listed
105 // in the same order as they appear in the layout.
107 function genGroupSelector($name, $layout_id, $default = '')
110 "SELECT grp_group_id, grp_title " .
111 "FROM layout_group_properties WHERE " .
112 "grp_form_id = ? AND grp_group_id != '' ORDER BY grp_group_id",
115 $s = "<select class='form-control' name='" . xla($name) . "'>";
116 $s .= "<option value=''>" . xlt('None') . "</option>";
119 while ($row = sqlFetchArray($res)) {
120 $thisid = $row['grp_group_id'];
122 // Compute number of initial matching groups.
123 while ($i < strlen($thisid) && $i < strlen($arrid) && $thisid[$i] == $arrid[$i]) {
126 $arr = array_slice($arr, 0, $i); // discard the rest
127 while ($i < (strlen($arrid) - 1)) {
128 $arr[$i++
] = '???'; // should not happen
130 $arr[$i] = $row['grp_title'];
132 foreach ($arr as $part) {
138 $s .= "<option value='" . attr($thisid) . "'";
139 if ($thisid == $default) {
142 $s .= ">" . text($gval) . "</option>";
148 // Compute a new group ID that will become layout_options.group_id and
149 // layout_group_properties.grp_group_id.
150 // $parent is a string of zero or more sequence prefix characters.
151 // If there is a nonempty $parent then its ID will be the prefix for the
152 // new ID and the sequence prefix will be computed within the parent.
154 function genGroupId($parent)
157 $results = sqlStatement(
158 "SELECT grp_group_id " .
159 "FROM layout_group_properties WHERE " .
160 "grp_form_id = ? AND grp_group_id LIKE ?",
161 array($layout_id, "$parent_%")
164 while ($result = sqlFetchArray($results)) {
165 $tmp = substr($result['grp_group_id'], strlen($parent), 1);
166 if ($tmp >= $maxnum) {
167 $maxnum = nextGroupOrder($tmp);
170 return $parent . $maxnum;
173 // Changes a group's ID from and to the specified IDs. This also works for groups
174 // that have sub-groups, in which case only the appropriate parent portion of
175 // the ID is changed.
177 function fuzzyRename($from, $to)
181 $query = "UPDATE layout_options SET group_id = concat(?, substr(group_id, ?)) " .
182 "WHERE form_id = ? AND group_id LIKE ?";
183 sqlStatement($query, array($to, strlen($from) +
1, $layout_id, "$from%"));
185 $query = "UPDATE layout_group_properties SET grp_group_id = concat(?, substr(grp_group_id, ?)) " .
186 "WHERE grp_form_id = ? AND grp_group_id LIKE ?";
187 sqlStatement($query, array($to, strlen($from) +
1, $layout_id, "$from%"));
190 // Swaps the positions of two groups. To the degree they have matching parents,
191 // only the first differing child positions are swapped.
193 function swapGroups($id1, $id2)
196 while ($i < strlen($id1) && $i < strlen($id2) && $id1[$i] == $id2[$i]) {
199 // $i is now the number of matching characters/levels.
200 if ($i < strlen($id1) && $i < strlen($id2)) {
201 $common = substr($id1, 0, $i);
202 $pfx1 = substr($id1, $i, 1);
203 $pfx2 = substr($id2, $i, 1);
204 $tmpname = $common . '#';
205 // To avoid collision use 3 renames.
206 fuzzyRename($common . $pfx1, $common . '#');
207 fuzzyRename($common . $pfx2, $common . $pfx1);
208 fuzzyRename($common . '#', $common . $pfx2);
212 function tableNameFromLayout($layout_id)
214 // Skip layouts that store data in vertical tables.
215 if (substr($layout_id, 0, 3) == 'LBF' ||
substr($layout_id, 0, 3) == 'LBT' ||
$layout_id == "FACUSR") {
218 if ($layout_id == "DEM") {
219 $tablename = "patient_data";
220 } elseif ($layout_id == "HIS") {
221 $tablename = "history_data";
222 } elseif ($layout_id == "SRH") {
223 $tablename = "lists_ippf_srh";
224 } elseif ($layout_id == "CON") {
225 $tablename = "lists_ippf_con";
226 } elseif ($layout_id == "GCA") {
227 $tablename = "lists_ippf_gcac";
229 die(xlt('Internal error in tableNameFromLayout') . '(' . text($layout_id) . ')');
234 // Call this when adding or removing a layout field. This will create or drop
235 // the corresponding table column when appropriate. Table columns are not
236 // dropped if they contain any non-empty values.
237 function addOrDeleteColumn($layout_id, $field_id, $add = true)
239 $tablename = tableNameFromLayout($layout_id);
243 // Check if the column currently exists.
244 $tmp = sqlQuery("SHOW COLUMNS FROM `$tablename` LIKE '$field_id'");
245 $column_exists = !empty($tmp);
247 if ($add && !$column_exists) {
248 sqlStatement("ALTER TABLE `$tablename` ADD `$field_id` TEXT");
251 $_SESSION['authUser'],
252 $_SESSION['authProvider'],
254 "$tablename ADD $field_id"
256 } elseif (!$add && $column_exists) {
257 // Do not drop a column that has any data.
258 $tmp = sqlQuery("SELECT `$field_id` FROM `$tablename` WHERE " .
259 "`$field_id` IS NOT NULL AND `$field_id` != '' LIMIT 1");
260 if (!isset($tmp['field_id'])) {
261 sqlStatement("ALTER TABLE `$tablename` DROP `$field_id`");
264 $_SESSION['authUser'],
265 $_SESSION['authProvider'],
267 "$tablename DROP $field_id "
273 // Call this before renaming a layout field.
274 // Renames the table column (if applicable) and returns a result status:
275 // -1 = There is no table for this layout (not an error).
276 // 0 = Rename successful.
277 // 2 = There is no column having the old name.
278 // 3 = There is already a column having the new name.
280 function renameColumn($layout_id, $old_field_id, $new_field_id)
282 $tablename = tableNameFromLayout($layout_id);
284 return -1; // Indicate rename is not relevant.
286 // Make sure old column exists.
287 $colarr = sqlQuery("SHOW COLUMNS FROM `$tablename` LIKE ?", array($old_field_id));
288 if (empty($colarr)) {
289 // Error, old name does not exist.
292 // Make sure new column does not exist.
293 $tmp = sqlQuery("SHOW COLUMNS FROM `$tablename` LIKE ?", array($new_field_id));
295 // Error, new name already in use.
298 // With MySQL you can't change just the name, you have to specify the column definition too.
299 $colstr = $colarr['Type'];
300 if ($colarr['Null'] == 'NO') {
301 $colstr .= " NOT NULL";
303 if ($colarr['Default'] !== null) {
304 $colstr .= " DEFAULT '" . add_escape_custom($colarr['Default']) . "'";
306 if ($colarr['Extra']) {
307 $colstr .= " " . $colarr['Extra'];
309 $query = "ALTER TABLE `$tablename` CHANGE `$old_field_id` `$new_field_id` $colstr";
310 sqlStatement($query);
313 $_SESSION['authUser'],
314 $_SESSION['authProvider'],
316 "$tablename RENAME $old_field_id TO $new_field_id $colstr"
318 return 0; // Indicate rename done and successful.
321 // Check authorization.
322 $thisauth = acl_check('admin', 'super');
324 die(xl('Not authorized'));
327 // The layout ID identifies the layout to be edited.
328 $layout_id = empty($_REQUEST['layout_id']) ?
'' : $_REQUEST['layout_id'];
330 // Tag style for stuff to hide if not an LBF layout. Currently just for the Source column.
331 $lbfonly = substr($layout_id, 0, 3) == 'LBF' ?
"" : "style='display:none;'";
333 // Handle the Form actions
335 if ($_POST['formaction'] == "save" && $layout_id) {
336 // If we are saving, then save.
337 $fld = $_POST['fld'];
338 for ($lino = 1; isset($fld[$lino]['id']); ++
$lino) {
340 $field_id = formTrim($iter['id']);
341 $field_id_original = formTrim($iter['originalid']);
342 $data_type = formTrim($iter['datatype']);
343 $listval = $data_type == 34 ?
formTrim($iter['contextName']) : formTrim($iter['list_id']);
344 $action = $iter['action'];
345 if ($action == 'value') {
346 $action = 'value=' . $iter['value'];
349 // Skip conditions for the line are stored as a serialized array.
350 $condarr = array('action' => $action);
352 for (; !empty($iter['condition_id'][$cix]); ++
$cix) {
353 $andor = empty($iter['condition_andor'][$cix]) ?
'' : $iter['condition_andor'][$cix];
354 $condarr[$cix] = array(
355 'id' => strip_escape_custom($iter['condition_id' ][$cix]),
356 'itemid' => strip_escape_custom($iter['condition_itemid' ][$cix]),
357 'operator' => strip_escape_custom($iter['condition_operator'][$cix]),
358 'value' => strip_escape_custom($iter['condition_value' ][$cix]),
359 'andor' => strip_escape_custom($andor),
362 $conditions = $cix ?
serialize($condarr) : '';
365 if ($field_id != $field_id_original) {
366 if (renameColumn($layout_id, $field_id_original, $field_id) > 0) {
367 // If column rename had an error then don't rename it here.
368 $field_id = $field_id_original;
371 sqlStatement("UPDATE layout_options SET " .
372 "field_id = '" . formDataCore($field_id) . "', " .
373 "source = '" . formTrim($iter['source']) . "', " .
374 "title = '" . formDataCore($iter['title']) . "', " .
375 "group_id = '" . formTrim($iter['group']) . "', " .
376 "seq = '" . formTrim($iter['seq']) . "', " .
377 "uor = '" . formTrim($iter['uor']) . "', " .
378 "fld_length = '" . formTrim($iter['lengthWidth']) . "', " .
379 "fld_rows = '" . formTrim($iter['lengthHeight']) . "', " .
380 "max_length = '" . formTrim($iter['maxSize']) . "', " .
381 "titlecols = '" . formTrim($iter['titlecols']) . "', " .
382 "datacols = '" . formTrim($iter['datacols']) . "', " .
383 "data_type= '$data_type', " .
384 "list_id= '" . $listval . "', " .
385 "list_backup_id= '" . formTrim($iter['list_backup_id']) . "', " .
386 "edit_options = '" . json_encode($iter['edit_options']) . "', " .
387 "default_value = '" . formTrim($iter['default']) . "', " .
388 "description = '" . formTrim($iter['desc']) . "', " .
389 "conditions = '" . add_escape_custom($conditions) . "', " .
390 "validation = '" . formTrim($iter['validation']) . "' " .
391 "WHERE form_id = '$layout_id' AND field_id = '$field_id_original'");
394 } else if ($_POST['formaction'] == "addfield" && $layout_id) {
395 // Add a new field to a specific group
396 $data_type = formTrim($_POST['newdatatype']);
397 $max_length = $data_type == 3 ?
3 : 255;
398 $listval = $data_type == 34 ?
formTrim($_POST['contextName']) : formTrim($_POST['newlistid']);
399 sqlStatement("INSERT INTO layout_options (" .
400 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
401 ", titlecols, datacols, data_type, edit_options, default_value, description" .
402 ", max_length, list_id, list_backup_id " .
404 "'" . formTrim($_POST['layout_id']) . "'" .
405 ",'" . formTrim($_POST['newsource']) . "'" .
406 ",'" . formTrim($_POST['newid']) . "'" .
407 ",'" . formDataCore($_POST['newtitle']) . "'" .
408 ",'" . formTrim($_POST['newfieldgroupid']) . "'" .
409 ",'" . formTrim($_POST['newseq']) . "'" .
410 ",'" . formTrim($_POST['newuor']) . "'" .
411 ",'" . formTrim($_POST['newlengthWidth']) . "'" .
412 ",'" . formTrim($_POST['newlengthHeight']) . "'" .
413 ",'" . formTrim($_POST['newtitlecols']) . "'" .
414 ",'" . formTrim($_POST['newdatacols']) . "'" .
416 ",'" . json_encode($_POST['newedit_options']) . "'" .
417 ",'" . formTrim($_POST['newdefault']) . "'" .
418 ",'" . formTrim($_POST['newdesc']) . "'" .
419 ",'" . formTrim($_POST['newmaxSize']) . "'" .
420 ",'" . $listval . "'" .
421 ",'" . formTrim($_POST['newbackuplistid']) . "'" .
423 addOrDeleteColumn($layout_id, formTrim($_POST['newid']), true);
424 } else if ($_POST['formaction'] == "movefields" && $layout_id) {
425 // Move field(s) to a new group in the layout
426 $sqlstmt = "UPDATE layout_options SET ".
427 " group_id = '" . $_POST['targetgroup'] . "' " .
429 " form_id = '" . $_POST['layout_id'] . "' ".
430 " AND field_id IN (";
432 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
433 $sqlstmt .= $comma."'".$onefield."'";
439 sqlStatement($sqlstmt);
440 } else if ($_POST['formaction'] == "deletefields" && $layout_id) {
441 // Delete a field from a specific group
442 $sqlstmt = "DELETE FROM layout_options WHERE ".
443 " form_id = '".$_POST['layout_id']."' ".
444 " AND field_id IN (";
446 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
447 $sqlstmt .= $comma."'".$onefield."'";
452 sqlStatement($sqlstmt);
453 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
454 addOrDeleteColumn($layout_id, $onefield, false);
456 } else if ($_POST['formaction'] == "addgroup" && $layout_id) {
457 // Generate new value for layout_items.group_id.
458 $newgroupid = genGroupId($_POST['newgroupparent']);
461 "INSERT INTO layout_group_properties SET " .
462 "grp_form_id = ?, " .
463 "grp_group_id = ?, " .
465 array($layout_id, $newgroupid, $_POST['newgroupname'])
468 $data_type = formTrim($_POST['gnewdatatype']);
469 $max_length = $data_type == 3 ?
3 : 255;
470 $listval = $data_type == 34 ?
formTrim($_POST['gcontextName']) : formTrim($_POST['gnewlistid']);
471 // add a new group to the layout, with the defined field
472 sqlStatement("INSERT INTO layout_options (" .
473 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
474 ", titlecols, datacols, data_type, edit_options, default_value, description" .
475 ", max_length, list_id, list_backup_id " .
477 "'" . formTrim($_POST['layout_id']) . "'" .
478 ",'" . formTrim($_POST['gnewsource']) . "'" .
479 ",'" . formTrim($_POST['gnewid']) . "'" .
480 ",'" . formDataCore($_POST['gnewtitle']) . "'" .
481 ",'" . formTrim($newgroupid) . "'" .
482 ",'" . formTrim($_POST['gnewseq']) . "'" .
483 ",'" . formTrim($_POST['gnewuor']) . "'" .
484 ",'" . formTrim($_POST['gnewlengthWidth']) . "'" .
485 ",'" . formTrim($_POST['gnewlengthHeight']) . "'" .
486 ",'" . formTrim($_POST['gnewtitlecols']) . "'" .
487 ",'" . formTrim($_POST['gnewdatacols']) . "'" .
489 ",'" . json_encode($_POST['gnewedit_options']) . "'" .
490 ",'" . formTrim($_POST['gnewdefault']) . "'" .
491 ",'" . formTrim($_POST['gnewdesc']) . "'" .
492 ",'" . formTrim($_POST['gnewmaxSize']) . "'" .
493 ",'" . $listval . "'" .
494 ",'" . formTrim($_POST['gnewbackuplistid']) . "'" .
496 addOrDeleteColumn($layout_id, formTrim($_POST['gnewid']), true);
497 } /**********************************************************************
498 else if ($_POST['formaction'] == "deletegroup" && $layout_id) {
499 // drop the fields from the related table (this is critical)
500 $res = sqlStatement("SELECT field_id FROM layout_options WHERE " .
501 "form_id = '" . $_POST['layout_id'] . "' ".
502 "AND group_name = '" . $_POST['deletegroupname'] . "'");
503 while ($row = sqlFetchArray($res)) {
504 addOrDeleteColumn($layout_id, $row['field_id'], false);
507 // Delete an entire group from the form
508 sqlStatement("DELETE FROM layout_options WHERE ".
509 " form_id = '".$_POST['layout_id']."' ".
510 " AND group_name = '".$_POST['deletegroupname']."'"
513 **********************************************************************/
515 else if ($_POST['formaction'] == "movegroup" && $layout_id) {
516 // Note that in some cases below the swapGroups() call will do nothing.
518 "SELECT DISTINCT group_id " .
519 "FROM layout_options WHERE form_id = ? ORDER BY group_id",
522 $row = sqlFetchArray($res);
523 $id1 = $row['group_id'];
524 while ($row = sqlFetchArray($res)) {
525 $id2 = $row['group_id'];
526 if ($_POST['movedirection'] == 'up') { // moving up
527 if ($id2 == $_POST['movegroupname']) {
528 swapGroups($id2, $id1);
531 } else { // moving down
532 if ($id1 == $_POST['movegroupname']) {
533 swapGroups($id1, $id2);
539 } // Renaming a group. This might include moving to a different parent group.
540 else if ($_POST['formaction'] == "renamegroup" && $layout_id) {
541 $newparent = $_POST['renamegroupparent']; // this is an ID
542 $oldid = $_POST['renameoldgroupname']; // this is an ID
543 $oldparent = substr($oldid, 0, -1);
545 if ($newparent != $oldparent) {
546 // Different parent, generate a new child prefix character.
547 $newid = genGroupId($newparent);
549 "UPDATE layout_options SET group_id = ? " .
550 "WHERE form_id = ? AND group_id = ?",
551 array($newid, $layout_id, $oldid)
554 $query = "UPDATE layout_group_properties SET " .
555 "grp_group_id = ?, grp_title = ? " .
556 "WHERE grp_form_id = ? AND grp_group_id = ?";
557 sqlStatement($query, array($newid, $_POST['renamegroupname'], $layout_id, $oldid));
560 // Get the selected form's elements.
562 $res = sqlStatement("SELECT * FROM layout_options WHERE " .
563 "form_id = '$layout_id' ORDER BY group_id, seq");
566 // global counter for field numbers
571 // This is called to generate a select option list for fields within this form.
572 // Used for selecting a field for testing in a skip condition.
574 function genFieldOptionList($current = '')
577 $option_list = "<option value=''>-- " . xlt('Please Select') . " --</option>";
579 $query = "SELECT field_id FROM layout_options WHERE form_id = ? ORDER BY group_id, seq";
580 $res = sqlStatement($query, array($layout_id));
581 while ($row = sqlFetchArray($res)) {
582 $field_id = $row['field_id'];
583 $option_list .= "<option value='" . attr($field_id) . "'";
584 if ($field_id == $current) {
585 $option_list .= " selected";
587 $option_list .= ">" . text($field_id) . "</option>";
593 // Write one option line to the form.
595 function writeFieldLine($linedata)
597 global $fld_line_no, $sources, $lbfonly, $extra_html,$validations;
599 $checked = $linedata['default_value'] ?
" checked" : "";
601 //echo " <tr bgcolor='$bgcolor'>\n";
602 echo " <tr id='fld[$fld_line_no]' class='".($fld_line_no %
2 ?
'even' : 'odd')."'>\n";
604 echo " <td class='optcell' nowrap>";
605 // tuck the group_name INPUT in here
606 echo "<input type='hidden' name='fld[$fld_line_no][group]' value='" .
607 htmlspecialchars($linedata['group_id'], ENT_QUOTES
) . "' class='optin' />";
608 // Original field ID.
609 echo "<input type='hidden' name='fld[$fld_line_no][originalid]' value='" .
610 attr($linedata['field_id']) . "' />";
612 echo "<input type='checkbox' class='selectfield' ".
613 "name='" . $linedata['group_id'] . "~" . $linedata['field_id'] . "' " .
614 "id='" . $linedata['group_id'] . "~" . $linedata['field_id'] . "' " .
615 "title='" . xla('Select field') . "' />";
617 echo "<input type='text' name='fld[$fld_line_no][seq]' id='fld[$fld_line_no][seq]' value='" .
618 htmlspecialchars($linedata['seq'], ENT_QUOTES
) . "' size='2' maxlength='4' " .
619 "class='optin' style='width:32pt' />";
622 echo " <td align='center' class='optcell' $lbfonly>";
623 echo "<select class='form-control' name='fld[$fld_line_no][source]' class='optin' $lbfonly>";
624 foreach ($sources as $key => $value) {
625 echo "<option value='" . attr($key) . "'";
626 if ($key == $linedata['source']) {
630 echo ">" . text($value) . "</option>\n";
636 echo " <td align='left' class='optcell'>";
637 echo "<input type='text' name='fld[$fld_line_no][id]' value='" .
638 htmlspecialchars($linedata['field_id'], ENT_QUOTES
) . "' size='15' maxlength='63' " .
639 "class='optin' style='width:100%' onclick='FieldIDClicked(this)' />";
642 echo " <td align='center' class='optcell'>";
643 echo "<input type='text' id='fld[$fld_line_no][title]' name='fld[$fld_line_no][title]' value='" .
644 htmlspecialchars($linedata['title'], ENT_QUOTES
) . "' size='15' maxlength='63' class='optin' style='width:100%' />";
647 // if not english and set to translate layout labels, then show the translation
648 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
649 echo "<td align='center' class='translation' >" . htmlspecialchars(xl($linedata['title']), ENT_QUOTES
) . "</td>\n";
652 echo " <td align='center' class='optcell'>";
653 echo "<select class='form-control' name='fld[$fld_line_no][uor]' class='optin'>";
654 foreach (array(0 =>xl('Unused'), 1 =>xl('Optional'), 2 =>xl('Required')) as $key => $value) {
655 echo "<option value='$key'";
656 if ($key == $linedata['uor']) {
660 echo ">$value</option>\n";
666 echo " <td align='center' class='optcell'>";
667 echo "<select class='form-control' name='fld[$fld_line_no][datatype]' id='fld[$fld_line_no][datatype]' onchange=NationNotesContext('".$fld_line_no."',this.value)>";
668 echo "<option value=''></option>";
670 foreach ($datatypes as $key => $value) {
671 if ($linedata['data_type'] == $key) {
672 echo "<option value='$key' selected>$value</option>";
674 echo "<option value='$key'>$value</option>";
681 echo " <td align='center' class='optcell'>";
682 if ($linedata['data_type'] == 2 ||
$linedata['data_type'] == 3 ||
683 $linedata['data_type'] == 21 ||
$linedata['data_type'] == 22 ||
684 $linedata['data_type'] == 23 ||
$linedata['data_type'] == 25 ||
685 $linedata['data_type'] == 27 ||
$linedata['data_type'] == 28 ||
686 $linedata['data_type'] == 32 ||
$linedata['data_type'] == 15 ||
687 $linedata['data_type'] == 40
689 // Show the width field
690 echo "<input type='text' name='fld[$fld_line_no][lengthWidth]' value='" .
691 htmlspecialchars($linedata['fld_length'], ENT_QUOTES
) .
692 "' size='2' maxlength='10' class='optin' title='" . xla('Width') . "' />";
693 if ($linedata['data_type'] == 3 ||
$linedata['data_type'] == 40) {
694 // Show the height field
695 echo "<input type='text' name='fld[$fld_line_no][lengthHeight]' value='" .
696 htmlspecialchars($linedata['fld_rows'], ENT_QUOTES
) .
697 "' size='2' maxlength='10' class='optin' title='" . xla('Height') . "' />";
699 // Hide the height field
700 echo "<input type='hidden' name='fld[$fld_line_no][lengthHeight]' value=''>";
703 // all other data_types (hide both the width and height fields
704 echo "<input type='hidden' name='fld[$fld_line_no][lengthWidth]' value=''>";
705 echo "<input type='hidden' name='fld[$fld_line_no][lengthHeight]' value=''>";
710 echo " <td align='center' class='optcell'>";
711 echo "<input type='text' name='fld[$fld_line_no][maxSize]' value='" .
712 htmlspecialchars($linedata['max_length'], ENT_QUOTES
) .
713 "' size='1' maxlength='10' class='optin' style='width:100%' " .
714 "title='" . xla('Maximum Size (entering 0 will allow any size)') . "' />";
717 echo " <td align='center' class='optcell'>";
718 if ($linedata['data_type'] == 1 ||
$linedata['data_type'] == 21 ||
719 $linedata['data_type'] == 22 ||
$linedata['data_type'] == 23 ||
720 $linedata['data_type'] == 25 ||
$linedata['data_type'] == 26 ||
721 $linedata['data_type'] == 27 ||
$linedata['data_type'] == 32 ||
722 $linedata['data_type'] == 33 ||
$linedata['data_type'] == 34 ||
723 $linedata['data_type'] == 36) {
725 $disp = "style='display:none'";
726 if ($linedata['data_type'] == 34) {
727 $type = "style='display:none'";
731 echo "<input type='text' name='fld[$fld_line_no][list_id]' id='fld[$fld_line_no][list_id]' value='" .
732 htmlspecialchars($linedata['list_id'], ENT_QUOTES
) . "'".$type.
733 " size='6' maxlength='100' class='optin listid' style='width:100%;cursor:pointer'".
734 "title='". xl('Choose list') . "' />";
736 echo "<select class='form-control' name='fld[$fld_line_no][contextName]' id='fld[$fld_line_no][contextName]' ".$disp.">";
737 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
738 while ($row = sqlFetchArray($res)) {
740 if ($linedata['list_id'] == $row['cl_list_item_long']) {
744 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."' ".$sel.">".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
749 // all other data_types
750 echo "<input type='hidden' name='fld[$fld_line_no][list_id]' value=''>";
756 echo " <td align='center' class='optcell'>";
757 if ($linedata['data_type'] == 1 ||
$linedata['data_type'] == 26 ||
758 $linedata['data_type'] == 33 ||
$linedata['data_type'] == 36) {
759 echo "<input type='text' name='fld[$fld_line_no][list_backup_id]' value='" .
760 htmlspecialchars($linedata['list_backup_id'], ENT_QUOTES
) .
761 "' size='3' maxlength='100' class='optin listid' style='cursor:pointer; width:100%' />";
763 echo "<input type='hidden' name='fld[$fld_line_no][list_backup_id]' value=''>";
769 echo " <td align='center' class='optcell'>";
770 echo "<input type='text' name='fld[$fld_line_no][titlecols]' value='" .
771 htmlspecialchars($linedata['titlecols'], ENT_QUOTES
) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
774 echo " <td align='center' class='optcell'>";
775 echo "<input type='text' name='fld[$fld_line_no][datacols]' value='" .
776 htmlspecialchars($linedata['datacols'], ENT_QUOTES
) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
778 /* Below for compatabilty with existing string modifiers. */
779 if (strpos($linedata['edit_options'], ',') === false && ! empty($linedata['edit_options'])) {
780 json_decode($linedata['edit_options']);
781 if (is_string($linedata['edit_options']) && ! (json_last_error() === JSON_ERROR_NONE
)) { // hopefully string of characters.
782 $t = str_split(trim($linedata['edit_options']));
783 $linedata['edit_options'] = json_encode($t); // convert to array select understands.
786 echo " <td align='center' class='optcell' title='" . xla("Add modifiers for this field type. You may select more than one.") . "'>";
787 echo "<select id='fld[$fld_line_no][edit_options]' name='fld[$fld_line_no][edit_options][]' class='typeAddons optin' size=3 multiple data-set='" .
788 trim($linedata['edit_options']) . "' ></select></td>\n";
790 if ($linedata['data_type'] == 31) {
791 echo " <td align='center' class='optcell'>";
792 echo "<textarea name='fld[$fld_line_no][desc]' rows='3' cols='35' class='optin' style='width:100%'>" .
793 $linedata['description'] . "</textarea>";
794 echo "<input type='hidden' name='fld[$fld_line_no][default]' value='" .
795 htmlspecialchars($linedata['default_value'], ENT_QUOTES
) . "' />";
798 echo " <td align='center' class='optcell' >";
799 echo "<input type='text' name='fld[$fld_line_no][desc]' value='" .
800 htmlspecialchars($linedata['description'], ENT_QUOTES
) .
801 "' size='30' class='optin' style='width:100%' />";
802 echo "<input type='hidden' name='fld[$fld_line_no][default]' value='" .
803 htmlspecialchars($linedata['default_value'], ENT_QUOTES
) . "' />";
805 // if not english and showing layout labels, then show the translation of Description
806 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
807 echo "<td align='center' class='translation'>" .
808 htmlspecialchars(xl($linedata['description']), ENT_QUOTES
) . "</td>\n";
812 // The "?" to click on for yet more field attributes.
813 echo " <td class='bold' id='querytd_$fld_line_no' style='cursor:pointer;";
814 if (!empty($linedata['conditions']) ||
!empty($linedata['validation'])) {
815 echo "background-color:#77ff77;";
818 echo "' onclick='extShow($fld_line_no, this)' align='center' ";
819 echo "title='" . xla('Click here to view/edit more details') . "'>";
820 echo " ? ";
825 // Create a floating div for the additional attributes of this field.
826 $conditions = empty($linedata['conditions']) ?
827 array(0 => array('id' => '', 'itemid' => '', 'operator' => '', 'value' => '')) :
828 unserialize($linedata['conditions']);
829 $action = empty($conditions['action']) ?
'skip' : $conditions['action'];
830 $action_value = $action == 'skip' ?
'' : substr($action, 6);
832 $extra_html .= "<div id='ext_$fld_line_no' " .
833 "style='position:absolute;width:750px;border:1px solid black;" .
834 "padding:2px;background-color:#cccccc;visibility:hidden;" .
835 "z-index:1000;left:-1000px;top:0px;font-size:8pt;'>\n" .
836 "<table width='100%'>\n" .
838 " <th colspan='3' align='left' class='bold'>" .
839 xlt('For') . " " . text($linedata['field_id']) . " " .
840 "<select name='fld[$fld_line_no][action]' onchange='actionChanged($fld_line_no)'>" .
841 "<option value='skip' " . ($action == 'skip' ?
'selected' : '') . ">" . xlt('hide this field') . "</option>" .
842 "<option value='value' " . ($action != 'skip' ?
'selected' : '') . ">" . xlt('set value to') . "</option>" .
844 "<input type='text' name='fld[$fld_line_no][value]' value='" . attr($action_value) . "' size='15' />" .
847 " <th colspan='2' align='right' class='text'><input type='button' " .
848 "value='" . xla('Close') . "' onclick='extShow($fld_line_no, false)' /> </th>\n" .
851 " <th align='left' class='bold'>" . xlt('Field ID') . "</th>\n" .
852 " <th align='left' class='bold'>" . xlt('List item ID') . "</th>\n" .
853 " <th align='left' class='bold'>" . xlt('Operator') . "</th>\n" .
854 " <th align='left' class='bold'>" . xlt('Value if comparing') . "</th>\n" .
855 " <th align='left' class='bold'> </th>\n" .
857 // There may be multiple condition lines for each field.
858 foreach ($conditions as $i => $condition) {
859 if (!is_numeric($i)) {
860 continue; // skip if 'action'
864 " <td align='left'>\n" .
865 " <select name='fld[$fld_line_no][condition_id][$i]' onchange='cidChanged($fld_line_no, $i)'>" .
866 genFieldOptionList($condition['id']) . " </select>\n" .
868 " <td align='left'>\n" .
869 // List item choices are populated on the client side but will need the current value,
870 // so we insert a temporary option here to hold that value.
871 " <select name='fld[$fld_line_no][condition_itemid][$i]'><option value='" .
872 attr($condition['itemid']) . "'>...</option></select>\n" .
874 " <td align='left'>\n" .
875 " <select name='fld[$fld_line_no][condition_operator][$i]'>\n";
877 'eq' => xl('Equals'),
878 'ne' => xl('Does not equal'),
879 'se' => xl('Is selected'),
880 'ns' => xl('Is not selected'),
881 ) as $key => $value) {
882 $extra_html .= " <option value='$key'";
883 if ($key == $condition['operator']) {
884 $extra_html .= " selected";
887 $extra_html .= ">" . text($value) . "</option>\n";
893 " <td align='left' title='" . xla('Only for comparisons') . "'>\n" .
894 " <input type='text' name='fld[$fld_line_no][condition_value][$i]' value='" .
895 attr($condition['value']) . "' size='15' maxlength='63' />\n" .
897 if (!isset($conditions[$i +
1])) {
899 " <td align='right' title='" . xla('Add a condition') . "'>\n" .
900 " <input type='button' value='+' onclick='extAddCondition($fld_line_no,this)' />\n" .
904 " <td align='right'>\n" .
905 " <select name='fld[$fld_line_no][condition_andor][$i]'>\n";
909 ) as $key => $value) {
910 $extra_html .= " <option value='$key'";
911 if ($key == $condition['andor']) {
912 $extra_html .= " selected";
915 $extra_html .= ">" . text($value) . "</option>\n";
930 $extra_html .= "<table width='100%'>\n" .
932 " <td colspan='3' align='left' class='bold'>\"" . text($linedata['field_id']) . "\" " .
933 xlt('will have the following validation rules') . ":</td>\n" .
936 " <td align='left' class='bold'>" . xlt('Validation rule') . " </td>\n" .
939 " <td align='left' title='" . xla('Select a validation rule') . "'>\n" .
942 " <select name='fld[$fld_line_no][validation]' onchange='valChanged($fld_line_no)'>\n" .
944 if (empty($linedata['validation'])) {
945 $extra_html .= " selected";
948 $extra_html .= ">-- " . xlt('Please Select') . " --</option>";
949 foreach ($validations as $key => $value) {
950 $extra_html .= " <option value='$key'";
951 if ($key == $linedata['validation']) {
952 $extra_html .= " selected";
955 $extra_html .= ">" . text($value) . "</option>\n";
958 $extra_html .="</select>\n" .
970 <?php Header
::setupHeader('select2'); ?
>
972 <title
><?php
xl('Layout Editor', 'e'); ?
></title
>
975 .orgTable tr
.head
{ font
-size
:8pt
; background
-color
:#cccccc; }
976 .orgTable tr
.detail
{ font
-size
:8pt
; }
977 .orgTable td
{ font
-size
:8pt
; }
978 .orgTable input
{ font
-size
:8pt
; }
979 .orgTable select
{ font
-size
:8pt
; }
980 a
, a
:visited
, a
:hover
{ color
:#0000cc; }
982 .optin
{ background
: transparent
; }
984 margin
: 0pt
0pt
8pt
0pt
;
990 border
-collapse
: collapse
;
995 background
-color
: #ddddff;
996 padding
: 3px
0px
3px
0px
;
999 background
-color
: #ffdddd;
1000 padding
: 3px
0px
3px
0px
;
1002 .help
{ cursor
: help
; }
1003 .layouts_title
{ font
-size
: 110%
; }
1009 border
: 2px solid blue
;
1010 background
-color
: yellow
;
1013 .select2
-container
--default .select2
-selection
--multiple
{
1016 .select2
-search__field
{
1018 width
: 0 !important
;
1020 .select2
-selection__choice
{
1023 .select2
-container
{
1025 opacity
: 0.99 !important
;
1030 // Helper functions for positioning the floating divs.
1031 function extGetX(elem
) {
1033 while(elem
!= null) {
1034 x +
= elem
.offsetLeft
;
1035 elem
= elem
.offsetParent
;
1039 function extGetY(elem
) {
1041 while(elem
!= null) {
1042 y +
= elem
.offsetTop
;
1043 elem
= elem
.offsetParent
;
1048 // Show or hide the "extras" div for a row.
1050 function extShow(lino
, show
) {
1051 var thisdiv
= document
.getElementById("ext_" + lino
);
1053 extdiv
.style
.visibility
= 'hidden';
1054 extdiv
.style
.left
= '-1000px';
1055 extdiv
.style
.top
= '0px';
1057 if (show
&& thisdiv
!= extdiv
) {
1059 var dw
= window
.innerWidth ? window
.innerWidth
- 20 : document
.body
.clientWidth
;
1060 x
= dw
- extdiv
.offsetWidth
;
1062 var y
= extGetY(show
) + show
.offsetHeight
;
1063 extdiv
.style
.left
= x
;
1064 extdiv
.style
.top
= y
;
1065 extdiv
.style
.visibility
= 'visible';
1072 // Show or hide the value field for a "Set value to" condition.
1073 function actionChanged(lino
) {
1074 var f
= document
.forms
[0];
1075 var eaction
= f
['fld[' + lino +
'][action]'];
1076 var evalue
= f
['fld[' + lino +
'][value]'];
1077 evalue
.style
.display
= eaction
.value
== 'skip' ?
'none' : '';
1080 // Add an extra condition line for the given row.
1081 function extAddCondition(lino
, btnelem
) {
1082 var f
= document
.forms
[0];
1085 // Get index of next condition line.
1086 while (f
['fld[' + lino +
'][condition_id][' + i +
']']) ++i
;
1087 if (i
== 0) alert('f["fld[' + lino +
'][condition_id][' + i +
']"] <?php echo xls('not found
') ?>');
1089 // Get containing <td>, <tr> and <table> nodes of the "+" button.
1090 var tdplus
= btnelem
.parentNode
;
1091 var trelem
= tdplus
.parentNode
;
1092 var telem
= trelem
.parentNode
;
1094 // Replace contents of the tdplus cell.
1096 "<select name='fld[" + lino +
"][condition_andor][" + i +
"]'>" +
1097 "<option value='and'><?php echo xls('And') ?></option>" +
1098 "<option value='or' ><?php echo xls('Or') ?></option>" +
1102 var newtrelem
= telem
.insertRow(i+
2);
1103 newtrelem
.innerHTML
=
1104 "<td align='left'>" +
1105 "<select name='fld[" + lino +
"][condition_id][" + i +
"]' onchange='cidChanged(" + lino +
"," + i +
")'>" +
1106 "<?php echo addslashes(genFieldOptionList()) ?>" +
1109 "<td align='left'>" +
1110 "<select name='fld[" + lino +
"][condition_itemid][" + i +
"]' style='display:none' />" +
1112 "<td align='left'>" +
1113 "<select name='fld[" + lino +
"][condition_operator][" + i +
"]'>" +
1114 "<option value='eq'><?php echo xls('Equals') ?></option>" +
1115 "<option value='ne'><?php echo xls('Does not equal') ?></option>" +
1116 "<option value='se'><?php echo xls('Is selected') ?></option>" +
1117 "<option value='ns'><?php echo xls('Is not selected') ?></option>" +
1120 "<td align='left'>" +
1121 "<input type='text' name='fld[" + lino +
"][condition_value][" + i +
"]' value='' size='15' maxlength='63' />" +
1123 "<td align='right'>" +
1124 "<input type='button' value='+' onclick='extAddCondition(" + lino +
",this)' />" +
1128 // This is called when a field ID is chosen for testing within a skip condition.
1129 // It checks to see if a corresponding list item must also be chosen for the test, and
1130 // if so then inserts the dropdown for selecting an item from the appropriate list.
1131 function setListItemOptions(lino
, seq
, init
) {
1132 var f
= document
.forms
[0];
1133 var target
= 'fld[' + lino +
'][condition_itemid][' + seq +
']';
1134 // field_id is the ID of the field that the condition will test.
1135 var field_id
= f
['fld[' + lino +
'][condition_id][' + seq +
']'].value
;
1137 f
[target
].options
.length
= 0;
1138 f
[target
].style
.display
= 'none';
1141 // Find the occurrence of that field in the layout.
1144 var idname
= 'fld[' + i +
'][id]';
1146 alert('<?php echo xls('Condition field not found
') ?>: ' + field_id
);
1149 if (f
[idname
].value
== field_id
) break;
1152 // If this is startup initialization then preserve the current value.
1153 var current
= init ? f
[target
].value
: '';
1154 f
[target
].options
.length
= 0;
1155 // Get the corresponding data type and list ID.
1156 var data_type
= f
['fld[' + i +
'][datatype]'].value
;
1157 var list_id
= f
['fld[' + i +
'][list_id]'].value
;
1158 // WARNING: If new data types are defined the following test may need enhancing.
1159 // We're getting out if the type does not generate multiple fields with different names.
1160 if (data_type
!= '21' && data_type
!= '22' && data_type
!= '23' && data_type
!= '25') {
1161 f
[target
].style
.display
= 'none';
1164 // OK, list item IDs do apply so go get 'em.
1165 // This happens asynchronously so the generated code needs to stand alone.
1166 f
[target
].style
.display
= '';
1167 $
.getScript('layout_listitems_ajax.php' +
1168 '?listid=' +
encodeURIComponent(list_id
) +
1169 '&target=' +
encodeURIComponent(target
) +
1170 '¤t=' +
encodeURIComponent(current
));
1173 // This is called whenever a condition's field ID selection is changed.
1174 function cidChanged(lino
, seq
) {
1176 setListItemOptions(lino
, seq
, false);
1179 // This invokes the popup to edit layout properties or add a new layout.
1180 function edit_layout_props(groupid
) {
1181 dlgopen('edit_layout_props.php?layout_id=<?php echo attr($layout_id); ?>&group_id=' + groupid
,
1182 '_blank', 700, 550);
1185 // callback from edit_layout_props.php:
1186 function refreshme(layout_id
) {
1187 location
.href
= 'edit_layout.php?layout_id=' + layout_id
;
1190 // This is called whenever a validation rule field ID selection is changed.
1191 function valChanged(lino
) {
1195 function changeColor(lino
){
1196 var thisid
= document
.forms
[0]['fld[' + lino +
'][condition_id][0]'].value
;
1197 var thisValId
= document
.forms
[0]['fld[' + lino +
'][validation]'].value
;
1198 var thistd
= document
.getElementById("querytd_" + lino
);
1199 if(thisid
!='' || thisValId
!='') {
1200 thistd
.style
.backgroundColor
= '#77ff77';
1202 thistd
.style
.backgroundColor
='';
1206 // Call this to disable the warning about unsaved changes and submit the form.
1207 function mySubmit() {
1208 somethingChanged
= false;
1209 top
.restoreSession();
1210 document
.forms
[0].submit();
1213 // User is about to do something that would discard any unsaved changes.
1214 // Return true if that is OK.
1215 function myChangeCheck() {
1216 if (somethingChanged
) {
1217 if (!confirm('<?php echo xls('You have unsaved changes
. Abandon them?
'); ?>')) {
1220 // Do not set somethingChanged to false here because if they cancel the
1221 // action then the previously changed values will still be of interest.
1230 <body
class="body_top admin-layout">
1231 <div
class="container-responsive">
1232 <form method
='post' name
='theform' id
='theform' action
='edit_layout.php'>
1233 <input type
="hidden" name
="formaction" id
="formaction" value
="">
1234 <!-- elements used to identify a field to delete
-->
1235 <input type
="hidden" name
="deletefieldid" id
="deletefieldid" value
="">
1236 <input type
="hidden" name
="deletefieldgroup" id
="deletefieldgroup" value
="">
1237 <!-- elements used to identify a group to delete
-->
1239 <input type
="hidden" name
="deletegroupname" id
="deletegroupname" value
="">
1241 <!-- elements used to change the group order
-->
1242 <input type
="hidden" name
="movegroupname" id
="movegroupname" value
="">
1243 <input type
="hidden" name
="movedirection" id
="movedirection" value
="">
1244 <!-- elements used to select more than one field
-->
1245 <input type
="hidden" name
="selectedfields" id
="selectedfields" value
="">
1246 <input type
="hidden" id
="targetgroup" name
="targetgroup" value
="">
1247 <div
class="lbfmenubar">
1249 <b
><?php
xl('Edit layout', 'e'); ?
>:</b
> 
;
1250 <select name
='layout_id' id
='layout_id' class='form-control' style
='display:inline-block;margin-bottom:5px;width:15%;'>
1251 <option value
=''>-- <?php
echo xl('Select') ?
> --</option
>
1254 foreach ($layouts as $key => $value) {
1255 if ($value[0] != $lastgroup) {
1257 echo " </optgroup>\n";
1259 echo " <optgroup label='" . attr($value[0]) . "'>\n";
1260 $lastgroup = $value[0];
1262 echo " <option value='" . attr($key) . "'";
1263 if ($key == $layout_id) {
1266 echo ">" . text($value[1]) . "</option>\n";
1269 echo " </optgroup>\n";
1275 <?php
if ($layout_id) { ?
>
1276 <input type
='button' value
='<?php echo xla('Layout Properties
'); ?>' onclick
='edit_layout_props("")' /> 
;
1277 <input type
='button' class='addgroup' id
='addgroup' value
='<?php echo xla('Add Group
'); ?>' />
1278 <span style
="font-size:90%">  
;
1279 <input type
='button' class="btn btn-danger"name
='save' id
='save' value
='<?php xl('Save Changes
', 'e
'); ?>' /></span
>  
; 
;
1280 <?php
xl('With selected:', 'e');?
>
1281 <input type
='button' name
='deletefields' id
='deletefields' value
='<?php xl('Delete
', 'e
'); ?>' style
="font-size:90%" disabled
="disabled" />
1282 <input type
='button' name
='movefields' id
='movefields' value
='<?php xl('Move to
...', 'e
'); ?>' style
="font-size:90%" disabled
="disabled" /></span
>
1284 <input type
='button' value
='<?php echo xla('New Layout
'); ?>' onclick
='edit_layout_props("")' /> 
;
1290 // Load array of properties for this layout and its groups.
1292 $gres = sqlStatement("SELECT * FROM layout_group_properties WHERE grp_form_id = ? " .
1293 "ORDER BY grp_group_id", array($layout_id));
1294 while ($grow = sqlFetchArray($gres)) {
1295 $grparr[$grow['grp_group_id']] = $grow;
1298 $prevgroup = "!@#asdf1234"; // an unlikely group ID
1299 $firstgroup = true; // flag indicates it's the first group to be displayed
1301 while ($row = sqlFetchArray($res)) {
1302 $group_id = $row['group_id'];
1303 if ($group_id != $prevgroup) {
1304 if ($firstgroup == false) {
1305 echo "</tbody></table></div>\n";
1307 echo "<div id='" . $group_id . "' class='group'>";
1308 echo "<div class='text bold layouts_title' style='position:relative; background-color: #eef'>";
1310 // Get the fully qualified descriptive name of this group (i.e. including ancestor names).
1312 for ($i = 1; $i <= strlen($group_id); ++
$i) {
1314 $gdispname .= ' / ';
1316 $gdispname .= $grparr[substr($group_id, 0, $i)]['grp_title'];
1318 $gmyname = $grparr[$group_id]['grp_title'];
1320 echo text($gdispname);
1322 // if not english and set to translate layout labels, then show the translation of group name
1323 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1324 echo "<span class='translation'>>> " . xlt($gdispname) . "</span>";
1329 echo " <input type='button' class='addfield' id='addto~$group_id' value='" . xla('Add Field') . "'/>";
1330 echo " ";
1331 echo " <input type='button' class='renamegroup' id='$group_id~$gmyname' value='" . xla('Rename Group') . "'/>";
1332 /******************************************************************
1333 echo " ";
1334 echo " <input type='button' class='deletegroup' id='$group_id' value='" . xl('Delete Group') . "'/>";
1335 ******************************************************************/
1336 echo " ";
1337 echo " <input type='button' class='movegroup' id='$group_id~up' value='" . xl('Move Up') . "'/>";
1338 echo " ";
1339 echo " <input type='button' class='movegroup' id='$group_id~down' value='" . xl('Move Down') . "'/>";
1340 echo " ";
1341 echo "<input type='button' value='" . xla('Group Properties') . "' onclick='edit_layout_props(\"$group_id\")' />";
1343 $firstgroup = false;
1345 <table
class='table table-condensed table-striped'>
1348 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1349 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1350 <th style
='width:5%'><?php
xl('ID', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('A unique value to identify this field, not visible to the user', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1351 <th style
='width:10%'><?php
xl('Label', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('The label that appears to the user on the form', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1352 <?php
// if not english and showing layout label translations, then show translation header for title
1353 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1354 echo "<th>" . xl('Translation')."<span class='help' title='" . xl('The translated label that will appear on the form in current language') . "'> (?)</span></th>";
1356 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1357 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1358 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1359 <th style
='width:1%'><?php
xl('Max Size', 'e'); ?
></th
>
1360 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1361 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1362 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1363 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1364 <th style
='width:5%'><?php
xl('Options', 'e'); ?
></th
>
1365 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1366 <?php
// if not english and showing layout label translations, then show translation header for description
1367 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1368 echo "<th>" . xl('Translation')."<span class='help' title='" . xl('The translation of description in current language')."'> (?)</span></th>";
1370 <th style
='width:1%'><?php
echo xlt('?'); ?
></th
>
1376 } // end if-group_name
1378 writeFieldLine($row);
1379 $prevgroup = $group_id;
1386 <?php
echo $extra_html; ?
>
1390 <!-- template DIV that appears when user chooses to rename an existing group
-->
1391 <div id
="renamegroupdetail"
1392 style
="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1393 <input type
="hidden" name
="renameoldgroupname" id
="renameoldgroupname" value
="" />
1394 <?php
echo xlt('Group Name'); ?
>:
1395 <input type
="text" size
="20" maxlength
="30" name
="renamegroupname" id
="renamegroupname" />
1397 <?php
echo xlt('Parent'); ?
>:
1398 <?php
echo genGroupSelector('renamegroupparent', $layout_id); ?
>
1400 <input type
="button" class="saverenamegroup .btn-save" value
="<?php echo xla('Rename Group'); ?>" />
1401 <input type
="button" class="cancelrenamegroup" value
="<?php echo xla('Cancel'); ?>" />
1404 <!-- template DIV that appears when user chooses to add a
new group
-->
1405 <div id
="groupdetail"
1406 style
="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1408 <?php
echo xlt('Group Name'); ?
>:
1409 <input type
="text" size
="20" maxlength
="30" name
="newgroupname" id
="newgroupname" />
1411 <?php
echo xlt('Parent'); ?
>:
1412 <?php
echo genGroupSelector('newgroupparent', $layout_id); ?
>
1414 <table
class='table table-condensed table-striped' style
="border-collapse: collapse; margin-top: 5px;">
1417 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1418 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1419 <th style
='width:5%'><?php
xl('ID', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('A unique value to identify this field, not visible to the user', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1420 <th style
='width:10%'><?php
xl('Label', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('The label that appears to the user on the form', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1421 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1422 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1423 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1424 <th style
='width:1%'><?php
xl('Max Size', 'e'); ?
></th
>
1425 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1426 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1427 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1428 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1429 <th style
='width:10%'><?php
xl('Options', 'e'); ?
></th
>
1430 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1435 <td
><input type
="text" name
="gnewseq" id
="gnewseq" value
="" size
="2" maxlength
="4"> </td
>
1436 <td
<?php
echo " $lbfonly"; ?
>>
1437 <select
class='form-control' name
='gnewsource' id
='gnewsource'>
1439 foreach ($sources as $key => $value) {
1440 echo "<option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1445 <td
><input type
="text" name
="gnewid" id
="gnewid" value
="" size
="10" maxlength
="20"
1446 onclick
='FieldIDClicked(this)'> </td
>
1447 <td
><input type
="text" name
="gnewtitle" id
="gnewtitle" value
="" size
="20" maxlength
="63"> </td
>
1449 <select
class='form-control' name
="gnewuor" id
="gnewuor">
1450 <option value
="0"><?php
xl('Unused', 'e'); ?
></option
>
1451 <option value
="1" selected
><?php
xl('Optional', 'e'); ?
></option
>
1452 <option value
="2"><?php
xl('Required', 'e'); ?
></option
>
1456 <select
class='form-control' name
='gnewdatatype' id
='gnewdatatype'>
1457 <option value
=''></option
>
1460 foreach ($datatypes as $key => $value) {
1461 echo "<option value='$key'>$value</option>";
1466 <td
><input type
="text" name
="gnewlengthWidth" id
="gnewlengthWidth" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Width'); ?>">
1467 <input type
="text" name
="gnewlengthHeight" id
="gnewlengthHeight" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Height'); ?>"></td
>
1468 <td
><input type
="text" name
="gnewmaxSize" id
="gnewmaxSize" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Maximum Size (entering 0 will allow any size)'); ?>"></td
>
1469 <td
><input type
="text" name
="gnewlistid" id
="gnewlistid" value
="" size
="8" maxlength
="100" class="listid">
1470 <select
class='form-control' name
='gcontextName' id
='gcontextName' style
='display:none'>
1472 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1473 while ($row = sqlFetchArray($res)) {
1474 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."'>".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
1479 <td
><input type
="text" name
="gnewbackuplistid" id
="gnewbackuplistid" value
="" size
="8" maxlength
="100" class="listid"></td
>
1480 <td
><input type
="text" name
="gnewtitlecols" id
="gnewtitlecols" value
="" size
="3" maxlength
="3"> </td
>
1481 <td
><input type
="text" name
="gnewdatacols" id
="gnewdatacols" value
="" size
="3" maxlength
="3"> </td
>
1482 <td
><select name
="gnewedit_options[]" id
="gnewedit_options" class="typeAddons" multiple style
='width:100%' value
="" size
="3"></select
>
1483 <input type
="hidden" name
="gnewdefault" id
="gnewdefault" value
="" /> </td
>
1484 <td
><input type
="text" name
="gnewdesc" id
="gnewdesc" value
="" size
="30"> </td
>
1489 <input type
="button" class="savenewgroup" value
=<?php
xl('Save New Group', 'e', '\'', '\''); ?
>>
1490 <input type
="button" class="cancelnewgroup" value
=<?php
xl('Cancel', 'e', '\'', '\''); ?
>>
1494 <!-- template DIV that appears when user chooses to add a
new field to a group
-->
1495 <div id
="fielddetail" class="fielddetail" style
="display: none; visibility: hidden">
1496 <input type
="hidden" name
="newfieldgroupid" id
="newfieldgroupid" value
="">
1497 <table
class="table table-condensed" style
="border-collapse: collapse;">
1500 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1501 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1502 <th style
='width:5%'><?php
xl('ID', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('A unique value to identify this field, not visible to the user', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1503 <th style
='width:10%'><?php
xl('Label', 'e'); ?
> 
;<span
class="help" title
=<?php
xl('The label that appears to the user on the form', 'e', '\'', '\''); ?
> >(?
)</span
></th
>
1504 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1505 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1506 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1507 <th style
='width:1%'><?php
xl('Max Size', 'e'); ?
></th
>
1508 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1509 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1510 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1511 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1512 <th style
='width:10%'><?php
xl('Options', 'e'); ?
></th
>
1513 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1518 <td
><input type
="text" name
="newseq" id
="newseq" value
="" size
="2" maxlength
="4"> </td
>
1519 <td
<?php
echo " $lbfonly"; ?
>>
1520 <select
class='form-control' name
='newsource' id
='newsource'>
1522 foreach ($sources as $key => $value) {
1523 echo " <option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1528 <td
><input type
="text" name
="newid" id
="newid" value
="" size
="10" maxlength
="20"
1529 onclick
='FieldIDClicked(this)'> </td
>
1530 <td
><input type
="text" name
="newtitle" id
="newtitle" value
="" size
="20" maxlength
="63"> </td
>
1532 <select
class='form-control' name
="newuor" id
="newuor">
1533 <option value
="0"><?php
xl('Unused', 'e'); ?
></option
>
1534 <option value
="1" selected
><?php
xl('Optional', 'e'); ?
></option
>
1535 <option value
="2"><?php
xl('Required', 'e'); ?
></option
>
1539 <select
class='form-control' name
='newdatatype' id
='newdatatype'>
1540 <option value
=''></option
>
1543 foreach ($datatypes as $key => $value) {
1544 echo " <option value='$key'>$value</option>\n";
1549 <td
><input type
="text" name
="newlengthWidth" id
="newlengthWidth" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Width'); ?>">
1550 <input type
="text" name
="newlengthHeight" id
="newlengthHeight" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Height'); ?>"></td
>
1551 <td
><input type
="text" name
="newmaxSize" id
="newmaxSize" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Maximum Size (entering 0 will allow any size)'); ?>"></td
>
1552 <td
><input type
="text" name
="newlistid" id
="newlistid" value
="" size
="8" maxlength
="31" class="listid">
1553 <select
class='form-control' name
='contextName' id
='contextName' style
='display:none'>
1555 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1556 while ($row = sqlFetchArray($res)) {
1557 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."'>".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
1562 <td
><input type
="text" name
="newbackuplistid" id
="newbackuplistid" value
="" size
="8" maxlength
="31" class="listid"></td
>
1563 <td
><input type
="text" name
="newtitlecols" id
="newtitlecols" value
="" size
="3" maxlength
="3"> </td
>
1564 <td
><input type
="text" name
="newdatacols" id
="newdatacols" value
="" size
="3" maxlength
="3"> </td
>
1565 <td
><select name
="newedit_options[]" id
="newedit_options" multiple
class='typeAddons' style
='width:100%'></select
>
1566 <input type
="hidden" name
="newdefault" id
="newdefault" value
="" /> </td
>
1567 <td
><input type
="text" name
="newdesc" id
="newdesc" value
="" size
="30"> </td
>
1571 <input type
="button" class="savenewfield" value
=<?php
xl('Save New Field', 'e', '\'', '\''); ?
>>
1572 <input type
="button" class="cancelnewfield" value
=<?php
xl('Cancel', 'e', '\'', '\''); ?
>>
1582 /* Field modifier objects - heading towards context based.
1583 Used by Select2 so rtl may be enabled*/
1584 <?php
echo "var fldOptions = [
1585 {id: 'A',text:'" . xla('Age') . "',ctx:['4'],ctxExcp:['0']},
1586 {id: 'B',text:'" . xla('Gestational Age') . "',ctx:['4'],ctxExcp:['0']},
1587 {id: 'F',text:'" . xla('Add Time to Date') . "',ctx:['4'],ctxExcp:['0']},
1588 {id: 'C',text:'" . xla('Capitalize') . "',ctx:['0'],ctxExcp:['4','15','40']},
1589 {id: 'D',text:'" . xla('Dup Check') . "'},
1590 {id: 'E',text:'" . xla('Dup Check on only Edit') . "'},
1591 {id: 'W',text:'" . xla('Dup Check on only New') . "'},
1592 {id: 'G',text:'" . xla('Graphable') . "'},
1593 {id: 'I',text:'" . xla('Initially Open Group') . "'},
1594 {id: 'L',text:'" . xla('Lab Order') . "'},
1595 {id: 'N',text:'" . xla('New Patient Form') . "'},
1596 {id: 'O',text:'" . xla('Order Processor') . "'},
1597 {id: 'P',text:'" . xla('Default to previous value') . "'},
1598 {id: 'R',text:'" . xla('Distributor') . "'},
1599 {id: 'T',text:'" . xla('Description is default text') . "'},
1600 {id: 'U',text:'" . xla('Capitalize all') . "'},
1601 {id: 'V',text:'" . xla('Vendor') . "'},
1602 {id: 'X',text:'" . xla('Do Not Print') . "'},
1603 {id: '0',text:'" . xla('Read Only') . "'},
1604 {id: '1',text:'" . xla('Write Once') . "'},
1605 {id: '2',text:'" . xla('Billing Code Descriptions') . "'}];\n";
1607 // Language direction for select2
1608 echo 'var langDirection = "' . $_SESSION['language_direction'] . '";';
1611 // used when selecting a list-name for a field
1614 // Support for beforeunload handler.
1615 var somethingChanged
= false;
1617 // Get the next logical sequence number for a field in the specified group.
1618 // Note it guesses and uses the existing increment value.
1619 function getNextSeq(group
) {
1620 var f
= document
.forms
[0];
1623 for (var i
= 1; true; ++i
) {
1624 var gelem
= f
['fld[' + i +
'][group]'];
1626 if (gelem
.value
!= group
) continue;
1627 var tmp
= parseInt(f
['fld[' + i +
'][seq]'].value
);
1628 if (isNaN(tmp
)) continue;
1629 if (tmp
<= seq
) continue;
1636 // jQuery stuff to make the page a little easier to use
1638 $
(document
).ready(function(){
1641 $
('.typeAddons').select2({
1645 closeOnSelect
: false,
1647 minimumResultsForSearch
: 'Infinity',
1648 containerCssClass
: ':all:',
1653 // Populate field option selects
1655 $
('.typeAddons').each(function(i
, obj
) {
1656 var v
= $
(this
).data('set')
1657 if(typeof v
!== 'undefined' && v
> ""){
1658 $
(this
).select2().val(v
).trigger("change")
1661 somethingChanged
= false;
1664 $
("#save").click(function() { SaveChanges(); });
1665 $
("#layout_id").change(function() {
1666 if (!myChangeCheck()) {
1667 $
("#layout_id").val("<?php echo $layout_id; ?>");
1672 $
(".addgroup").click(function() { AddGroup(this
); });
1673 $
(".savenewgroup").click(function() { SaveNewGroup(this
); });
1674 /******************************************************************
1675 $(".deletegroup").click(function() { DeleteGroup(this); });
1676 ******************************************************************/
1677 $
(".cancelnewgroup").click(function() { CancelNewGroup(this
); });
1678 $
(".movegroup").click(function() { MoveGroup(this
); });
1679 $
(".renamegroup").click(function() { RenameGroup(this
); });
1680 $
(".saverenamegroup").click(function() { SaveRenameGroup(this
); });
1681 $
(".cancelrenamegroup").click(function() { CancelRenameGroup(this
); });
1682 $
(".addfield").click(function() { AddField(this
); });
1683 $
("#deletefields").click(function() { DeleteFields(this
); });
1684 $
(".selectfield").click(function() {
1685 var TRparent
= $
(this
).parent().parent();
1686 $
(TRparent
).children("td").toggleClass("highlight");
1687 // disable the delete-move buttons
1688 $
("#deletefields").attr("disabled", "disabled");
1689 $
("#movefields").attr("disabled", "disabled");
1690 $
(".selectfield").each(function(i
) {
1691 // if any field is selected, enable the delete-move buttons
1692 if ($
(this
).prop("checked") == true) {
1693 $
("#deletefields").removeAttr("disabled");
1694 $
("#movefields").removeAttr("disabled");
1699 $
("#movefields").click(function() { ShowGroups(this
); });
1700 $
(".savenewfield").click(function() { SaveNewField(this
); });
1701 $
(".cancelnewfield").click(function() { CancelNewField(this
); });
1702 $
("#newtitle").blur(function() { if ($
("#newid").val() == "") $
("#newid").val($
("#newtitle").val()); });
1703 $
("#newdatatype").change(function() { ChangeList(this
.value
);});
1704 $
("#gnewdatatype").change(function() { ChangeListg(this
.value
);});
1705 $
(".listid").click(function() { ShowLists(this
); });
1707 // special class that skips the element
1708 $
(".noselect").focus(function() { $
(this
).blur(); });
1710 // Save the changes made to the form
1711 var SaveChanges
= function () {
1712 var f
= document
.forms
[0];
1713 for (var i
= 1; f
['fld['+i+
'][id]']; ++i
) {
1714 var ival
= f
['fld['+i+
'][id]'].value
;
1715 for (var j
= i +
1; f
['fld['+j+
'][id]']; ++j
) {
1716 if (ival
== f
['fld['+j+
'][id]'].value || ival
== f
['fld['+j+
'][originalid]'].value
) {
1717 alert('<?php echo xls('Error
: Duplicated field ID
'); ?>: ' + ival
);
1722 $
("#formaction").val("save");
1726 /****************************************************/
1727 /************ Group functions ***********************/
1728 /****************************************************/
1730 // display the 'new group' DIV
1731 var AddGroup
= function(btnObj
) {
1732 if (!myChangeCheck()) return;
1733 $
("#save").attr("disabled", true);
1734 // show the field details DIV
1735 $
('#groupdetail').css('visibility', 'visible');
1736 $
('#groupdetail').css('display', 'block');
1737 $
(btnObj
).parent().append($
("#groupdetail"));
1738 $
('#groupdetail > #newgroupname').focus();
1739 // Assign a sensible default sequence number.
1740 $
('#gnewseq').val(10);
1743 // save the new group to the form
1744 var SaveNewGroup
= function(btnObj
) {
1745 // the group name field can only have letters, numbers, spaces and underscores
1746 // AND it cannot start with a number
1747 if ($
("#newgroupname").val() == "") {
1748 alert("<?php xl('Group names cannot be blank', 'e'); ?>");
1751 if ($
("#newgroupname").val().match(/^
(\d+|\s+
)/)) {
1752 alert("<?php xl('Group names cannot start with numbers or spaces.', 'e'); ?>");
1755 var validname
= $
("#newgroupname").val().replace(/[^A
-za
-z0
-9 ]/g
, "_"); // match any non-word characters and replace them
1756 $
("#newgroupname").val(validname
);
1758 // now, check the first group field values
1760 // seq must be numeric and <= 9999
1761 if (! IsNumeric($
("#gnewseq").val(), 0, 9999)) {
1762 alert("<?php xl('Order must be a number between 1 and 9999', 'e'); ?>");
1765 // length must be numeric and less than 999
1766 if (! IsNumeric($
("#gnewlengthWidth").val(), 0, 999)) {
1767 alert("<?php xl('Size must be a number between 1 and 999', 'e'); ?>");
1770 // titlecols must be numeric and less than 100
1771 if (! IsNumeric($
("#gnewtitlecols").val(), 0, 999)) {
1772 alert("<?php xl('LabelCols must be a number between 1 and 999', 'e'); ?>");
1775 // datacols must be numeric and less than 100
1776 if (! IsNumeric($
("#gnewdatacols").val(), 0, 999)) {
1777 alert("<?php xl('DataCols must be a number between 1 and 999', 'e'); ?>");
1780 // the id field can only have letters, numbers and underscores
1781 if ($
("#gnewid").val() == "") {
1782 alert("<?php xl('ID cannot be blank', 'e'); ?>");
1785 var validid
= $
("#gnewid").val().replace(/(\s|\W
)/g
, "_"); // match any non-word characters and replace them
1786 $
("#gnewid").val(validid
);
1787 // similarly with the listid field
1788 validid
= $
("#gnewlistid").val().replace(/(\s|\W
)/g
, "_");
1789 $
("#gnewlistid").val(validid
);
1790 // similarly with the backuplistid field
1791 validid
= $
("#gnewbackuplistid").val().replace(/(\s|\W
)/g
, "_");
1792 $
("#gnewbackuplistid").val(validid
);
1795 // submit the form to add a new field to a specific group
1796 $
("#formaction").val("addgroup");
1800 /******************************************************************
1801 // actually delete an entire group from the database
1802 var DeleteGroup = function(btnObj) {
1803 var parts = $(btnObj).attr("id");
1804 var groupname = parts.replace(/^\d+/, "");
1805 if (confirm("<?php xl('WARNING', 'e', '', ' - ') . xl('This action cannot be undone.', 'e', '', '\n') . xl('Are you sure you wish to delete the entire group named', 'e', '', ' '); ?>'"+groupname+"'?")) {
1806 // submit the form to add a new field to a specific group
1807 $("#formaction").val("deletegroup");
1808 $("#deletegroupname").val(parts);
1809 $("#theform").submit();
1812 ******************************************************************/
1814 // just hide the new field DIV
1815 var CancelNewGroup
= function(btnObj
) {
1816 // hide the field details DIV
1817 $
('#groupdetail').css('visibility', 'hidden');
1818 $
('#groupdetail').css('display', 'none');
1819 // reset the new group values to a default
1820 $
('#groupdetail > #newgroupname').val("");
1821 $
('#groupdetail > #newgroupparent').val("");
1822 $
("#save").attr("disabled", false);
1825 // display the 'new field' DIV
1826 var MoveGroup
= function(btnObj
) {
1827 if (!myChangeCheck()) return;
1828 var btnid
= $
(btnObj
).attr("id");
1829 var parts
= btnid
.split("~");
1830 var groupid
= parts
[0];
1831 var direction
= parts
[1];
1832 // submit the form to change group order
1833 $
("#formaction").val("movegroup");
1834 $
("#movegroupname").val(groupid
);
1835 $
("#movedirection").val(direction
);
1839 // show the rename group DIV
1840 var RenameGroup
= function(btnObj
) {
1841 if (!myChangeCheck()) return;
1842 $
("#save").attr("disabled", true);
1843 $
('#renamegroupdetail').css('visibility', 'visible');
1844 $
('#renamegroupdetail').css('display', 'block');
1845 $
(btnObj
).parent().append($
("#renamegroupdetail"));
1846 var parts
= $
(btnObj
).attr("id").split("~");
1847 $
('#renameoldgroupname').val(parts
[0]); // this is actually the existing group ID
1848 $
('#renamegroupname').val(parts
[1]); // the textual name of just this group
1849 var i
= parts
[0].length
;
1850 $
('[name=renamegroupparent]').val(i
> 0 ? parts
[0].substr(0, i
-1) : ''); // parent ID
1853 // save the new group to the form
1854 var SaveRenameGroup
= function(btnObj
) {
1855 // the group name field can only have letters, numbers, spaces and underscores
1856 // AND it cannot start with a number
1857 if ($
("#renamegroupname").val().match(/^\d+
/)) {
1858 alert("<?php xl('Group names cannot start with numbers.', 'e'); ?>");
1861 var validname
= $
("#renamegroupname").val().replace(/[^A
-za
-z0
-9 ]/g
, "_"); // match any non-word characters and replace them
1862 $
("#renamegroupname").val(validname
);
1864 // submit the form to add a new field to a specific group
1865 $
("#formaction").val("renamegroup");
1869 // just hide the new field DIV
1870 var CancelRenameGroup
= function(btnObj
) {
1871 // hide the field details DIV
1872 $
('#renamegroupdetail').css('visibility', 'hidden');
1873 $
('#renamegroupdetail').css('display', 'none');
1874 // reset the rename group values to a default
1875 $
('#renameoldgroupname').val("");
1876 $
('#renamegroupname').val("");
1877 $
('#renamegroupparent').val("");
1880 /****************************************************/
1881 /************ Field functions ***********************/
1882 /****************************************************/
1884 // display the 'new field' DIV
1885 var AddField
= function(btnObj
) {
1886 if (!myChangeCheck()) return;
1887 $
("#save").attr("disabled", true);
1888 // update the fieldgroup value to be the groupid
1889 var btnid
= $
(btnObj
).attr("id");
1890 var parts
= btnid
.split("~");
1891 var groupid
= parts
[1];
1892 $
('#fielddetail > #newfieldgroupid').attr('value', groupid
);
1893 // show the field details DIV
1894 $
('#fielddetail').css('visibility', 'visible');
1895 $
('#fielddetail').css('display', 'block');
1896 $
(btnObj
).parent().append($
("#fielddetail"));
1897 // Assign a sensible default sequence number.
1898 $
('#newseq').val(getNextSeq(groupid
));
1901 var DeleteFields
= function(btnObj
) {
1902 if (!myChangeCheck()) return;
1903 if (confirm("<?php xl('WARNING', 'e', '', ' - ') . xl('This action cannot be undone.', 'e', '', '\n') . xl('Are you sure you wish to delete the selected fields?', 'e'); ?>")) {
1905 $
(".selectfield").each(function(i
) {
1906 // build a list of selected field names to be moved
1907 if ($
(this
).prop("checked")) {
1908 var parts
= this
.id
.split("~");
1909 var currval
= $
("#selectedfields").val();
1910 $
("#selectedfields").val(currval+delim+parts
[1]);
1914 // submit the form to delete the field(s)
1915 $
("#formaction").val("deletefields");
1920 // save the new field to the form
1921 var SaveNewField
= function(btnObj
) {
1922 // check the new field values for correct formatting
1924 // seq must be numeric and <= 9999
1925 if (! IsNumeric($
("#newseq").val(), 0, 9999)) {
1926 alert("<?php xl('Order must be a number between 1 and 9999', 'e'); ?>");
1929 // length must be numeric and less than 999
1930 if (! IsNumeric($
("#newlengthWidth").val(), 0, 999)) {
1931 alert("<?php xl('Size must be a number between 1 and 999', 'e'); ?>");
1934 // titlecols must be numeric and less than 100
1935 if (! IsNumeric($
("#newtitlecols").val(), 0, 999)) {
1936 alert("<?php xl('LabelCols must be a number between 1 and 999', 'e'); ?>");
1939 // datacols must be numeric and less than 100
1940 if (! IsNumeric($
("#newdatacols").val(), 0, 999)) {
1941 alert("<?php xl('DataCols must be a number between 1 and 999', 'e'); ?>");
1944 // the id field can only have letters, numbers and underscores
1945 var validid
= $
("#newid").val().replace(/(\s|\W
)/g
, "_"); // match any non-word characters and replace them
1946 $
("#newid").val(validid
);
1947 // similarly with the listid field
1948 validid
= $
("#newlistid").val().replace(/(\s|\W
)/g
, "_");
1949 $
("#newlistid").val(validid
);
1950 // similarly with the backuplistid field
1951 validid
= $
("#newbackuplistid").val().replace(/(\s|\W
)/g
, "_");
1952 $
("#newbackuplistid").val(validid
);
1954 // submit the form to add a new field to a specific group
1955 $
("#formaction").val("addfield");
1959 // just hide the new field DIV
1960 var CancelNewField
= function(btnObj
) {
1961 // hide the field details DIV
1962 $
('#fielddetail').css('visibility', 'hidden');
1963 $
('#fielddetail').css('display', 'none');
1964 // reset the new field values to a default
1965 ResetNewFieldValues();
1966 $
("#save").attr("disabled", false);
1969 // show the popup choice of lists
1970 var ShowLists
= function(btnObj
) {
1971 window
.open('../patient_file/encounter/find_code_dynamic.php?what=lists',
1972 'lists', 'width=700,height=600,scrollbars=yes');
1973 selectedfield
= btnObj
;
1976 // show the popup choice of groups
1977 var ShowGroups
= function(btnObj
) {
1978 if (!myChangeCheck()) return;
1979 window
.open('../patient_file/encounter/find_code_dynamic.php?what=groups&layout_id=<?php echo addslashes($layout_id); ?>',
1980 'groups', 'width=700,height=600,scrollbars=yes');
1983 // Show context DD for NationNotes
1984 var ChangeList
= function(btnObj
){
1986 $
('#newlistid').hide();
1987 $
('#contextName').show();
1990 $
('#newlistid').show();
1991 $
('#contextName').hide();
1994 var ChangeListg
= function(btnObj
){
1996 $
('#gnewlistid').hide();
1997 $
('#gcontextName').show();
2000 $
('#gnewlistid').show();
2001 $
('#gcontextName').hide();
2005 // Initialize list item selectors and value field visibilities in skip conditions.
2006 var f
= document
.forms
[0];
2007 for (var lino
= 1; f
['fld[' + lino +
'][id]']; ++lino
) {
2008 for (var seq
= 0; f
['fld[' + lino +
'][condition_itemid][' + seq +
']']; ++seq
) {
2009 setListItemOptions(lino
, seq
, true);
2011 actionChanged(lino
);
2014 // Support for beforeunload handler.
2015 $
('tbody input, tbody select, tbody textarea').not('.selectfield').change(function() {
2016 somethingChanged
= true;
2018 window
.addEventListener("beforeunload", function (e
) {
2019 if (somethingChanged
&& !top
.timed_out
) {
2020 var msg
= "<?php echo xls('You have unsaved changes.'); ?>";
2021 e
.returnValue
= msg
; // Gecko, Trident, Chrome 34+
2022 return msg
; // Gecko, WebKit, Chrome <34
2026 }); /* Ready Done */
2028 function NationNotesContext(lineitem
,val
){
2030 document
.getElementById("fld["+lineitem+
"][contextName]").style
.display
='';
2031 document
.getElementById("fld["+lineitem+
"][list_id]").style
.display
='none';
2032 document
.getElementById("fld["+lineitem+
"][list_id]").value
='';
2035 document
.getElementById("fld["+lineitem+
"][list_id]").style
.display
='';
2036 document
.getElementById("fld["+lineitem+
"][contextName]").style
.display
='none';
2037 document
.getElementById("fld["+lineitem+
"][list_id]").value
='';
2041 function SetList(listid
) {
2042 $
(selectedfield
).val(listid
);
2045 //////////////////////////////////////////////////////////////////////
2046 // The following supports the field ID selection pop-up.
2047 //////////////////////////////////////////////////////////////////////
2049 var fieldselectfield
;
2051 function elemFromPart(part
) {
2052 var ename
= fieldselectfield
.name
;
2053 // ename is like one of the following:
2054 // fld[$fld_line_no][id]
2057 // and "part" is what we substitute for the "id" part.
2058 var i
= ename
.lastIndexOf('id');
2059 ename
= ename
.substr(0, i
) + part + ename
.substr(i+
2);
2060 return document
.forms
[0][ename
];
2063 function FieldIDClicked(elem
) {
2064 <?php
if (substr($layout_id, 0, 3) == 'LBF') { ?
>
2065 fieldselectfield
= elem
;
2066 var srcval
= elemFromPart('source').value
;
2067 // If the field ID is for the local form, allow direct entry.
2068 if (srcval
== 'F') return;
2069 // Otherwise pop up the selection window.
2070 window
.open('../patient_file/encounter/find_code_dynamic.php?what=fields&source='
2071 + srcval
, 'fields', 'width=700,height=600,scrollbars=yes');
2075 function SetField(field_id
, title
, data_type
, uor
, fld_length
, max_length
,
2076 list_id
, titlecols
, datacols
, edit_options
, description
, fld_rows
)
2078 fieldselectfield
.value
= field_id
;
2079 elemFromPart('title' ).value
= title
;
2080 elemFromPart('datatype' ).value
= data_type
;
2081 elemFromPart('uor' ).value
= uor
;
2082 elemFromPart('lengthWidth' ).value
= fld_length
;
2083 elemFromPart('maxSize' ).value
= max_length
;
2084 elemFromPart('list_id' ).value
= list_id
;
2085 elemFromPart('titlecols' ).value
= titlecols
;
2086 elemFromPart('datacols' ).value
= datacols
;
2087 elemFromPart('edit_options').value
= edit_options
;
2088 elemFromPart('desc' ).value
= description
;
2089 elemFromPart('lengthHeight').value
= fld_rows
;
2092 //////////////////////////////////////////////////////////////////////
2093 // End code for field ID selection pop-up.
2094 //////////////////////////////////////////////////////////////////////
2096 /* this is called after the user chooses a new group from the popup window
2097 * it will submit the page so the selected fields can be moved into
2100 function MoveFields(targetgroup
) {
2101 $
("#targetgroup").val(targetgroup
);
2103 $
(".selectfield").each(function(i
) {
2104 // build a list of selected field names to be moved
2105 if ($
(this
).prop("checked")) {
2106 var parts
= this
.id
.split("~");
2107 var currval
= $
("#selectedfields").val();
2108 $
("#selectedfields").val(currval+delim+parts
[1]);
2112 $
("#formaction").val("movefields");
2116 // set the new-field values to a default state
2117 function ResetNewFieldValues () {
2118 $
("#newseq").val("");
2119 $
("#newsource").val("");
2120 $
("#newid").val("");
2121 $
("#newtitle").val("");
2122 $
("#newuor").val(1);
2123 $
("#newlengthWidth").val("");
2124 $
("#newlengthHeight").val("");
2125 $
("#newmaxSize").val("");
2126 $
("#newdatatype").val("");
2127 $
("#newlistid").val("");
2128 $
("#newbackuplistid").val("");
2129 $
("#newtitlecols").val("");
2130 $
("#newdatacols").val("");
2131 $
("#newedit_options").val("");
2132 $
("#newdefault").val("");
2133 $
("#newdesc").val("");
2136 // is value an integer and between min and max
2137 function IsNumeric(value
, min
, max
) {
2138 if (value
== "" || value
== null) return false;
2140 parseInt(value
) < min ||
2141 parseInt(value
) > max
)
2147 /****************************************************/
2148 /****************************************************/
2149 /****************************************************/
2151 // tell if num is an Integer
2152 function IsN(num
) { return !/\D
/.test(num
); }