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 // Test options array for save
322 function encodeModifier($jsonArray)
324 return $jsonArray !== null ?
json_encode($jsonArray) : "";
327 // Check authorization.
328 $thisauth = acl_check('admin', 'super');
330 die(xl('Not authorized'));
333 // The layout ID identifies the layout to be edited.
334 $layout_id = empty($_REQUEST['layout_id']) ?
'' : $_REQUEST['layout_id'];
336 // Tag style for stuff to hide if not an LBF layout. Currently just for the Source column.
337 $lbfonly = substr($layout_id, 0, 3) == 'LBF' ?
"" : "style='display:none;'";
339 // Handle the Form actions
341 if ($_POST['formaction'] == "save" && $layout_id) {
342 // If we are saving, then save.
343 $fld = $_POST['fld'];
344 for ($lino = 1; isset($fld[$lino]['id']); ++
$lino) {
346 $field_id = formTrim($iter['id']);
347 $field_id_original = formTrim($iter['originalid']);
348 $data_type = formTrim($iter['datatype']);
349 $listval = $data_type == 34 ?
formTrim($iter['contextName']) : formTrim($iter['list_id']);
350 $action = $iter['action'];
351 if ($action == 'value') {
352 $action = 'value=' . $iter['value'];
355 // Skip conditions for the line are stored as a serialized array.
356 $condarr = array('action' => $action);
358 for (; !empty($iter['condition_id'][$cix]); ++
$cix) {
359 $andor = empty($iter['condition_andor'][$cix]) ?
'' : $iter['condition_andor'][$cix];
360 $condarr[$cix] = array(
361 'id' => strip_escape_custom($iter['condition_id' ][$cix]),
362 'itemid' => strip_escape_custom($iter['condition_itemid' ][$cix]),
363 'operator' => strip_escape_custom($iter['condition_operator'][$cix]),
364 'value' => strip_escape_custom($iter['condition_value' ][$cix]),
365 'andor' => strip_escape_custom($andor),
368 $conditions = $cix ?
serialize($condarr) : '';
371 if ($field_id != $field_id_original) {
372 if (renameColumn($layout_id, $field_id_original, $field_id) > 0) {
373 // If column rename had an error then don't rename it here.
374 $field_id = $field_id_original;
377 sqlStatement("UPDATE layout_options SET " .
378 "field_id = '" . formDataCore($field_id) . "', " .
379 "source = '" . formTrim($iter['source']) . "', " .
380 "title = '" . formDataCore($iter['title']) . "', " .
381 "group_id = '" . formTrim($iter['group']) . "', " .
382 "seq = '" . formTrim($iter['seq']) . "', " .
383 "uor = '" . formTrim($iter['uor']) . "', " .
384 "fld_length = '" . formTrim($iter['lengthWidth']) . "', " .
385 "fld_rows = '" . formTrim($iter['lengthHeight']) . "', " .
386 "max_length = '" . formTrim($iter['maxSize']) . "', " .
387 "titlecols = '" . formTrim($iter['titlecols']) . "', " .
388 "datacols = '" . formTrim($iter['datacols']) . "', " .
389 "data_type= '$data_type', " .
390 "list_id= '" . $listval . "', " .
391 "list_backup_id= '" . formTrim($iter['list_backup_id']) . "', " .
392 "edit_options = '" . encodeModifier($iter['edit_options']) . "', " .
393 "default_value = '" . formTrim($iter['default']) . "', " .
394 "description = '" . formTrim($iter['desc']) . "', " .
395 "conditions = '" . add_escape_custom($conditions) . "', " .
396 "validation = '" . formTrim($iter['validation']) . "' " .
397 "WHERE form_id = '$layout_id' AND field_id = '$field_id_original'");
400 } else if ($_POST['formaction'] == "addfield" && $layout_id) {
401 // Add a new field to a specific group
402 $data_type = formTrim($_POST['newdatatype']);
403 $max_length = $data_type == 3 ?
3 : 255;
404 $listval = $data_type == 34 ?
formTrim($_POST['contextName']) : formTrim($_POST['newlistid']);
405 sqlStatement("INSERT INTO layout_options (" .
406 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
407 ", titlecols, datacols, data_type, edit_options, default_value, description" .
408 ", max_length, list_id, list_backup_id " .
410 "'" . formTrim($_POST['layout_id']) . "'" .
411 ",'" . formTrim($_POST['newsource']) . "'" .
412 ",'" . formTrim($_POST['newid']) . "'" .
413 ",'" . formDataCore($_POST['newtitle']) . "'" .
414 ",'" . formTrim($_POST['newfieldgroupid']) . "'" .
415 ",'" . formTrim($_POST['newseq']) . "'" .
416 ",'" . formTrim($_POST['newuor']) . "'" .
417 ",'" . formTrim($_POST['newlengthWidth']) . "'" .
418 ",'" . formTrim($_POST['newlengthHeight']) . "'" .
419 ",'" . formTrim($_POST['newtitlecols']) . "'" .
420 ",'" . formTrim($_POST['newdatacols']) . "'" .
422 ",'" . encodeModifier($_POST['newedit_options']) . "'" .
423 ",'" . formTrim($_POST['newdefault']) . "'" .
424 ",'" . formTrim($_POST['newdesc']) . "'" .
425 ",'" . formTrim($_POST['newmaxSize']) . "'" .
426 ",'" . $listval . "'" .
427 ",'" . formTrim($_POST['newbackuplistid']) . "'" .
429 addOrDeleteColumn($layout_id, formTrim($_POST['newid']), true);
430 } else if ($_POST['formaction'] == "movefields" && $layout_id) {
431 // Move field(s) to a new group in the layout
432 $sqlstmt = "UPDATE layout_options SET ".
433 " group_id = '" . $_POST['targetgroup'] . "' " .
435 " form_id = '" . $_POST['layout_id'] . "' ".
436 " AND field_id IN (";
438 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
439 $sqlstmt .= $comma."'".$onefield."'";
445 sqlStatement($sqlstmt);
446 } else if ($_POST['formaction'] == "deletefields" && $layout_id) {
447 // Delete a field from a specific group
448 $sqlstmt = "DELETE FROM layout_options WHERE ".
449 " form_id = '".$_POST['layout_id']."' ".
450 " AND field_id IN (";
452 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
453 $sqlstmt .= $comma."'".$onefield."'";
458 sqlStatement($sqlstmt);
459 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
460 addOrDeleteColumn($layout_id, $onefield, false);
462 } else if ($_POST['formaction'] == "addgroup" && $layout_id) {
463 // Generate new value for layout_items.group_id.
464 $newgroupid = genGroupId($_POST['newgroupparent']);
467 "INSERT INTO layout_group_properties SET " .
468 "grp_form_id = ?, " .
469 "grp_group_id = ?, " .
471 array($layout_id, $newgroupid, $_POST['newgroupname'])
474 $data_type = formTrim($_POST['gnewdatatype']);
475 $max_length = $data_type == 3 ?
3 : 255;
476 $listval = $data_type == 34 ?
formTrim($_POST['gcontextName']) : formTrim($_POST['gnewlistid']);
477 // add a new group to the layout, with the defined field
478 sqlStatement("INSERT INTO layout_options (" .
479 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
480 ", titlecols, datacols, data_type, edit_options, default_value, description" .
481 ", max_length, list_id, list_backup_id " .
483 "'" . formTrim($_POST['layout_id']) . "'" .
484 ",'" . formTrim($_POST['gnewsource']) . "'" .
485 ",'" . formTrim($_POST['gnewid']) . "'" .
486 ",'" . formDataCore($_POST['gnewtitle']) . "'" .
487 ",'" . formTrim($newgroupid) . "'" .
488 ",'" . formTrim($_POST['gnewseq']) . "'" .
489 ",'" . formTrim($_POST['gnewuor']) . "'" .
490 ",'" . formTrim($_POST['gnewlengthWidth']) . "'" .
491 ",'" . formTrim($_POST['gnewlengthHeight']) . "'" .
492 ",'" . formTrim($_POST['gnewtitlecols']) . "'" .
493 ",'" . formTrim($_POST['gnewdatacols']) . "'" .
495 ",'" . encodeModifier($_POST['gnewedit_options']) . "'" .
496 ",'" . formTrim($_POST['gnewdefault']) . "'" .
497 ",'" . formTrim($_POST['gnewdesc']) . "'" .
498 ",'" . formTrim($_POST['gnewmaxSize']) . "'" .
499 ",'" . $listval . "'" .
500 ",'" . formTrim($_POST['gnewbackuplistid']) . "'" .
502 addOrDeleteColumn($layout_id, formTrim($_POST['gnewid']), true);
503 } /**********************************************************************
504 else if ($_POST['formaction'] == "deletegroup" && $layout_id) {
505 // drop the fields from the related table (this is critical)
506 $res = sqlStatement("SELECT field_id FROM layout_options WHERE " .
507 "form_id = '" . $_POST['layout_id'] . "' ".
508 "AND group_name = '" . $_POST['deletegroupname'] . "'");
509 while ($row = sqlFetchArray($res)) {
510 addOrDeleteColumn($layout_id, $row['field_id'], false);
513 // Delete an entire group from the form
514 sqlStatement("DELETE FROM layout_options WHERE ".
515 " form_id = '".$_POST['layout_id']."' ".
516 " AND group_name = '".$_POST['deletegroupname']."'"
519 **********************************************************************/
521 else if ($_POST['formaction'] == "movegroup" && $layout_id) {
522 // Note that in some cases below the swapGroups() call will do nothing.
524 "SELECT DISTINCT group_id " .
525 "FROM layout_options WHERE form_id = ? ORDER BY group_id",
528 $row = sqlFetchArray($res);
529 $id1 = $row['group_id'];
530 while ($row = sqlFetchArray($res)) {
531 $id2 = $row['group_id'];
532 if ($_POST['movedirection'] == 'up') { // moving up
533 if ($id2 == $_POST['movegroupname']) {
534 swapGroups($id2, $id1);
537 } else { // moving down
538 if ($id1 == $_POST['movegroupname']) {
539 swapGroups($id1, $id2);
545 } // Renaming a group. This might include moving to a different parent group.
546 else if ($_POST['formaction'] == "renamegroup" && $layout_id) {
547 $newparent = $_POST['renamegroupparent']; // this is an ID
548 $oldid = $_POST['renameoldgroupname']; // this is an ID
549 $oldparent = substr($oldid, 0, -1);
551 if ($newparent != $oldparent) {
552 // Different parent, generate a new child prefix character.
553 $newid = genGroupId($newparent);
555 "UPDATE layout_options SET group_id = ? " .
556 "WHERE form_id = ? AND group_id = ?",
557 array($newid, $layout_id, $oldid)
560 $query = "UPDATE layout_group_properties SET " .
561 "grp_group_id = ?, grp_title = ? " .
562 "WHERE grp_form_id = ? AND grp_group_id = ?";
563 sqlStatement($query, array($newid, $_POST['renamegroupname'], $layout_id, $oldid));
566 // Get the selected form's elements.
568 $res = sqlStatement("SELECT * FROM layout_options WHERE " .
569 "form_id = '$layout_id' ORDER BY group_id, seq");
572 // global counter for field numbers
577 // This is called to generate a select option list for fields within this form.
578 // Used for selecting a field for testing in a skip condition.
580 function genFieldOptionList($current = '')
583 $option_list = "<option value=''>-- " . xlt('Please Select') . " --</option>";
585 $query = "SELECT field_id FROM layout_options WHERE form_id = ? ORDER BY group_id, seq";
586 $res = sqlStatement($query, array($layout_id));
587 while ($row = sqlFetchArray($res)) {
588 $field_id = $row['field_id'];
589 $option_list .= "<option value='" . attr($field_id) . "'";
590 if ($field_id == $current) {
591 $option_list .= " selected";
593 $option_list .= ">" . text($field_id) . "</option>";
599 // Write one option line to the form.
601 function writeFieldLine($linedata)
603 global $fld_line_no, $sources, $lbfonly, $extra_html,$validations;
605 $checked = $linedata['default_value'] ?
" checked" : "";
607 //echo " <tr bgcolor='$bgcolor'>\n";
608 echo " <tr id='fld[$fld_line_no]' class='".($fld_line_no %
2 ?
'even' : 'odd')."'>\n";
610 echo " <td class='optcell' nowrap>";
611 // tuck the group_name INPUT in here
612 echo "<input type='hidden' name='fld[$fld_line_no][group]' value='" .
613 htmlspecialchars($linedata['group_id'], ENT_QUOTES
) . "' class='optin' />";
614 // Original field ID.
615 echo "<input type='hidden' name='fld[$fld_line_no][originalid]' value='" .
616 attr($linedata['field_id']) . "' />";
618 echo "<input type='checkbox' class='selectfield' ".
619 "name='" . $linedata['group_id'] . "~" . $linedata['field_id'] . "' " .
620 "id='" . $linedata['group_id'] . "~" . $linedata['field_id'] . "' " .
621 "title='" . xla('Select field') . "' />";
623 echo "<input type='text' name='fld[$fld_line_no][seq]' id='fld[$fld_line_no][seq]' value='" .
624 htmlspecialchars($linedata['seq'], ENT_QUOTES
) . "' size='2' maxlength='4' " .
625 "class='optin' style='width:32pt' />";
628 echo " <td align='center' class='optcell' $lbfonly>";
629 echo "<select class='form-control' name='fld[$fld_line_no][source]' class='optin' $lbfonly>";
630 foreach ($sources as $key => $value) {
631 echo "<option value='" . attr($key) . "'";
632 if ($key == $linedata['source']) {
636 echo ">" . text($value) . "</option>\n";
642 echo " <td align='left' class='optcell'>";
643 echo "<input type='text' name='fld[$fld_line_no][id]' value='" .
644 htmlspecialchars($linedata['field_id'], ENT_QUOTES
) . "' size='15' maxlength='63' " .
645 "class='optin' style='width:100%' onclick='FieldIDClicked(this)' />";
648 echo " <td align='center' class='optcell'>";
649 echo "<input type='text' id='fld[$fld_line_no][title]' name='fld[$fld_line_no][title]' value='" .
650 htmlspecialchars($linedata['title'], ENT_QUOTES
) . "' size='15' maxlength='63' class='optin' style='width:100%' />";
653 // if not english and set to translate layout labels, then show the translation
654 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
655 echo "<td align='center' class='translation' >" . htmlspecialchars(xl($linedata['title']), ENT_QUOTES
) . "</td>\n";
658 echo " <td align='center' class='optcell'>";
659 echo "<select class='form-control' name='fld[$fld_line_no][uor]' class='optin'>";
660 foreach (array(0 =>xl('Unused'), 1 =>xl('Optional'), 2 =>xl('Required')) as $key => $value) {
661 echo "<option value='$key'";
662 if ($key == $linedata['uor']) {
666 echo ">$value</option>\n";
672 echo " <td align='center' class='optcell'>";
673 echo "<select class='form-control' name='fld[$fld_line_no][datatype]' id='fld[$fld_line_no][datatype]' onchange=NationNotesContext('".$fld_line_no."',this.value)>";
674 echo "<option value=''></option>";
676 foreach ($datatypes as $key => $value) {
677 if ($linedata['data_type'] == $key) {
678 echo "<option value='$key' selected>$value</option>";
680 echo "<option value='$key'>$value</option>";
687 echo " <td align='center' class='optcell'>";
688 if ($linedata['data_type'] == 2 ||
$linedata['data_type'] == 3 ||
689 $linedata['data_type'] == 21 ||
$linedata['data_type'] == 22 ||
690 $linedata['data_type'] == 23 ||
$linedata['data_type'] == 25 ||
691 $linedata['data_type'] == 27 ||
$linedata['data_type'] == 28 ||
692 $linedata['data_type'] == 32 ||
$linedata['data_type'] == 15 ||
693 $linedata['data_type'] == 40
695 // Show the width field
696 echo "<input type='text' name='fld[$fld_line_no][lengthWidth]' value='" .
697 htmlspecialchars($linedata['fld_length'], ENT_QUOTES
) .
698 "' size='2' maxlength='10' class='optin' title='" . xla('Width') . "' />";
699 if ($linedata['data_type'] == 3 ||
$linedata['data_type'] == 40) {
700 // Show the height field
701 echo "<input type='text' name='fld[$fld_line_no][lengthHeight]' value='" .
702 htmlspecialchars($linedata['fld_rows'], ENT_QUOTES
) .
703 "' size='2' maxlength='10' class='optin' title='" . xla('Height') . "' />";
705 // Hide the height field
706 echo "<input type='hidden' name='fld[$fld_line_no][lengthHeight]' value=''>";
709 // all other data_types (hide both the width and height fields
710 echo "<input type='hidden' name='fld[$fld_line_no][lengthWidth]' value=''>";
711 echo "<input type='hidden' name='fld[$fld_line_no][lengthHeight]' value=''>";
716 echo " <td align='center' class='optcell'>";
717 echo "<input type='text' name='fld[$fld_line_no][maxSize]' value='" .
718 htmlspecialchars($linedata['max_length'], ENT_QUOTES
) .
719 "' size='1' maxlength='10' class='optin' style='width:100%' " .
720 "title='" . xla('Maximum Size (entering 0 will allow any size)') . "' />";
723 echo " <td align='center' class='optcell'>";
724 if ($linedata['data_type'] == 1 ||
$linedata['data_type'] == 21 ||
725 $linedata['data_type'] == 22 ||
$linedata['data_type'] == 23 ||
726 $linedata['data_type'] == 25 ||
$linedata['data_type'] == 26 ||
727 $linedata['data_type'] == 27 ||
$linedata['data_type'] == 32 ||
728 $linedata['data_type'] == 33 ||
$linedata['data_type'] == 34 ||
729 $linedata['data_type'] == 36) {
731 $disp = "style='display:none'";
732 if ($linedata['data_type'] == 34) {
733 $type = "style='display:none'";
737 echo "<input type='text' name='fld[$fld_line_no][list_id]' id='fld[$fld_line_no][list_id]' value='" .
738 htmlspecialchars($linedata['list_id'], ENT_QUOTES
) . "'".$type.
739 " size='6' maxlength='100' class='optin listid' style='width:100%;cursor:pointer'".
740 "title='". xl('Choose list') . "' />";
742 echo "<select class='form-control' name='fld[$fld_line_no][contextName]' id='fld[$fld_line_no][contextName]' ".$disp.">";
743 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
744 while ($row = sqlFetchArray($res)) {
746 if ($linedata['list_id'] == $row['cl_list_item_long']) {
750 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."' ".$sel.">".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
755 // all other data_types
756 echo "<input type='hidden' name='fld[$fld_line_no][list_id]' value=''>";
762 echo " <td align='center' class='optcell'>";
763 if ($linedata['data_type'] == 1 ||
$linedata['data_type'] == 26 ||
764 $linedata['data_type'] == 33 ||
$linedata['data_type'] == 36) {
765 echo "<input type='text' name='fld[$fld_line_no][list_backup_id]' value='" .
766 htmlspecialchars($linedata['list_backup_id'], ENT_QUOTES
) .
767 "' size='3' maxlength='100' class='optin listid' style='cursor:pointer; width:100%' />";
769 echo "<input type='hidden' name='fld[$fld_line_no][list_backup_id]' value=''>";
775 echo " <td align='center' class='optcell'>";
776 echo "<input type='text' name='fld[$fld_line_no][titlecols]' value='" .
777 htmlspecialchars($linedata['titlecols'], ENT_QUOTES
) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
780 echo " <td align='center' class='optcell'>";
781 echo "<input type='text' name='fld[$fld_line_no][datacols]' value='" .
782 htmlspecialchars($linedata['datacols'], ENT_QUOTES
) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
784 /* Below for compatabilty with existing string modifiers. */
785 if (strpos($linedata['edit_options'], ',') === false && isset($linedata['edit_options'])) {
786 $t = json_decode($linedata['edit_options']);
787 if (json_last_error() !== JSON_ERROR_NONE ||
$t === 0) { // hopefully string of characters and 0 handled.
788 $t = str_split(trim($linedata['edit_options']));
789 $linedata['edit_options'] = json_encode($t); // convert to array select understands.
792 echo " <td align='center' class='optcell' title='" . xla("Add modifiers for this field type. You may select more than one.") . "'>";
793 echo "<select id='fld[$fld_line_no][edit_options]' name='fld[$fld_line_no][edit_options][]' class='typeAddons optin' size=3 multiple data-set='" .
794 trim($linedata['edit_options']) . "' ></select></td>\n";
796 if ($linedata['data_type'] == 31) {
797 echo " <td align='center' class='optcell'>";
798 echo "<textarea name='fld[$fld_line_no][desc]' rows='3' cols='35' class='optin' style='width:100%'>" .
799 $linedata['description'] . "</textarea>";
800 echo "<input type='hidden' name='fld[$fld_line_no][default]' value='" .
801 htmlspecialchars($linedata['default_value'], ENT_QUOTES
) . "' />";
804 echo " <td align='center' class='optcell' >";
805 echo "<input type='text' name='fld[$fld_line_no][desc]' value='" .
806 htmlspecialchars($linedata['description'], ENT_QUOTES
) .
807 "' size='30' class='optin' style='width:100%' />";
808 echo "<input type='hidden' name='fld[$fld_line_no][default]' value='" .
809 htmlspecialchars($linedata['default_value'], ENT_QUOTES
) . "' />";
811 // if not english and showing layout labels, then show the translation of Description
812 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
813 echo "<td align='center' class='translation'>" .
814 htmlspecialchars(xl($linedata['description']), ENT_QUOTES
) . "</td>\n";
818 // The "?" to click on for yet more field attributes.
819 echo " <td class='bold' id='querytd_$fld_line_no' style='cursor:pointer;";
820 if (!empty($linedata['conditions']) ||
!empty($linedata['validation'])) {
821 echo "background-color:#77ff77;";
824 echo "' onclick='extShow($fld_line_no, this)' align='center' ";
825 echo "title='" . xla('Click here to view/edit more details') . "'>";
826 echo " ? ";
831 // Create a floating div for the additional attributes of this field.
832 $conditions = empty($linedata['conditions']) ?
833 array(0 => array('id' => '', 'itemid' => '', 'operator' => '', 'value' => '')) :
834 unserialize($linedata['conditions']);
835 $action = empty($conditions['action']) ?
'skip' : $conditions['action'];
836 $action_value = $action == 'skip' ?
'' : substr($action, 6);
838 $extra_html .= "<div id='ext_$fld_line_no' " .
839 "style='position:absolute;width:750px;border:1px solid black;" .
840 "padding:2px;background-color:#cccccc;visibility:hidden;" .
841 "z-index:1000;left:-1000px;top:0px;font-size:8pt;'>\n" .
842 "<table width='100%'>\n" .
844 " <th colspan='3' align='left' class='bold'>" .
845 xlt('For') . " " . text($linedata['field_id']) . " " .
846 "<select name='fld[$fld_line_no][action]' onchange='actionChanged($fld_line_no)'>" .
847 "<option value='skip' " . ($action == 'skip' ?
'selected' : '') . ">" . xlt('hide this field') . "</option>" .
848 "<option value='value' " . ($action != 'skip' ?
'selected' : '') . ">" . xlt('set value to') . "</option>" .
850 "<input type='text' name='fld[$fld_line_no][value]' value='" . attr($action_value) . "' size='15' />" .
853 " <th colspan='2' align='right' class='text'><input type='button' " .
854 "value='" . xla('Close') . "' onclick='extShow($fld_line_no, false)' /> </th>\n" .
857 " <th align='left' class='bold'>" . xlt('Field ID') . "</th>\n" .
858 " <th align='left' class='bold'>" . xlt('List item ID') . "</th>\n" .
859 " <th align='left' class='bold'>" . xlt('Operator') . "</th>\n" .
860 " <th align='left' class='bold'>" . xlt('Value if comparing') . "</th>\n" .
861 " <th align='left' class='bold'> </th>\n" .
863 // There may be multiple condition lines for each field.
864 foreach ($conditions as $i => $condition) {
865 if (!is_numeric($i)) {
866 continue; // skip if 'action'
870 " <td align='left'>\n" .
871 " <select name='fld[$fld_line_no][condition_id][$i]' onchange='cidChanged($fld_line_no, $i)'>" .
872 genFieldOptionList($condition['id']) . " </select>\n" .
874 " <td align='left'>\n" .
875 // List item choices are populated on the client side but will need the current value,
876 // so we insert a temporary option here to hold that value.
877 " <select name='fld[$fld_line_no][condition_itemid][$i]'><option value='" .
878 attr($condition['itemid']) . "'>...</option></select>\n" .
880 " <td align='left'>\n" .
881 " <select name='fld[$fld_line_no][condition_operator][$i]'>\n";
883 'eq' => xl('Equals'),
884 'ne' => xl('Does not equal'),
885 'se' => xl('Is selected'),
886 'ns' => xl('Is not selected'),
887 ) as $key => $value) {
888 $extra_html .= " <option value='$key'";
889 if ($key == $condition['operator']) {
890 $extra_html .= " selected";
893 $extra_html .= ">" . text($value) . "</option>\n";
899 " <td align='left' title='" . xla('Only for comparisons') . "'>\n" .
900 " <input type='text' name='fld[$fld_line_no][condition_value][$i]' value='" .
901 attr($condition['value']) . "' size='15' maxlength='63' />\n" .
903 if (!isset($conditions[$i +
1])) {
905 " <td align='right' title='" . xla('Add a condition') . "'>\n" .
906 " <input type='button' value='+' onclick='extAddCondition($fld_line_no,this)' />\n" .
910 " <td align='right'>\n" .
911 " <select name='fld[$fld_line_no][condition_andor][$i]'>\n";
915 ) as $key => $value) {
916 $extra_html .= " <option value='$key'";
917 if ($key == $condition['andor']) {
918 $extra_html .= " selected";
921 $extra_html .= ">" . text($value) . "</option>\n";
936 $extra_html .= "<table width='100%'>\n" .
938 " <td colspan='3' align='left' class='bold'>\"" . text($linedata['field_id']) . "\" " .
939 xlt('will have the following validation rules') . ":</td>\n" .
942 " <td align='left' class='bold'>" . xlt('Validation rule') . " </td>\n" .
945 " <td align='left' title='" . xla('Select a validation rule') . "'>\n" .
948 " <select name='fld[$fld_line_no][validation]' onchange='valChanged($fld_line_no)'>\n" .
950 if (empty($linedata['validation'])) {
951 $extra_html .= " selected";
954 $extra_html .= ">-- " . xlt('Please Select') . " --</option>";
955 foreach ($validations as $key => $value) {
956 $extra_html .= " <option value='$key'";
957 if ($key == $linedata['validation']) {
958 $extra_html .= " selected";
961 $extra_html .= ">" . text($value) . "</option>\n";
964 $extra_html .="</select>\n" .
976 <?php Header
::setupHeader(['select2']); ?
>
978 <title
><?php
xl('Layout Editor', 'e'); ?
></title
>
981 .orgTable tr
.head
{ font
-size
:8pt
; background
-color
:#cccccc; }
982 .orgTable tr
.detail
{ font
-size
:8pt
; }
983 .orgTable td
{ font
-size
:8pt
; }
984 .orgTable input
{ font
-size
:8pt
; }
985 .orgTable select
{ font
-size
:8pt
; }
986 a
, a
:visited
, a
:hover
{ color
:#0000cc; }
988 .optin
{ background
: transparent
; }
990 margin
: 0pt
0pt
8pt
0pt
;
996 border
-collapse
: collapse
;
1001 background
-color
: #ddddff;
1002 padding
: 3px
0px
3px
0px
;
1004 .orgTable
.even td
{
1005 background
-color
: #ffdddd;
1006 padding
: 3px
0px
3px
0px
;
1008 .help
{ cursor
: help
; }
1009 .layouts_title
{ font
-size
: 110%
; }
1015 border
: 2px solid blue
;
1016 background
-color
: yellow
;
1019 .select2
-container
--default .select2
-selection
--multiple
{
1022 .select2
-search__field
{
1024 width
: 0 !important
;
1026 .select2
-selection__choice
{
1029 .select2
-container
{
1031 opacity
: 0.99 !important
;
1034 opacity
: 0.99 !important
;
1043 // Helper functions for positioning the floating divs.
1044 function extGetX(elem
) {
1046 while(elem
!= null) {
1047 x +
= elem
.offsetLeft
;
1048 elem
= elem
.offsetParent
;
1052 function extGetY(elem
) {
1054 while(elem
!= null) {
1055 y +
= elem
.offsetTop
;
1056 elem
= elem
.offsetParent
;
1061 // Show or hide the "extras" div for a row.
1063 function extShow(lino
, show
) {
1064 var thisdiv
= document
.getElementById("ext_" + lino
);
1066 extdiv
.style
.visibility
= 'hidden';
1067 extdiv
.style
.left
= '-1000px';
1068 extdiv
.style
.top
= '0px';
1070 if (show
&& thisdiv
!= extdiv
) {
1072 var dw
= window
.innerWidth ? window
.innerWidth
- 20 : document
.body
.clientWidth
;
1073 x
= dw
- extdiv
.offsetWidth
;
1075 var y
= extGetY(show
) + show
.offsetHeight
;
1076 extdiv
.style
.left
= x
;
1077 extdiv
.style
.top
= y
;
1078 extdiv
.style
.visibility
= 'visible';
1085 // Show or hide the value field for a "Set value to" condition.
1086 function actionChanged(lino
) {
1087 var f
= document
.forms
[0];
1088 var eaction
= f
['fld[' + lino +
'][action]'];
1089 var evalue
= f
['fld[' + lino +
'][value]'];
1090 evalue
.style
.display
= eaction
.value
== 'skip' ?
'none' : '';
1093 // Add an extra condition line for the given row.
1094 function extAddCondition(lino
, btnelem
) {
1095 var f
= document
.forms
[0];
1098 // Get index of next condition line.
1099 while (f
['fld[' + lino +
'][condition_id][' + i +
']']) ++i
;
1100 if (i
== 0) alert('f["fld[' + lino +
'][condition_id][' + i +
']"] <?php echo xls('not found
') ?>');
1102 // Get containing <td>, <tr> and <table> nodes of the "+" button.
1103 var tdplus
= btnelem
.parentNode
;
1104 var trelem
= tdplus
.parentNode
;
1105 var telem
= trelem
.parentNode
;
1107 // Replace contents of the tdplus cell.
1109 "<select name='fld[" + lino +
"][condition_andor][" + i +
"]'>" +
1110 "<option value='and'><?php echo xls('And') ?></option>" +
1111 "<option value='or' ><?php echo xls('Or') ?></option>" +
1115 var newtrelem
= telem
.insertRow(i+
2);
1116 newtrelem
.innerHTML
=
1117 "<td align='left'>" +
1118 "<select name='fld[" + lino +
"][condition_id][" + i +
"]' onchange='cidChanged(" + lino +
"," + i +
")'>" +
1119 "<?php echo addslashes(genFieldOptionList()) ?>" +
1122 "<td align='left'>" +
1123 "<select name='fld[" + lino +
"][condition_itemid][" + i +
"]' style='display:none' />" +
1125 "<td align='left'>" +
1126 "<select name='fld[" + lino +
"][condition_operator][" + i +
"]'>" +
1127 "<option value='eq'><?php echo xls('Equals') ?></option>" +
1128 "<option value='ne'><?php echo xls('Does not equal') ?></option>" +
1129 "<option value='se'><?php echo xls('Is selected') ?></option>" +
1130 "<option value='ns'><?php echo xls('Is not selected') ?></option>" +
1133 "<td align='left'>" +
1134 "<input type='text' name='fld[" + lino +
"][condition_value][" + i +
"]' value='' size='15' maxlength='63' />" +
1136 "<td align='right'>" +
1137 "<input type='button' value='+' onclick='extAddCondition(" + lino +
",this)' />" +
1141 // This is called when a field ID is chosen for testing within a skip condition.
1142 // It checks to see if a corresponding list item must also be chosen for the test, and
1143 // if so then inserts the dropdown for selecting an item from the appropriate list.
1144 function setListItemOptions(lino
, seq
, init
) {
1145 var f
= document
.forms
[0];
1146 var target
= 'fld[' + lino +
'][condition_itemid][' + seq +
']';
1147 // field_id is the ID of the field that the condition will test.
1148 var field_id
= f
['fld[' + lino +
'][condition_id][' + seq +
']'].value
;
1150 f
[target
].options
.length
= 0;
1151 f
[target
].style
.display
= 'none';
1154 // Find the occurrence of that field in the layout.
1157 var idname
= 'fld[' + i +
'][id]';
1159 alert('<?php echo xls('Condition field not found
') ?>: ' + field_id
);
1162 if (f
[idname
].value
== field_id
) break;
1165 // If this is startup initialization then preserve the current value.
1166 var current
= init ? f
[target
].value
: '';
1167 f
[target
].options
.length
= 0;
1168 // Get the corresponding data type and list ID.
1169 var data_type
= f
['fld[' + i +
'][datatype]'].value
;
1170 var list_id
= f
['fld[' + i +
'][list_id]'].value
;
1171 // WARNING: If new data types are defined the following test may need enhancing.
1172 // We're getting out if the type does not generate multiple fields with different names.
1173 if (data_type
!= '21' && data_type
!= '22' && data_type
!= '23' && data_type
!= '25') {
1174 f
[target
].style
.display
= 'none';
1177 // OK, list item IDs do apply so go get 'em.
1178 // This happens asynchronously so the generated code needs to stand alone.
1179 f
[target
].style
.display
= '';
1180 $
.getScript('layout_listitems_ajax.php' +
1181 '?listid=' +
encodeURIComponent(list_id
) +
1182 '&target=' +
encodeURIComponent(target
) +
1183 '¤t=' +
encodeURIComponent(current
) +
1184 '&csrf_token_form=' +
encodeURIComponent(<?php
echo attr($_SESSION['csrf_token']); ?
>));
1187 // This is called whenever a condition's field ID selection is changed.
1188 function cidChanged(lino
, seq
) {
1190 setListItemOptions(lino
, seq
, false);
1193 // This invokes the popup to edit layout properties or add a new layout.
1194 function edit_layout_props(groupid
) {
1195 var title
= "<?php echo xlt('Layout Properties');?>";
1196 dlgopen('edit_layout_props.php?layout_id=<?php echo attr($layout_id); ?>&group_id=' + groupid
,
1197 '_blank', 775, 550, "", title
);
1200 // callback from edit_layout_props.php:
1201 function refreshme(layout_id
) {
1202 location
.href
= 'edit_layout.php?layout_id=' + layout_id
;
1205 // This is called whenever a validation rule field ID selection is changed.
1206 function valChanged(lino
) {
1210 function changeColor(lino
){
1211 var thisid
= document
.forms
[0]['fld[' + lino +
'][condition_id][0]'].value
;
1212 var thisValId
= document
.forms
[0]['fld[' + lino +
'][validation]'].value
;
1213 var thistd
= document
.getElementById("querytd_" + lino
);
1214 if(thisid
!='' || thisValId
!='') {
1215 thistd
.style
.backgroundColor
= '#77ff77';
1217 thistd
.style
.backgroundColor
='';
1221 // Call this to disable the warning about unsaved changes and submit the form.
1222 function mySubmit() {
1223 somethingChanged
= false;
1224 top
.restoreSession();
1225 document
.forms
[0].submit();
1228 // User is about to do something that would discard any unsaved changes.
1229 // Return true if that is OK.
1230 function myChangeCheck() {
1231 if (somethingChanged
) {
1232 if (!confirm('<?php echo xls('You have unsaved changes
. Abandon them?
'); ?>')) {
1235 // Do not set somethingChanged to false here because if they cancel the
1236 // action then the previously changed values will still be of interest.
1245 <body
class="body_top admin-layout">
1246 <div
class="container-responsive">
1247 <form method
='post' name
='theform' id
='theform' action
='edit_layout.php'>
1248 <input type
="hidden" name
="formaction" id
="formaction" value
="">
1249 <!-- elements used to identify a field to delete
-->
1250 <input type
="hidden" name
="deletefieldid" id
="deletefieldid" value
="">
1251 <input type
="hidden" name
="deletefieldgroup" id
="deletefieldgroup" value
="">
1252 <!-- elements used to identify a group to delete
-->
1254 <input type
="hidden" name
="deletegroupname" id
="deletegroupname" value
="">
1256 <!-- elements used to change the group order
-->
1257 <input type
="hidden" name
="movegroupname" id
="movegroupname" value
="">
1258 <input type
="hidden" name
="movedirection" id
="movedirection" value
="">
1259 <!-- elements used to select more than one field
-->
1260 <input type
="hidden" name
="selectedfields" id
="selectedfields" value
="">
1261 <input type
="hidden" id
="targetgroup" name
="targetgroup" value
="">
1263 <div
class="menubar" style
='padding:5px 0;'>
1265 <b
><?php
xl('Edit layout', 'e'); ?
>:</b
> 
;
1266 <select name
='layout_id' id
='layout_id' class='form-control' style
='display:inline-block;margin-bottom:5px;width:20%;'>
1267 <option value
=''>-- <?php
echo xl('Select') ?
> --</option
>
1270 foreach ($layouts as $key => $value) {
1271 if ($value[0] != $lastgroup) {
1273 echo " </optgroup>\n";
1275 echo " <optgroup label='" . attr($value[0]) . "'>\n";
1276 $lastgroup = $value[0];
1278 echo " <option value='" . attr($key) . "'";
1279 if ($key == $layout_id) {
1282 echo ">" . text($value[1]) . "</option>\n";
1285 echo " </optgroup>\n";
1290 <?php
if ($layout_id) { ?
>
1291 <input type
='button' value
='<?php echo xla('Layout Properties
'); ?>' onclick
='edit_layout_props("")' /> 
;
1292 <input type
='button' class='addgroup' id
='addgroup' value
='<?php echo xla('Add Group
'); ?>' />
1293 <span style
="font-size:90%">  
;
1294 <input type
='button' class="btn btn-danger" name
='save' id
='save' value
='<?php xl('Save Changes
', 'e
'); ?>' /></span
>  
; 
;
1295 <?php
xl('With selected:', 'e');?
>
1296 <input type
='button' name
='deletefields' id
='deletefields' value
='<?php xl('Delete
', 'e
'); ?>' style
="font-size:90%" disabled
="disabled" />
1297 <input type
='button' name
='movefields' id
='movefields' value
='<?php xl('Move to
...', 'e
'); ?>' style
="font-size:90%" disabled
="disabled" />
1298 <input type
='button' value
='<?php echo xla('Tips
'); ?>' onclick
='$("#tips").toggle();' /> 
;
1299 <input type
='button' value
='<?php echo xla('Encounter Preview
'); ?>' onclick
='layoutLook();' />
1302 <input type
='button' value
='<?php echo xla('New Layout
'); ?>' onclick
='edit_layout_props("")' /> 
;
1305 <div id
="tips" class="container tips"><section
class="panel panel-primary">
1306 <header
class="panel-heading">
1307 <h3
class="panel-title"><?php
echo xlt('Usage Tips') ?
></h3
>
1309 <div
class="panel-body">
1312 echo "<li>" . xlt("Clicking Options will present a multiselection drop menu to add behaviors to the selected data type. Typing after pull down activates allows search in options.") . "</li>";
1313 echo "<li>" . xlt("The option Span Entire Row is useful when using Static Text in allowing text to wrap and span entire row regardless of column settings. Another use could be to create an empty row as spacer or add additional option Add Bottom Border to create a line break.Only Bottom Border Row is useful here.") . "</li>";
1314 echo "<li>" . xlt("The options for Outline and Border will either wrap a row in thin border or add a border to the bottom of an item.") . "</li>";
1315 echo "<li>" . xlt("If a field's Label Col = 0 the label will immediately follow the previous data field in the Order sequence, on the same line as the Data field.") . "</li>";
1316 echo "<li>" . xlt("If a field's Data Col = 0 the data field will immediately follow its label field on the same line") . "</li>";
1317 echo "<li>" . xlt("If a field's Label Col = 1 the label field will go to a new line unless the previous field's total column values (Label + Data) is less than number of Layout columns from Group Properties or Layout Properties.") . "</li>";
1318 echo "<li>" . xlt("Generally, the first field in a group should be Label Cols = 1 Data Cols = number of Layout columns from Group Properties.") . "</li>";
1319 echo "<li>" . xlt("Make subsequent fields in the same row, Label = 0 Data = 0 and ensure enough columns are available from previous items to allow space for this new item. Otherwise result could be unpredictable") . "</li>";
1320 echo "<li>" . xlt("The Encounter Preview button is useful for showing encounter type layout forms as seen when using form in an encounter. Note, this feature is only useful for showing encounter forms and won't display system forms like Demographics") . "</li>";
1321 //echo "<li>" . xlt("") . "</li>";
1322 echo "<li>" . xlt("Please see http://www.open-emr.org/wiki/index.php/LBV_Forms for more on this topic") . "</li>";
1325 <button
class='btn btn-xs btn-success pull-right' onclick
='$("#tips").toggle();return false;'><?php
echo xlt('Dismiss')?
></button
>
1327 </section
></div
></div
>
1329 // Load array of properties for this layout and its groups.
1331 $gres = sqlStatement("SELECT * FROM layout_group_properties WHERE grp_form_id = ? " .
1332 "ORDER BY grp_group_id", array($layout_id));
1333 while ($grow = sqlFetchArray($gres)) {
1334 $grparr[$grow['grp_group_id']] = $grow;
1337 $prevgroup = "!@#asdf1234"; // an unlikely group ID
1338 $firstgroup = true; // flag indicates it's the first group to be displayed
1340 while ($row = sqlFetchArray($res)) {
1341 $group_id = $row['group_id'];
1342 if ($group_id != $prevgroup) {
1343 if ($firstgroup == false) {
1344 echo "</tbody></table></div>\n";
1345 echo "<div id='" . $group_id . "' class='group'>";
1346 } else { // making first group flag useful for maintaining top fixed nav bar.
1347 echo "<div id='" . $group_id . "' class='group' style='padding-top:40px'>";
1349 echo "<div class='text bold layouts_title' style='position:relative; background-color: #c9dbf2;'>";
1351 // Get the fully qualified descriptive name of this group (i.e. including ancestor names).
1353 for ($i = 1; $i <= strlen($group_id); ++
$i) {
1355 $gdispname .= ' / ';
1357 $gdispname .= $grparr[substr($group_id, 0, $i)]['grp_title'];
1359 $gmyname = $grparr[$group_id]['grp_title'];
1361 echo text($gdispname);
1363 // if not english and set to translate layout labels, then show the translation of group name
1364 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1365 echo "<span class='translation'>>> " . xlt($gdispname) . "</span>";
1370 echo " <input type='button' class='addfield' id='addto~$group_id' value='" . xla('Add Field') . "'/>";
1371 echo " ";
1372 echo " <input type='button' class='renamegroup' id='$group_id~$gmyname' value='" . xla('Rename Group') . "'/>";
1373 /******************************************************************
1374 echo " ";
1375 echo " <input type='button' class='deletegroup' id='$group_id' value='" . xl('Delete Group') . "'/>";
1376 ******************************************************************/
1377 echo " ";
1378 echo " <input type='button' class='movegroup' id='$group_id~up' value='" . xl('Move Up') . "'/>";
1379 echo " ";
1380 echo " <input type='button' class='movegroup' id='$group_id~down' value='" . xl('Move Down') . "'/>";
1381 echo " ";
1382 echo "<input type='button' value='" . xla('Group Properties') . "' onclick='edit_layout_props(\"$group_id\")' />";
1384 $firstgroup = false;
1386 <table
class='table table-condensed table-striped'>
1389 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1390 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1391 <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
>
1392 <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
>
1393 <?php
// if not english and showing layout label translations, then show translation header for title
1394 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1395 echo "<th>" . xl('Translation')."<span class='help' title='" . xl('The translated label that will appear on the form in current language') . "'> (?)</span></th>";
1397 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1398 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1399 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1400 <th style
='width:3%'><?php
xl('Max Size', 'e'); ?
></th
>
1401 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1402 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1403 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1404 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1405 <th style
='width:10%'><?php
xl('Options', 'e'); ?
></th
>
1406 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1407 <?php
// if not english and showing layout label translations, then show translation header for description
1408 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1409 echo "<th>" . xl('Translation')."<span class='help' title='" . xl('The translation of description in current language')."'> (?)</span></th>";
1411 <th style
='width:1%'><?php
echo xlt('?'); ?
></th
>
1417 } // end if-group_name
1419 writeFieldLine($row);
1420 $prevgroup = $group_id;
1427 <?php
echo $extra_html; ?
>
1431 <!-- template DIV that appears when user chooses to rename an existing group
-->
1432 <div id
="renamegroupdetail"
1433 style
="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1434 <input type
="hidden" name
="renameoldgroupname" id
="renameoldgroupname" value
="" />
1435 <?php
echo xlt('Group Name'); ?
>:
1436 <input type
="text" size
="20" maxlength
="30" name
="renamegroupname" id
="renamegroupname" />
1438 <?php
echo xlt('Parent'); ?
>:
1439 <?php
echo genGroupSelector('renamegroupparent', $layout_id); ?
>
1441 <input type
="button" class="saverenamegroup .btn-save" value
="<?php echo xla('Rename Group'); ?>" />
1442 <input type
="button" class="cancelrenamegroup" value
="<?php echo xla('Cancel'); ?>" />
1445 <!-- template DIV that appears when user chooses to add a
new group
-->
1446 <div id
="groupdetail"
1447 style
="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1449 <?php
echo xlt('Group Name'); ?
>:
1450 <input type
="text" size
="20" maxlength
="30" name
="newgroupname" id
="newgroupname" />
1452 <?php
echo xlt('Parent'); ?
>:
1453 <?php
echo genGroupSelector('newgroupparent', $layout_id); ?
>
1455 <table
class='table table-condensed table-striped' style
="border-collapse: collapse; margin-top: 5px;">
1458 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1459 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1460 <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
>
1461 <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
>
1462 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1463 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1464 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1465 <th style
='width:1%'><?php
xl('Max Size', 'e'); ?
></th
>
1466 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1467 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1468 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1469 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1470 <th style
='width:10%'><?php
xl('Options', 'e'); ?
></th
>
1471 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1476 <td
><input type
="text" name
="gnewseq" id
="gnewseq" value
="" size
="2" maxlength
="4"> </td
>
1477 <td
<?php
echo " $lbfonly"; ?
>>
1478 <select
class='form-control' name
='gnewsource' id
='gnewsource'>
1480 foreach ($sources as $key => $value) {
1481 echo "<option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1486 <td
><input type
="text" name
="gnewid" id
="gnewid" value
="" size
="10" maxlength
="20"
1487 onclick
='FieldIDClicked(this)'> </td
>
1488 <td
><input type
="text" name
="gnewtitle" id
="gnewtitle" value
="" size
="20" maxlength
="63"> </td
>
1490 <select
class='form-control' name
="gnewuor" id
="gnewuor">
1491 <option value
="0"><?php
xl('Unused', 'e'); ?
></option
>
1492 <option value
="1" selected
><?php
xl('Optional', 'e'); ?
></option
>
1493 <option value
="2"><?php
xl('Required', 'e'); ?
></option
>
1497 <select
class='form-control' name
='gnewdatatype' id
='gnewdatatype'>
1498 <option value
=''></option
>
1501 foreach ($datatypes as $key => $value) {
1502 echo "<option value='$key'>$value</option>";
1507 <td
><input type
="text" name
="gnewlengthWidth" id
="gnewlengthWidth" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Width'); ?>">
1508 <input type
="text" name
="gnewlengthHeight" id
="gnewlengthHeight" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Height'); ?>"></td
>
1509 <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
>
1510 <td
><input type
="text" name
="gnewlistid" id
="gnewlistid" value
="" size
="8" maxlength
="100" class="listid">
1511 <select
class='form-control' name
='gcontextName' id
='gcontextName' style
='display:none'>
1513 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1514 while ($row = sqlFetchArray($res)) {
1515 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."'>".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
1520 <td
><input type
="text" name
="gnewbackuplistid" id
="gnewbackuplistid" value
="" size
="8" maxlength
="100" class="listid"></td
>
1521 <td
><input type
="text" name
="gnewtitlecols" id
="gnewtitlecols" value
="" size
="3" maxlength
="3"> </td
>
1522 <td
><input type
="text" name
="gnewdatacols" id
="gnewdatacols" value
="" size
="3" maxlength
="3"> </td
>
1523 <td
><select name
="gnewedit_options[]" id
="gnewedit_options" class="typeAddons" multiple style
='width:100%' value
="" size
="3"></select
>
1524 <input type
="hidden" name
="gnewdefault" id
="gnewdefault" value
="" /> </td
>
1525 <td
><input type
="text" name
="gnewdesc" id
="gnewdesc" value
="" size
="30"> </td
>
1530 <input type
="button" class="savenewgroup" value
=<?php
xl('Save New Group', 'e', '\'', '\''); ?
>>
1531 <input type
="button" class="cancelnewgroup" value
=<?php
xl('Cancel', 'e', '\'', '\''); ?
>>
1535 <!-- template DIV that appears when user chooses to add a
new field to a group
-->
1536 <div id
="fielddetail" class="fielddetail" style
="display: none; visibility: hidden">
1537 <input type
="hidden" name
="newfieldgroupid" id
="newfieldgroupid" value
="">
1538 <table
class="table table-condensed" style
="border-collapse: collapse;">
1541 <th style
='width:1%'><?php
xl('Order', 'e'); ?
></th
>
1542 <th
<?php
echo " $lbfonly"; ?
>style
='width:5%'><?php
xl('Source', 'e'); ?
></th
>
1543 <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
>
1544 <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
>
1545 <th style
='width:6%'><?php
xl('UOR', 'e'); ?
></th
>
1546 <th style
='width:10%'><?php
xl('Data Type', 'e'); ?
></th
>
1547 <th style
='width:1%'><?php
xl('Size', 'e'); ?
></th
>
1548 <th style
='width:1%'><?php
xl('Max Size', 'e'); ?
></th
>
1549 <th style
='width:10%'><?php
xl('List', 'e'); ?
></th
>
1550 <th style
='width:10%'><?php
xl('Backup List', 'e'); ?
></th
>
1551 <th style
='width:1%'><?php
xl('Label Cols', 'e'); ?
></th
>
1552 <th style
='width:1%'><?php
xl('Data Cols', 'e'); ?
></th
>
1553 <th style
='width:10%'><?php
xl('Options', 'e'); ?
></th
>
1554 <th style
='width:20%'><?php
xl('Description', 'e'); ?
></th
>
1559 <td
><input type
="text" name
="newseq" id
="newseq" value
="" size
="2" maxlength
="4"> </td
>
1560 <td
<?php
echo " $lbfonly"; ?
>>
1561 <select
class='form-control' name
='newsource' id
='newsource'>
1563 foreach ($sources as $key => $value) {
1564 echo " <option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1569 <td
><input type
="text" name
="newid" id
="newid" value
="" size
="10" maxlength
="20"
1570 onclick
='FieldIDClicked(this)'> </td
>
1571 <td
><input type
="text" name
="newtitle" id
="newtitle" value
="" size
="20" maxlength
="63"> </td
>
1573 <select
class='form-control' name
="newuor" id
="newuor">
1574 <option value
="0"><?php
xl('Unused', 'e'); ?
></option
>
1575 <option value
="1" selected
><?php
xl('Optional', 'e'); ?
></option
>
1576 <option value
="2"><?php
xl('Required', 'e'); ?
></option
>
1580 <select
class='form-control' name
='newdatatype' id
='newdatatype'>
1581 <option value
=''></option
>
1584 foreach ($datatypes as $key => $value) {
1585 echo " <option value='$key'>$value</option>\n";
1590 <td
><input type
="text" name
="newlengthWidth" id
="newlengthWidth" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Width'); ?>">
1591 <input type
="text" name
="newlengthHeight" id
="newlengthHeight" value
="" size
="1" maxlength
="3" title
="<?php echo xla('Height'); ?>"></td
>
1592 <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
>
1593 <td
><input type
="text" name
="newlistid" id
="newlistid" value
="" size
="8" maxlength
="31" class="listid">
1594 <select
class='form-control' name
='contextName' id
='contextName' style
='display:none'>
1596 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1597 while ($row = sqlFetchArray($res)) {
1598 echo "<option value='".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."'>".htmlspecialchars($row['cl_list_item_long'], ENT_QUOTES
)."</option>";
1603 <td
><input type
="text" name
="newbackuplistid" id
="newbackuplistid" value
="" size
="8" maxlength
="31" class="listid"></td
>
1604 <td
><input type
="text" name
="newtitlecols" id
="newtitlecols" value
="" size
="3" maxlength
="3"> </td
>
1605 <td
><input type
="text" name
="newdatacols" id
="newdatacols" value
="" size
="3" maxlength
="3"> </td
>
1606 <td
><select name
="newedit_options[]" id
="newedit_options" multiple
class='typeAddons' style
='width:100%'></select
>
1607 <input type
="hidden" name
="newdefault" id
="newdefault" value
="" /> </td
>
1608 <td
><input type
="text" name
="newdesc" id
="newdesc" value
="" size
="30"> </td
>
1612 <input type
="button" class="savenewfield" value
=<?php
xl('Save New Field', 'e', '\'', '\''); ?
>>
1613 <input type
="button" class="cancelnewfield" value
=<?php
xl('Cancel', 'e', '\'', '\''); ?
>>
1623 /* Field modifier objects - heading towards context based.
1624 Used by Select2 so rtl may be enabled*/
1625 <?php
echo "var fldOptions = [
1626 {id: 'A',text:'" . xla('Age') . "',ctx:['4'],ctxExcp:['0']},
1627 {id: 'B',text:'" . xla('Gestational Age') . "',ctx:['4'],ctxExcp:['0']},
1628 {id: 'F',text:'" . xla('Add Time to Date') . "',ctx:['4'],ctxExcp:['0']},
1629 {id: 'C',text:'" . xla('Capitalize') . "',ctx:['0'],ctxExcp:['4','15','40']},
1630 {id: 'D',text:'" . xla('Dup Check') . "'},
1631 {id: 'E',text:'" . xla('Dup Check on only Edit') . "'},
1632 {id: 'W',text:'" . xla('Dup Check on only New') . "'},
1633 {id: 'G',text:'" . xla('Graphable') . "'},
1634 {id: 'I',text:'" . xla('Initially Open Group') . "'},
1635 {id: 'L',text:'" . xla('Lab Order') . "'},
1636 {id: 'N',text:'" . xla('New Patient Form') . "'},
1637 {id: 'O',text:'" . xla('Order Processor') . "'},
1638 {id: 'P',text:'" . xla('Default to previous value') . "'},
1639 {id: 'R',text:'" . xla('Distributor') . "'},
1640 {id: 'T',text:'" . xla('Description is default text') . "'},
1641 {id: 'U',text:'" . xla('Capitalize all') . "'},
1642 {id: 'V',text:'" . xla('Vendor') . "'},
1643 {id: 'X',text:'" . xla('Do Not Print') . "'},
1644 {id:'grp',text:'" . xla('Stylings') . "',children:[
1645 {id: 'RS',text:'" . xla('Add Bottom Border Row') . "'},
1646 {id: 'RO',text:'" . xla('Outline Entire Row') . "'},
1647 {id: 'DS',text:'" . xla('Add Data Bottom Border') . "'},
1648 {id: 'DO',text:'" . xla('Outline Data Col') . "'},
1649 {id: 'SP',text:'" . xla('Span Entire Row') . "'}
1651 {id: '0',text:'" . xla('Read Only') . "'},
1652 {id: '1',text:'" . xla('Write Once') . "'},
1653 {id: '2',text:'" . xla('Billing Code Descriptions') . "'}];\n";
1655 // Language direction for select2
1656 echo 'var langDirection = "' . $_SESSION['language_direction'] . '";';
1659 // used when selecting a list-name for a field
1662 // Support for beforeunload handler.
1663 var somethingChanged
= false;
1665 // Get the next logical sequence number for a field in the specified group.
1666 // Note it guesses and uses the existing increment value.
1667 function getNextSeq(group
) {
1668 var f
= document
.forms
[0];
1671 for (var i
= 1; true; ++i
) {
1672 var gelem
= f
['fld[' + i +
'][group]'];
1674 if (gelem
.value
!= group
) continue;
1675 var tmp
= parseInt(f
['fld[' + i +
'][seq]'].value
);
1676 if (isNaN(tmp
)) continue;
1677 if (tmp
<= seq
) continue;
1684 // jQuery stuff to make the page a little easier to use
1686 $
(document
).ready(function(){
1689 $
('.typeAddons').select2({
1693 closeOnSelect
: false,
1695 minimumResultsForSearch
: 'Infinity',
1696 containerCssClass
: ':all:',
1698 <?php
require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?
>
1701 // Populate field option selects
1703 $
('.typeAddons').each(function(i
, obj
) {
1704 var v
= $
(this
).data('set')
1705 if(typeof v
!== 'undefined' && v
> ""){
1706 $
(this
).val(v
).trigger("change")
1709 somethingChanged
= false;
1712 $
("#save").click(function() { SaveChanges(); });
1713 $
("#layout_id").change(function() {
1714 if (!myChangeCheck()) {
1715 $
("#layout_id").val("<?php echo $layout_id; ?>");
1720 $
(".addgroup").click(function() { AddGroup(this
); });
1721 $
(".savenewgroup").click(function() { SaveNewGroup(this
); });
1722 /******************************************************************
1723 $(".deletegroup").click(function() { DeleteGroup(this); });
1724 ******************************************************************/
1725 $
(".cancelnewgroup").click(function() { CancelNewGroup(this
); });
1726 $
(".movegroup").click(function() { MoveGroup(this
); });
1727 $
(".renamegroup").click(function() { RenameGroup(this
); });
1728 $
(".saverenamegroup").click(function() { SaveRenameGroup(this
); });
1729 $
(".cancelrenamegroup").click(function() { CancelRenameGroup(this
); });
1730 $
(".addfield").click(function() { AddField(this
); });
1731 $
("#deletefields").click(function() { DeleteFields(this
); });
1732 $
(".selectfield").click(function() {
1733 var TRparent
= $
(this
).parent().parent();
1734 $
(TRparent
).children("td").toggleClass("highlight");
1735 // disable the delete-move buttons
1736 $
("#deletefields").attr("disabled", "disabled");
1737 $
("#movefields").attr("disabled", "disabled");
1738 $
(".selectfield").each(function(i
) {
1739 // if any field is selected, enable the delete-move buttons
1740 if ($
(this
).prop("checked") == true) {
1741 $
("#deletefields").removeAttr("disabled");
1742 $
("#movefields").removeAttr("disabled");
1747 $
("#movefields").click(function() { ShowGroups(this
); });
1748 $
(".savenewfield").click(function() { SaveNewField(this
); });
1749 $
(".cancelnewfield").click(function() { CancelNewField(this
); });
1750 $
("#newtitle").blur(function() { if ($
("#newid").val() == "") $
("#newid").val($
("#newtitle").val()); });
1751 $
("#newdatatype").change(function() { ChangeList(this
.value
);});
1752 $
("#gnewdatatype").change(function() { ChangeListg(this
.value
);});
1753 $
(".listid").click(function() { ShowLists(this
); });
1755 // special class that skips the element
1756 $
(".noselect").focus(function() { $
(this
).blur(); });
1758 // Save the changes made to the form
1759 var SaveChanges
= function () {
1760 var f
= document
.forms
[0];
1761 for (var i
= 1; f
['fld['+i+
'][id]']; ++i
) {
1762 var ival
= f
['fld['+i+
'][id]'].value
;
1763 for (var j
= i +
1; f
['fld['+j+
'][id]']; ++j
) {
1764 if (ival
== f
['fld['+j+
'][id]'].value || ival
== f
['fld['+j+
'][originalid]'].value
) {
1765 alert('<?php echo xls('Error
: Duplicated field ID
'); ?>: ' + ival
);
1770 $
("#formaction").val("save");
1774 /****************************************************/
1775 /************ Group functions ***********************/
1776 /****************************************************/
1778 // display the 'new group' DIV
1779 var AddGroup
= function(btnObj
) {
1780 if (!myChangeCheck()) return;
1781 $
("#save").attr("disabled", true);
1782 // show the field details DIV
1783 $
('#groupdetail').css('visibility', 'visible');
1784 $
('#groupdetail').css('display', 'block');
1785 $
('#groupdetail').css('margin-top', '85px');
1786 $
(btnObj
).parent().after($
("#groupdetail"));
1787 $
("html, body").animate({ scrollTop
: 0 }, "slow");
1788 $
('#groupdetail > #newgroupname').focus();
1789 // Assign a sensible default sequence number.
1790 $
('#gnewseq').val(10);
1793 // save the new group to the form
1794 var SaveNewGroup
= function(btnObj
) {
1795 // the group name field can only have letters, numbers, spaces and underscores
1796 // AND it cannot start with a number
1797 if ($
("#newgroupname").val() == "") {
1798 alert("<?php xl('Group names cannot be blank', 'e'); ?>");
1801 if ($
("#newgroupname").val().match(/^
(\d+|\s+
)/)) {
1802 alert("<?php xl('Group names cannot start with numbers or spaces.', 'e'); ?>");
1805 var validname
= $
("#newgroupname").val().replace(/[^A
-za
-z0
-9 ]/g
, "_"); // match any non-word characters and replace them
1806 $
("#newgroupname").val(validname
);
1808 // now, check the first group field values
1810 // seq must be numeric and <= 9999
1811 if (! IsNumeric($
("#gnewseq").val(), 0, 9999)) {
1812 alert("<?php xl('Order must be a number between 1 and 9999', 'e'); ?>");
1815 // length must be numeric and less than 999
1816 if (! IsNumeric($
("#gnewlengthWidth").val(), 0, 999)) {
1817 alert("<?php xl('Size must be a number between 1 and 999', 'e'); ?>");
1820 // titlecols must be numeric and less than 100
1821 if (! IsNumeric($
("#gnewtitlecols").val(), 0, 999)) {
1822 alert("<?php xl('LabelCols must be a number between 1 and 999', 'e'); ?>");
1825 // datacols must be numeric and less than 100
1826 if (! IsNumeric($
("#gnewdatacols").val(), 0, 999)) {
1827 alert("<?php xl('DataCols must be a number between 1 and 999', 'e'); ?>");
1830 // the id field can only have letters, numbers and underscores
1831 if ($
("#gnewid").val() == "") {
1832 alert("<?php xl('ID cannot be blank', 'e'); ?>");
1835 var validid
= $
("#gnewid").val().replace(/(\s|\W
)/g
, "_"); // match any non-word characters and replace them
1836 $
("#gnewid").val(validid
);
1837 // similarly with the listid field
1838 validid
= $
("#gnewlistid").val().replace(/(\s|\W
)/g
, "_");
1839 $
("#gnewlistid").val(validid
);
1840 // similarly with the backuplistid field
1841 validid
= $
("#gnewbackuplistid").val().replace(/(\s|\W
)/g
, "_");
1842 $
("#gnewbackuplistid").val(validid
);
1845 // submit the form to add a new field to a specific group
1846 $
("#formaction").val("addgroup");
1850 /******************************************************************
1851 // actually delete an entire group from the database
1852 var DeleteGroup = function(btnObj) {
1853 var parts = $(btnObj).attr("id");
1854 var groupname = parts.replace(/^\d+/, "");
1855 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+"'?")) {
1856 // submit the form to add a new field to a specific group
1857 $("#formaction").val("deletegroup");
1858 $("#deletegroupname").val(parts);
1859 $("#theform").submit();
1862 ******************************************************************/
1864 // just hide the new field DIV
1865 var CancelNewGroup
= function(btnObj
) {
1866 // hide the field details DIV
1867 $
('#groupdetail').css('visibility', 'hidden');
1868 $
('#groupdetail').css('display', 'none');
1869 // reset the new group values to a default
1870 $
('#groupdetail > #newgroupname').val("");
1871 $
('#groupdetail > #newgroupparent').val("");
1872 $
("#save").attr("disabled", false);
1875 // display the 'new field' DIV
1876 var MoveGroup
= function(btnObj
) {
1877 if (!myChangeCheck()) return;
1878 var btnid
= $
(btnObj
).attr("id");
1879 var parts
= btnid
.split("~");
1880 var groupid
= parts
[0];
1881 var direction
= parts
[1];
1882 // submit the form to change group order
1883 $
("#formaction").val("movegroup");
1884 $
("#movegroupname").val(groupid
);
1885 $
("#movedirection").val(direction
);
1889 // show the rename group DIV
1890 var RenameGroup
= function(btnObj
) {
1891 if (!myChangeCheck()) return;
1892 $
("#save").attr("disabled", true);
1893 $
('#renamegroupdetail').css('visibility', 'visible');
1894 $
('#renamegroupdetail').css('display', 'block');
1895 $
(btnObj
).parent().append($
("#renamegroupdetail"));
1896 var parts
= $
(btnObj
).attr("id").split("~");
1897 $
('#renameoldgroupname').val(parts
[0]); // this is actually the existing group ID
1898 $
('#renamegroupname').val(parts
[1]); // the textual name of just this group
1899 var i
= parts
[0].length
;
1900 $
('[name=renamegroupparent]').val(i
> 0 ? parts
[0].substr(0, i
-1) : ''); // parent ID
1903 // save the new group to the form
1904 var SaveRenameGroup
= function(btnObj
) {
1905 // the group name field can only have letters, numbers, spaces and underscores
1906 // AND it cannot start with a number
1907 if ($
("#renamegroupname").val().match(/^\d+
/)) {
1908 alert("<?php xl('Group names cannot start with numbers.', 'e'); ?>");
1911 var validname
= $
("#renamegroupname").val().replace(/[^A
-za
-z0
-9 ]/g
, "_"); // match any non-word characters and replace them
1912 $
("#renamegroupname").val(validname
);
1914 // submit the form to add a new field to a specific group
1915 $
("#formaction").val("renamegroup");
1919 // just hide the new field DIV
1920 var CancelRenameGroup
= function(btnObj
) {
1921 // hide the field details DIV
1922 $
('#renamegroupdetail').css('visibility', 'hidden');
1923 $
('#renamegroupdetail').css('display', 'none');
1924 // reset the rename group values to a default
1925 $
('#renameoldgroupname').val("");
1926 $
('#renamegroupname').val("");
1927 $
('#renamegroupparent').val("");
1930 /****************************************************/
1931 /************ Field functions ***********************/
1932 /****************************************************/
1934 // display the 'new field' DIV
1935 var AddField
= function(btnObj
) {
1936 if (!myChangeCheck()) return;
1937 $
("#save").attr("disabled", true);
1938 // update the fieldgroup value to be the groupid
1939 var btnid
= $
(btnObj
).attr("id");
1940 var parts
= btnid
.split("~");
1941 var groupid
= parts
[1];
1942 $
('#fielddetail > #newfieldgroupid').attr('value', groupid
);
1943 // show the field details DIV
1944 $
('#fielddetail').css('visibility', 'visible');
1945 $
('#fielddetail').css('display', 'block');
1946 $
(btnObj
).parent().append($
("#fielddetail"));
1947 // Assign a sensible default sequence number.
1948 $
('#newseq').val(getNextSeq(groupid
));
1951 var DeleteFields
= function(btnObj
) {
1952 if (!myChangeCheck()) return;
1953 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'); ?>")) {
1955 $
(".selectfield").each(function(i
) {
1956 // build a list of selected field names to be moved
1957 if ($
(this
).prop("checked") == true) {
1958 var parts
= this
.id
.split("~");
1959 var currval
= $
("#selectedfields").val();
1960 $
("#selectedfields").val(currval+delim+parts
[1]);
1964 // submit the form to delete the field(s)
1965 $
("#formaction").val("deletefields");
1970 // save the new field to the form
1971 var SaveNewField
= function(btnObj
) {
1972 // check the new field values for correct formatting
1974 // seq must be numeric and <= 9999
1975 if (! IsNumeric($
("#newseq").val(), 0, 9999)) {
1976 alert("<?php xl('Order must be a number between 1 and 9999', 'e'); ?>");
1979 // length must be numeric and less than 999
1980 if (! IsNumeric($
("#newlengthWidth").val(), 0, 999)) {
1981 alert("<?php xl('Size must be a number between 1 and 999', 'e'); ?>");
1984 // titlecols must be numeric and less than 100
1985 if (! IsNumeric($
("#newtitlecols").val(), 0, 999)) {
1986 alert("<?php xl('LabelCols must be a number between 1 and 999', 'e'); ?>");
1989 // datacols must be numeric and less than 100
1990 if (! IsNumeric($
("#newdatacols").val(), 0, 999)) {
1991 alert("<?php xl('DataCols must be a number between 1 and 999', 'e'); ?>");
1994 // the id field can only have letters, numbers and underscores
1995 var validid
= $
("#newid").val().replace(/(\s|\W
)/g
, "_"); // match any non-word characters and replace them
1996 $
("#newid").val(validid
);
1997 // similarly with the listid field
1998 validid
= $
("#newlistid").val().replace(/(\s|\W
)/g
, "_");
1999 $
("#newlistid").val(validid
);
2000 // similarly with the backuplistid field
2001 validid
= $
("#newbackuplistid").val().replace(/(\s|\W
)/g
, "_");
2002 $
("#newbackuplistid").val(validid
);
2004 // submit the form to add a new field to a specific group
2005 $
("#formaction").val("addfield");
2009 // just hide the new field DIV
2010 var CancelNewField
= function(btnObj
) {
2011 // hide the field details DIV
2012 $
('#fielddetail').css('visibility', 'hidden');
2013 $
('#fielddetail').css('display', 'none');
2014 // reset the new field values to a default
2015 ResetNewFieldValues();
2016 $
("#save").attr("disabled", false);
2019 // show the popup choice of lists
2020 var ShowLists
= function(btnObj
) {
2021 var title
= "<?php echo xla('Select List');?>";
2022 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=lists',"_blank", 850, 750, "", title
);
2023 selectedfield
= btnObj
;
2026 // show the popup choice of groups
2027 var ShowGroups
= function(btnObj
) {
2028 if (!myChangeCheck()) return;
2029 var title
= "<?php echo xlt('Select Group');?>";
2030 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=groups&layout_id=<?php echo addslashes($layout_id); ?>',
2031 "_blank",850, 600,"", title
);
2034 // Show context DD for NationNotes
2035 var ChangeList
= function(btnObj
){
2037 $
('#newlistid').hide();
2038 $
('#contextName').show();
2041 $
('#newlistid').show();
2042 $
('#contextName').hide();
2045 var ChangeListg
= function(btnObj
){
2047 $
('#gnewlistid').hide();
2048 $
('#gcontextName').show();
2051 $
('#gnewlistid').show();
2052 $
('#gcontextName').hide();
2056 // Initialize list item selectors and value field visibilities in skip conditions.
2057 var f
= document
.forms
[0];
2058 for (var lino
= 1; f
['fld[' + lino +
'][id]']; ++lino
) {
2059 for (var seq
= 0; f
['fld[' + lino +
'][condition_itemid][' + seq +
']']; ++seq
) {
2060 setListItemOptions(lino
, seq
, true);
2062 actionChanged(lino
);
2065 // Support for beforeunload handler.
2066 $
('tbody input, tbody select, tbody textarea').not('.selectfield').change(function() {
2067 somethingChanged
= true;
2069 window
.addEventListener("beforeunload", function (e
) {
2070 if (somethingChanged
&& !top
.timed_out
) {
2071 var msg
= "<?php echo xls('You have unsaved changes.'); ?>";
2072 e
.returnValue
= msg
; // Gecko, Trident, Chrome 34+
2073 return msg
; // Gecko, WebKit, Chrome <34
2077 }); /* Ready Done */
2079 function layoutLook(){
2080 var form
= "<?php echo attr($layout_id);?>";
2081 var btnName
= "<?php echo xla('Back To Editor');?>";
2082 var url
= "../patient_file/encounter/view_form.php?isShow&id=0&formname=" + form
;
2083 var title
= "<?php echo xlt('LBF Encounter Form Preview');?>";
2084 dlgopen(url
, '_blank', 1250, 800, "", title
);
2088 function NationNotesContext(lineitem
, val
) {
2089 // Check if function is needed.
2090 if (!document
.getElementById("fld[" + lineitem +
"][contextName]") ||
!document
.getElementById("fld[" + lineitem +
"][list_id]")) {
2091 return false; // these elements don't exist yet so do nothing.
2094 document
.getElementById("fld[" + lineitem +
"][contextName]").style
.display
= '';
2095 document
.getElementById("fld[" + lineitem +
"][list_id]").style
.display
= 'none';
2096 document
.getElementById("fld[" + lineitem +
"][list_id]").value
= '';
2099 document
.getElementById("fld[" + lineitem +
"][list_id]").style
.display
= '';
2100 document
.getElementById("fld[" + lineitem +
"][contextName]").style
.display
= 'none';
2101 document
.getElementById("fld[" + lineitem +
"][list_id]").value
= '';
2105 function SetList(listid
) {
2106 $
(selectedfield
).val(listid
);
2109 //////////////////////////////////////////////////////////////////////
2110 // The following supports the field ID selection pop-up.
2111 //////////////////////////////////////////////////////////////////////
2113 var fieldselectfield
;
2115 function elemFromPart(part
) {
2116 var ename
= fieldselectfield
.name
;
2117 // ename is like one of the following:
2118 // fld[$fld_line_no][id]
2121 // and "part" is what we substitute for the "id" part.
2122 var i
= ename
.lastIndexOf('id');
2123 ename
= ename
.substr(0, i
) + part + ename
.substr(i+
2);
2124 return document
.forms
[0][ename
];
2127 function FieldIDClicked(elem
) {
2128 <?php
if (substr($layout_id, 0, 3) == 'LBF') { ?
>
2129 fieldselectfield
= elem
;
2130 var srcval
= elemFromPart('source').value
;
2131 // If the field ID is for the local form, allow direct entry.
2132 if (srcval
== 'F') return;
2133 // Otherwise pop up the selection window.
2134 var title
= "<?php echo xlt('Select Field');?>";
2135 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=fields&source='
2136 + srcval
, "_blank", 700, 600, "", title
);
2140 function SetField(field_id
, title
, data_type
, uor
, fld_length
, max_length
,
2141 list_id
, titlecols
, datacols
, edit_options
, description
, fld_rows
)
2143 fieldselectfield
.value
= field_id
;
2144 elemFromPart('title' ).value
= title
;
2145 elemFromPart('datatype' ).value
= data_type
;
2146 elemFromPart('uor' ).value
= uor
;
2147 elemFromPart('lengthWidth' ).value
= fld_length
;
2148 elemFromPart('maxSize' ).value
= max_length
;
2149 elemFromPart('list_id' ).value
= list_id
;
2150 elemFromPart('titlecols' ).value
= titlecols
;
2151 elemFromPart('datacols' ).value
= datacols
;
2152 elemFromPart('edit_options').value
= edit_options
;
2153 elemFromPart('desc' ).value
= description
;
2154 elemFromPart('lengthHeight').value
= fld_rows
;
2157 //////////////////////////////////////////////////////////////////////
2158 // End code for field ID selection pop-up.
2159 //////////////////////////////////////////////////////////////////////
2161 /* this is called after the user chooses a new group from the popup window
2162 * it will submit the page so the selected fields can be moved into
2165 function MoveFields(targetgroup
) {
2166 $
("#targetgroup").val(targetgroup
);
2168 $
(".selectfield").each(function(i
) {
2169 // build a list of selected field names to be moved
2170 if ($
(this
).prop("checked") == true) {
2171 var parts
= this
.id
.split("~");
2172 var currval
= $
("#selectedfields").val();
2173 $
("#selectedfields").val(currval+delim+parts
[1]);
2177 $
("#formaction").val("movefields");
2181 // set the new-field values to a default state
2182 function ResetNewFieldValues () {
2183 $
("#newseq").val("");
2184 $
("#newsource").val("");
2185 $
("#newid").val("");
2186 $
("#newtitle").val("");
2187 $
("#newuor").val(1);
2188 $
("#newlengthWidth").val("");
2189 $
("#newlengthHeight").val("");
2190 $
("#newmaxSize").val("");
2191 $
("#newdatatype").val("");
2192 $
("#newlistid").val("");
2193 $
("#newbackuplistid").val("");
2194 $
("#newtitlecols").val("");
2195 $
("#newdatacols").val("");
2196 $
("#newedit_options").val("");
2197 $
("#newdefault").val("");
2198 $
("#newdesc").val("");
2201 // is value an integer and between min and max
2202 function IsNumeric(value
, min
, max
) {
2203 if (value
== "" || value
== null) return false;
2205 parseInt(value
) < min ||
2206 parseInt(value
) > max
)
2212 /****************************************************/
2213 /****************************************************/
2214 /****************************************************/
2216 // tell if num is an Integer
2217 function IsN(num
) { return !/\D
/.test(num
); }