Fully responsive globals.php with vertical menu (#2460)
[openemr.git] / interface / super / edit_layout.php
blobde9d23d34c1c0e1b63b767d589b8815cce5202c9
1 <?php
2 /**
3 * Edit layouts gui
5 * @package OpenEMR
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-2019 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2017 Jerry Padgett <sjpadgett@gmail.com>
12 * @copyright Copyright (c) 2017-2018 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");
19 use OpenEMR\Common\Logging\EventAuditLogger;
20 use OpenEMR\Core\Header;
22 function collectLayoutNames($condition, $mapping = '')
24 global $layouts;
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'];
31 if (!$tmp) {
32 $tmp = '(' . xl('No Name') . ')';
34 $layouts[$grow['grp_form_id']] = array($tmp, $grow['grp_title']);
37 $layouts = array();
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
52 $datatypes = array(
53 "1" => xl("List box"),
54 "2" => xl("Textbox"),
55 "3" => xl("Textarea"),
56 "4" => xl("Text-date"),
57 "10" => xl("Providers"),
58 "11" => xl("Providers NPI"),
59 "12" => xl("Pharmacies"),
60 "13" => xl("Squads"),
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"),
82 $sources = array(
83 'F' => xl('Form'),
84 'D' => xl('Patient'),
85 'H' => xl('History'),
86 'E' => xl('Visit'),
87 'V' => xl('VisForm'),
90 function nextGroupOrder($order)
92 if ($order == '9') {
93 $order = 'A';
94 } else if ($order == 'Z') {
95 $order = 'a';
96 } else {
97 $order = chr(ord($order) + 1);
100 return $order;
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 = '')
109 $res = sqlStatement(
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",
113 array($layout_id)
115 $s = "<select class='form-control' name='" . xla($name) . "'>";
116 $s .= "<option value=''>" . xlt('None') . "</option>";
117 $arr = array();
118 $arrid = '';
119 while ($row = sqlFetchArray($res)) {
120 $thisid = $row['grp_group_id'];
121 $i = 0;
122 // Compute number of initial matching groups.
123 while ($i < strlen($thisid) && $i < strlen($arrid) && $thisid[$i] == $arrid[$i]) {
124 ++$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'];
131 $gval = '';
132 foreach ($arr as $part) {
133 if ($gval) {
134 $gval .= ' / ';
136 $gval .= $part;
138 $s .= "<option value='" . attr($thisid) . "'";
139 if ($thisid == $default) {
140 $s .= ' selected';
142 $s .= ">" . text($gval) . "</option>";
144 $s .= "</select>";
145 return $s;
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)
156 global $layout_id;
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_%")
163 $maxnum = '1';
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)
179 global $layout_id;
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)
195 $i = 0;
196 while ($i < strlen($id1) && $i < strlen($id2) && $id1[$i] == $id2[$i]) {
197 ++$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") {
216 return '';
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";
228 } else {
229 die(xlt('Internal error in tableNameFromLayout') . '(' . text($layout_id) . ')');
231 return $tablename;
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);
240 if (!$tablename) {
241 return;
243 // Check if the column currently exists.
244 $tmp = sqlQuery("SHOW COLUMNS FROM `$tablename` LIKE ?", array($field_id));
245 $column_exists = !empty($tmp);
247 if ($add && !$column_exists) {
248 sqlStatement("ALTER TABLE `$tablename` ADD `" . add_escape_custom($field_id) . "` TEXT");
249 EventAuditLogger::instance()->newEvent(
250 "alter_table",
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 `" . add_escape_custom($field_id) . "` FROM `$tablename` WHERE " .
259 "`" . add_escape_custom($field_id) . "` IS NOT NULL AND `" . add_escape_custom($field_id) . "` != '' LIMIT 1");
260 if (!isset($tmp['field_id'])) {
261 sqlStatement("ALTER TABLE `$tablename` DROP `" . add_escape_custom($field_id) . "`");
262 EventAuditLogger::instance()->newEvent(
263 "alter_table",
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);
283 if (!$tablename) {
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.
290 return 2;
292 // Make sure new column does not exist.
293 $tmp = sqlQuery("SHOW COLUMNS FROM `$tablename` LIKE ?", array($new_field_id));
294 if (!empty($tmp)) {
295 // Error, new name already in use.
296 return 3;
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 .= " " . add_escape_custom($colarr['Extra']);
309 $query = "ALTER TABLE `$tablename` CHANGE `" . add_escape_custom($old_field_id) . "` `" . add_escape_custom($new_field_id) . "` $colstr";
310 sqlStatement($query);
311 EventAuditLogger::instance()->newEvent(
312 "alter_table",
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');
329 if (!$thisauth) {
330 die(xlt('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 (!verifyCsrfToken($_POST["csrf_token_form"])) {
343 csrfNotVerified();
346 // If we are saving, then save.
347 $fld = $_POST['fld'];
348 for ($lino = 1; isset($fld[$lino]['id']); ++$lino) {
349 $iter = $fld[$lino];
350 $field_id = trim($iter['id']);
351 $field_id_original = trim($iter['originalid']);
352 $data_type = trim($iter['datatype']);
353 $listval = $data_type == 34 ? trim($iter['contextName']) : trim($iter['list_id']);
354 $action = $iter['action'];
355 if ($action == 'value') {
356 $action = 'value=' . $iter['value'];
359 // Skip conditions for the line are stored as a serialized array.
360 $condarr = array('action' => $action);
361 $cix = 0;
362 for (; !empty($iter['condition_id'][$cix]); ++$cix) {
363 $andor = empty($iter['condition_andor'][$cix]) ? '' : $iter['condition_andor'][$cix];
364 $condarr[$cix] = array(
365 'id' => $iter['condition_id' ][$cix],
366 'itemid' => $iter['condition_itemid' ][$cix],
367 'operator' => $iter['condition_operator'][$cix],
368 'value' => $iter['condition_value' ][$cix],
369 'andor' => $andor,
372 $conditions = $cix ? serialize($condarr) : '';
374 if ($field_id) {
375 if ($field_id != $field_id_original) {
376 if (renameColumn($layout_id, $field_id_original, $field_id) > 0) {
377 // If column rename had an error then don't rename it here.
378 $field_id = $field_id_original;
381 sqlStatement("UPDATE layout_options SET " .
382 "field_id = '" . add_escape_custom($field_id) . "', " .
383 "source = '" . add_escape_custom(trim($iter['source'])) . "', " .
384 "title = '" . add_escape_custom($iter['title']) . "', " .
385 "group_id = '" . add_escape_custom(trim($iter['group'])) . "', " .
386 "seq = '" . add_escape_custom(trim($iter['seq'])) . "', " .
387 "uor = '" . add_escape_custom(trim($iter['uor'])) . "', " .
388 "fld_length = '" . add_escape_custom(trim($iter['lengthWidth'])) . "', " .
389 "fld_rows = '" . add_escape_custom(trim($iter['lengthHeight'])) . "', " .
390 "max_length = '" . add_escape_custom(trim($iter['maxSize'])) . "', " .
391 "titlecols = '" . add_escape_custom(trim($iter['titlecols'])) . "', " .
392 "datacols = '" . add_escape_custom(trim($iter['datacols'])) . "', " .
393 "data_type= '" . add_escape_custom($data_type) . "', " .
394 "list_id= '" . add_escape_custom($listval) . "', " .
395 "list_backup_id= '" . add_escape_custom(trim($iter['list_backup_id'])) . "', " .
396 "edit_options = '" . add_escape_custom(encodeModifier($iter['edit_options'])) . "', " .
397 "default_value = '" . add_escape_custom(trim($iter['default'])) . "', " .
398 "description = '" . add_escape_custom(trim($iter['desc'])) . "', " .
399 "conditions = '" . add_escape_custom($conditions) . "', " .
400 "validation = '" . add_escape_custom(trim($iter['validation'])) . "' " .
401 "WHERE form_id = '" . add_escape_custom($layout_id) . "' AND field_id = '" . add_escape_custom($field_id_original) . "'");
404 } else if ($_POST['formaction'] == "addfield" && $layout_id) {
405 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
406 csrfNotVerified();
409 // Add a new field to a specific group
410 $data_type = trim($_POST['newdatatype']);
411 $max_length = $data_type == 3 ? 3 : 255;
412 $listval = $data_type == 34 ? trim($_POST['contextName']) : trim($_POST['newlistid']);
413 sqlStatement("INSERT INTO layout_options (" .
414 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
415 ", titlecols, datacols, data_type, edit_options, default_value, description" .
416 ", max_length, list_id, list_backup_id " .
417 ") VALUES ( " .
418 "'" . add_escape_custom(trim($_POST['layout_id'])) . "'" .
419 ",'" . add_escape_custom(trim($_POST['newsource'])) . "'" .
420 ",'" . add_escape_custom(trim($_POST['newid'])) . "'" .
421 ",'" . add_escape_custom($_POST['newtitle']) . "'" .
422 ",'" . add_escape_custom(trim($_POST['newfieldgroupid'])) . "'" .
423 ",'" . add_escape_custom(trim($_POST['newseq'])) . "'" .
424 ",'" . add_escape_custom(trim($_POST['newuor'])) . "'" .
425 ",'" . add_escape_custom(trim($_POST['newlengthWidth'])) . "'" .
426 ",'" . add_escape_custom(trim($_POST['newlengthHeight'])) . "'" .
427 ",'" . add_escape_custom(trim($_POST['newtitlecols'])) . "'" .
428 ",'" . add_escape_custom(trim($_POST['newdatacols'])) . "'" .
429 ",'" . add_escape_custom($data_type) . "'" .
430 ",'" . add_escape_custom(encodeModifier($_POST['newedit_options'])) . "'" .
431 ",'" . add_escape_custom(trim($_POST['newdefault'])) . "'" .
432 ",'" . add_escape_custom(trim($_POST['newdesc'])) . "'" .
433 ",'" . add_escape_custom(trim($_POST['newmaxSize'])) . "'" .
434 ",'" . add_escape_custom($listval) . "'" .
435 ",'" . add_escape_custom(trim($_POST['newbackuplistid'])) . "'" .
436 " )");
437 addOrDeleteColumn($layout_id, trim($_POST['newid']), true);
438 } else if ($_POST['formaction'] == "movefields" && $layout_id) {
439 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
440 csrfNotVerified();
443 // Move field(s) to a new group in the layout
444 $sqlstmt = "UPDATE layout_options SET ".
445 " group_id = '" . add_escape_custom($_POST['targetgroup']) . "' " .
446 " WHERE ".
447 " form_id = '" . add_escape_custom($_POST['layout_id']) . "' ".
448 " AND field_id IN (";
449 $comma = "";
450 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
451 $sqlstmt .= $comma."'" . add_escape_custom($onefield) . "'";
452 $comma = ", ";
455 $sqlstmt .= ")";
456 //echo $sqlstmt;
457 sqlStatement($sqlstmt);
458 } else if ($_POST['formaction'] == "deletefields" && $layout_id) {
459 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
460 csrfNotVerified();
463 // Delete a field from a specific group
464 $sqlstmt = "DELETE FROM layout_options WHERE ".
465 " form_id = '" . add_escape_custom($_POST['layout_id']) . "' ".
466 " AND field_id IN (";
467 $comma = "";
468 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
469 $sqlstmt .= $comma."'" . add_escape_custom($onefield) . "'";
470 $comma = ", ";
473 $sqlstmt .= ")";
474 sqlStatement($sqlstmt);
475 foreach (explode(" ", $_POST['selectedfields']) as $onefield) {
476 addOrDeleteColumn($layout_id, $onefield, false);
478 } else if ($_POST['formaction'] == "addgroup" && $layout_id) {
479 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
480 csrfNotVerified();
483 // Generate new value for layout_items.group_id.
484 $newgroupid = genGroupId($_POST['newgroupparent']);
486 sqlStatement(
487 "INSERT INTO layout_group_properties SET " .
488 "grp_form_id = ?, " .
489 "grp_group_id = ?, " .
490 "grp_title = ?",
491 array($layout_id, $newgroupid, $_POST['newgroupname'])
494 $data_type = trim($_POST['gnewdatatype']);
495 $max_length = $data_type == 3 ? 3 : 255;
496 $listval = $data_type == 34 ? trim($_POST['gcontextName']) : trim($_POST['gnewlistid']);
497 // add a new group to the layout, with the defined field
498 sqlStatement("INSERT INTO layout_options (" .
499 " form_id, source, field_id, title, group_id, seq, uor, fld_length, fld_rows" .
500 ", titlecols, datacols, data_type, edit_options, default_value, description" .
501 ", max_length, list_id, list_backup_id " .
502 ") VALUES ( " .
503 "'" . add_escape_custom(trim($_POST['layout_id'])) . "'" .
504 ",'" . add_escape_custom(trim($_POST['gnewsource'])) . "'" .
505 ",'" . add_escape_custom(trim($_POST['gnewid'])) . "'" .
506 ",'" . add_escape_custom($_POST['gnewtitle']) . "'" .
507 ",'" . add_escape_custom(trim($newgroupid)) . "'" .
508 ",'" . add_escape_custom(trim($_POST['gnewseq'])) . "'" .
509 ",'" . add_escape_custom(trim($_POST['gnewuor'])) . "'" .
510 ",'" . add_escape_custom(trim($_POST['gnewlengthWidth'])) . "'" .
511 ",'" . add_escape_custom(trim($_POST['gnewlengthHeight'])) . "'" .
512 ",'" . add_escape_custom(trim($_POST['gnewtitlecols'])) . "'" .
513 ",'" . add_escape_custom(trim($_POST['gnewdatacols'])) . "'" .
514 ",'" . add_escape_custom($data_type) . "'" .
515 ",'" . add_escape_custom(encodeModifier($_POST['gnewedit_options'])) . "'" .
516 ",'" . add_escape_custom(trim($_POST['gnewdefault'])) . "'" .
517 ",'" . add_escape_custom(trim($_POST['gnewdesc'])) . "'" .
518 ",'" . add_escape_custom(trim($_POST['gnewmaxSize'])) . "'" .
519 ",'" . add_escape_custom($listval) . "'" .
520 ",'" . add_escape_custom(trim($_POST['gnewbackuplistid'])) . "'" .
521 " )");
522 addOrDeleteColumn($layout_id, trim($_POST['gnewid']), true);
523 } /**********************************************************************
524 else if ($_POST['formaction'] == "deletegroup" && $layout_id) {
525 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
526 csrfNotVerified();
529 // drop the fields from the related table (this is critical)
530 $res = sqlStatement("SELECT field_id FROM layout_options WHERE " .
531 "form_id = '" . $_POST['layout_id'] . "' ".
532 "AND group_name = '" . $_POST['deletegroupname'] . "'");
533 while ($row = sqlFetchArray($res)) {
534 addOrDeleteColumn($layout_id, $row['field_id'], false);
537 // Delete an entire group from the form
538 sqlStatement("DELETE FROM layout_options WHERE ".
539 " form_id = '".$_POST['layout_id']."' ".
540 " AND group_name = '".$_POST['deletegroupname']."'"
543 **********************************************************************/
545 else if ($_POST['formaction'] == "movegroup" && $layout_id) {
546 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
547 csrfNotVerified();
550 // Note that in some cases below the swapGroups() call will do nothing.
551 $res = sqlStatement(
552 "SELECT DISTINCT group_id " .
553 "FROM layout_options WHERE form_id = ? ORDER BY group_id",
554 array($layout_id)
556 $row = sqlFetchArray($res);
557 $id1 = $row['group_id'];
558 while ($row = sqlFetchArray($res)) {
559 $id2 = $row['group_id'];
560 if ($_POST['movedirection'] == 'up') { // moving up
561 if ($id2 == $_POST['movegroupname']) {
562 swapGroups($id2, $id1);
563 break;
565 } else { // moving down
566 if ($id1 == $_POST['movegroupname']) {
567 swapGroups($id1, $id2);
568 break;
571 $id1 = $id2;
573 } // Renaming a group. This might include moving to a different parent group.
574 else if ($_POST['formaction'] == "renamegroup" && $layout_id) {
575 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
576 csrfNotVerified();
579 $newparent = $_POST['renamegroupparent']; // this is an ID
580 $oldid = $_POST['renameoldgroupname']; // this is an ID
581 $oldparent = substr($oldid, 0, -1);
582 $newid = $oldid;
583 if ($newparent != $oldparent) {
584 // Different parent, generate a new child prefix character.
585 $newid = genGroupId($newparent);
586 sqlStatement(
587 "UPDATE layout_options SET group_id = ? " .
588 "WHERE form_id = ? AND group_id = ?",
589 array($newid, $layout_id, $oldid)
592 $query = "UPDATE layout_group_properties SET " .
593 "grp_group_id = ?, grp_title = ? " .
594 "WHERE grp_form_id = ? AND grp_group_id = ?";
595 sqlStatement($query, array($newid, $_POST['renamegroupname'], $layout_id, $oldid));
598 // Get the selected form's elements.
599 if ($layout_id) {
600 $res = sqlStatement("SELECT * FROM layout_options WHERE " .
601 "form_id = ? ORDER BY group_id, seq", array($layout_id));
604 // global counter for field numbers
605 $fld_line_no = 0;
607 $extra_html = '';
609 // This is called to generate a select option list for fields within this form.
610 // Used for selecting a field for testing in a skip condition.
612 function genFieldOptionList($current = '')
614 global $layout_id;
615 $option_list = "<option value=''>-- " . xlt('Please Select') . " --</option>";
616 if ($layout_id) {
617 $query = "SELECT field_id FROM layout_options WHERE form_id = ? ORDER BY group_id, seq";
618 $res = sqlStatement($query, array($layout_id));
619 while ($row = sqlFetchArray($res)) {
620 $field_id = $row['field_id'];
621 $option_list .= "<option value='" . attr($field_id) . "'";
622 if ($field_id == $current) {
623 $option_list .= " selected";
625 $option_list .= ">" . text($field_id) . "</option>";
628 return $option_list;
631 // Write one option line to the form.
633 function writeFieldLine($linedata)
635 global $fld_line_no, $sources, $lbfonly, $extra_html,$validations;
636 ++$fld_line_no;
637 $checked = $linedata['default_value'] ? " checked" : "";
639 //echo " <tr bgcolor='$bgcolor'>\n";
640 echo " <tr id='fld[" . attr($fld_line_no) . "]' class='".($fld_line_no % 2 ? 'even' : 'odd')."'>\n";
642 echo " <td class='optcell' nowrap>";
643 // tuck the group_name INPUT in here
644 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][group]' value='" .
645 attr($linedata['group_id']) . "' class='optin' />";
646 // Original field ID.
647 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][originalid]' value='" .
648 attr($linedata['field_id']) . "' />";
650 echo "<input type='checkbox' class='selectfield' ".
651 "name='" . attr($linedata['group_id']) . "~" . attr($linedata['field_id']) . "' " .
652 "id='" . attr($linedata['group_id']) . "~" . attr($linedata['field_id']) . "' " .
653 "title='" . xla('Select field') . "' />";
655 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][seq]' id='fld[" . attr($fld_line_no) . "][seq]' value='" .
656 attr($linedata['seq']) . "' size='2' maxlength='4' " .
657 "class='optin' style='width:32pt' />";
658 echo "</td>\n";
660 echo " <td align='center' class='optcell' $lbfonly>";
661 echo "<select class='form-control' name='fld[" . attr($fld_line_no) . "][source]' class='optin' $lbfonly>";
662 foreach ($sources as $key => $value) {
663 echo "<option value='" . attr($key) . "'";
664 if ($key == $linedata['source']) {
665 echo " selected";
668 echo ">" . text($value) . "</option>\n";
671 echo "</select>";
672 echo "</td>\n";
674 echo " <td align='left' class='optcell'>";
675 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][id]' value='" .
676 attr($linedata['field_id']) . "' size='15' maxlength='63' " .
677 "class='optin' style='width:100%' onclick='FieldIDClicked(this)' />";
678 echo "</td>\n";
680 echo " <td align='center' class='optcell'>";
681 echo "<input type='text' id='fld[" . attr($fld_line_no) . "][title]' name='fld[" . attr($fld_line_no) . "][title]' value='" .
682 attr($linedata['title']) . "' size='15' maxlength='63' class='optin' style='width:100%' />";
683 echo "</td>\n";
685 // if not english and set to translate layout labels, then show the translation
686 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
687 echo "<td align='center' class='translation' >" . xlt($linedata['title']) . "</td>\n";
690 echo " <td align='center' class='optcell'>";
691 echo "<select class='form-control' name='fld[" . attr($fld_line_no) . "][uor]' class='optin'>";
692 foreach (array(0 =>xl('Unused'), 1 =>xl('Optional'), 2 =>xl('Required')) as $key => $value) {
693 echo "<option value='" . attr($key) . "'";
694 if ($key == $linedata['uor']) {
695 echo " selected";
698 echo ">" . text($value) . "</option>\n";
701 echo "</select>";
702 echo "</td>\n";
704 echo " <td align='center' class='optcell'>";
705 echo "<select class='form-control' name='fld[" . attr($fld_line_no) . "][datatype]' id='fld[" . attr($fld_line_no) . "][datatype]' onchange=NationNotesContext(" . attr_js($fld_line_no) . ",this.value)>";
706 echo "<option value=''></option>";
707 global $datatypes;
708 foreach ($datatypes as $key => $value) {
709 if ($linedata['data_type'] == $key) {
710 echo "<option value='" . attr($key) . "' selected>" . text($value) . "</option>";
711 } else {
712 echo "<option value='" . attr($key) . "'>" . text($value) . "</option>";
716 echo "</select>";
717 echo " </td>";
719 echo " <td align='center' class='optcell'>";
720 if ($linedata['data_type'] == 2 || $linedata['data_type'] == 3 ||
721 $linedata['data_type'] == 21 || $linedata['data_type'] == 22 ||
722 $linedata['data_type'] == 23 || $linedata['data_type'] == 25 ||
723 $linedata['data_type'] == 27 || $linedata['data_type'] == 28 ||
724 $linedata['data_type'] == 32 || $linedata['data_type'] == 15 ||
725 $linedata['data_type'] == 40
727 // Show the width field
728 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][lengthWidth]' value='" .
729 attr($linedata['fld_length']) .
730 "' size='2' maxlength='10' class='optin' title='" . xla('Width') . "' />";
731 if ($linedata['data_type'] == 3 || $linedata['data_type'] == 40) {
732 // Show the height field
733 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][lengthHeight]' value='" .
734 attr($linedata['fld_rows']) .
735 "' size='2' maxlength='10' class='optin' title='" . xla('Height') . "' />";
736 } else {
737 // Hide the height field
738 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][lengthHeight]' value=''>";
740 } else {
741 // all other data_types (hide both the width and height fields
742 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][lengthWidth]' value=''>";
743 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][lengthHeight]' value=''>";
746 echo "</td>\n";
748 echo " <td align='center' class='optcell'>";
749 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][maxSize]' value='" .
750 attr($linedata['max_length']) .
751 "' size='1' maxlength='10' class='optin' style='width:100%' " .
752 "title='" . xla('Maximum Size (entering 0 will allow any size)') . "' />";
753 echo "</td>\n";
755 echo " <td align='center' class='optcell'>";
756 if ($linedata['data_type'] == 1 || $linedata['data_type'] == 21 ||
757 $linedata['data_type'] == 22 || $linedata['data_type'] == 23 ||
758 $linedata['data_type'] == 25 || $linedata['data_type'] == 26 ||
759 $linedata['data_type'] == 27 || $linedata['data_type'] == 32 ||
760 $linedata['data_type'] == 33 || $linedata['data_type'] == 34 ||
761 $linedata['data_type'] == 36) {
762 $type = "";
763 $disp = "style='display:none'";
764 if ($linedata['data_type'] == 34) {
765 $type = "style='display:none'";
766 $disp = "";
769 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][list_id]' id='fld[" . attr($fld_line_no) . "][list_id]' value='" .
770 attr($linedata['list_id']) . "' " . $type .
771 " size='6' maxlength='100' class='optin listid' style='width:100%;cursor:pointer'".
772 "title='". xla('Choose list') . "' />";
774 echo "<select class='form-control' name='fld[" . attr($fld_line_no) . "][contextName]' id='fld[" . attr($fld_line_no) . "][contextName]' ".$disp.">";
775 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
776 while ($row = sqlFetchArray($res)) {
777 $sel = '';
778 if ($linedata['list_id'] == $row['cl_list_item_long']) {
779 $sel = 'selected';
782 echo "<option value='" . attr($row['cl_list_item_long']) . "' ".$sel.">" . text($row['cl_list_item_long']) . "</option>";
785 echo "</select>";
786 } else {
787 // all other data_types
788 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][list_id]' value=''>";
791 echo "</td>\n";
793 //Backup List Begin
794 echo " <td align='center' class='optcell'>";
795 if ($linedata['data_type'] == 1 || $linedata['data_type'] == 26 ||
796 $linedata['data_type'] == 33 || $linedata['data_type'] == 36) {
797 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][list_backup_id]' value='" .
798 attr($linedata['list_backup_id']) .
799 "' size='3' maxlength='100' class='optin listid' style='cursor:pointer; width:100%' />";
800 } else {
801 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][list_backup_id]' value=''>";
804 echo "</td>\n";
805 //Backup List End
807 echo " <td align='center' class='optcell'>";
808 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][titlecols]' value='" .
809 attr($linedata['titlecols']) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
810 echo "</td>\n";
812 echo " <td align='center' class='optcell'>";
813 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][datacols]' value='" .
814 attr($linedata['datacols']) . "' size='3' maxlength='10' class='optin' style='width:100%' />";
815 echo "</td>\n";
816 /* Below for compatabilty with existing string modifiers. */
817 if (strpos($linedata['edit_options'], ',') === false && isset($linedata['edit_options'])) {
818 $t = json_decode($linedata['edit_options']);
819 if (json_last_error() !== JSON_ERROR_NONE || $t === 0) { // hopefully string of characters and 0 handled.
820 $t = str_split(trim($linedata['edit_options']));
821 $linedata['edit_options'] = json_encode($t); // convert to array select understands.
824 echo " <td align='center' class='optcell' title='" . xla("Add modifiers for this field type. You may select more than one.") . "'>";
825 echo "<select id='fld[" . attr($fld_line_no) . "][edit_options]' name='fld[" . attr($fld_line_no) . "][edit_options][]' class='typeAddons optin' size=3 multiple data-set='" .
826 attr(trim($linedata['edit_options'])) . "' ></select></td>\n";
828 if ($linedata['data_type'] == 31) {
829 echo " <td align='center' class='optcell'>";
830 echo "<textarea name='fld[" . attr($fld_line_no) . "][desc]' rows='3' cols='35' class='optin' style='width:100%'>" .
831 text($linedata['description']) . "</textarea>";
832 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][default]' value='" .
833 attr($linedata['default_value']) . "' />";
834 echo "</td>\n";
835 } else {
836 echo " <td align='center' class='optcell' >";
837 echo "<input type='text' name='fld[" . attr($fld_line_no) . "][desc]' value='" .
838 attr($linedata['description']) .
839 "' size='30' class='optin' style='width:100%' />";
840 echo "<input type='hidden' name='fld[" . attr($fld_line_no) . "][default]' value='" .
841 attr($linedata['default_value']) . "' />";
842 echo "</td>\n";
843 // if not english and showing layout labels, then show the translation of Description
844 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
845 echo "<td align='center' class='translation'>" .
846 xlt($linedata['description']) . "</td>\n";
850 // The "?" to click on for yet more field attributes.
851 echo " <td class='bold' id='querytd_" . attr($fld_line_no) . "' style='cursor:pointer;";
852 if (!empty($linedata['conditions']) || !empty($linedata['validation'])) {
853 echo "background-color:#77ff77;";
856 echo "' onclick='extShow(" . attr($fld_line_no) . ", this)' align='center' ";
857 echo "title='" . xla('Click here to view/edit more details') . "'>";
858 echo "&nbsp;?&nbsp;";
859 echo "</td>\n";
861 echo " </tr>\n";
863 // Create a floating div for the additional attributes of this field.
864 $conditions = empty($linedata['conditions']) ?
865 array(0 => array('id' => '', 'itemid' => '', 'operator' => '', 'value' => '')) :
866 unserialize($linedata['conditions']);
867 $action = empty($conditions['action']) ? 'skip' : $conditions['action'];
868 $action_value = $action == 'skip' ? '' : substr($action, 6);
870 $extra_html .= "<div id='ext_" . attr($fld_line_no) . "' " .
871 "style='position:absolute;width:750px;border:1px solid black;" .
872 "padding:2px;background-color:#cccccc;visibility:hidden;" .
873 "z-index:1000;left:-1000px;top:0px;font-size:8pt;'>\n" .
874 "<table width='100%'>\n" .
875 " <tr>\n" .
876 " <th colspan='3' align='left' class='bold'>" .
877 xlt('For') . " " . text($linedata['field_id']) . " " .
878 "<select name='fld[" . attr($fld_line_no) . "][action]' onchange='actionChanged(" . attr_js($fld_line_no) . ")'>" .
879 "<option value='skip' " . ($action == 'skip' ? 'selected' : '') . ">" . xlt('hide this field') . "</option>" .
880 "<option value='value' " . ($action != 'skip' ? 'selected' : '') . ">" . xlt('set value to') . "</option>" .
881 "</select>" .
882 "<input type='text' name='fld[" . attr($fld_line_no) . "][value]' value='" . attr($action_value) . "' size='15' />" .
883 " " . xlt('if') .
884 "</th>\n" .
885 " <th colspan='2' align='right' class='text'><input type='button' " .
886 "value='" . xla('Close') . "' onclick='extShow(" . attr_js($fld_line_no) . ", false)' />&nbsp;</th>\n" .
887 " </tr>\n" .
888 " <tr>\n" .
889 " <th align='left' class='bold'>" . xlt('Field ID') . "</th>\n" .
890 " <th align='left' class='bold'>" . xlt('List item ID') . "</th>\n" .
891 " <th align='left' class='bold'>" . xlt('Operator') . "</th>\n" .
892 " <th align='left' class='bold'>" . xlt('Value if comparing') . "</th>\n" .
893 " <th align='left' class='bold'>&nbsp;</th>\n" .
894 " </tr>\n";
895 // There may be multiple condition lines for each field.
896 foreach ($conditions as $i => $condition) {
897 if (!is_numeric($i)) {
898 continue; // skip if 'action'
900 $extra_html .=
901 " <tr>\n" .
902 " <td align='left'>\n" .
903 " <select name='fld[" . attr($fld_line_no) . "][condition_id][" . attr($i) . "]' onchange='cidChanged(" . attr_js($fld_line_no) . ", " . attr_js($i) . ")'>" .
904 genFieldOptionList($condition['id']) . " </select>\n" .
905 " </td>\n" .
906 " <td align='left'>\n" .
907 // List item choices are populated on the client side but will need the current value,
908 // so we insert a temporary option here to hold that value.
909 " <select name='fld[" . attr($fld_line_no) . "][condition_itemid][" . attr($i) . "]'><option value='" .
910 attr($condition['itemid']) . "'>...</option></select>\n" .
911 " </td>\n" .
912 " <td align='left'>\n" .
913 " <select name='fld[" . attr($fld_line_no) . "][condition_operator][" . attr($i) . "]'>\n";
914 foreach (array(
915 'eq' => xl('Equals'),
916 'ne' => xl('Does not equal'),
917 'se' => xl('Is selected'),
918 'ns' => xl('Is not selected'),
919 ) as $key => $value) {
920 $extra_html .= " <option value='" . attr($key) . "'";
921 if ($key == $condition['operator']) {
922 $extra_html .= " selected";
925 $extra_html .= ">" . text($value) . "</option>\n";
928 $extra_html .=
929 " </select>\n" .
930 " </td>\n" .
931 " <td align='left' title='" . xla('Only for comparisons') . "'>\n" .
932 " <input type='text' name='fld[" . attr($fld_line_no) . "][condition_value][" . attr($i) . "]' value='" .
933 attr($condition['value']) . "' size='15' maxlength='63' />\n" .
934 " </td>\n";
935 if (!isset($conditions[$i + 1])) {
936 $extra_html .=
937 " <td align='right' title='" . xla('Add a condition') . "'>\n" .
938 " <input type='button' value='+' onclick='extAddCondition(" . attr_js($fld_line_no) . ",this)' />\n" .
939 " </td>\n";
940 } else {
941 $extra_html .=
942 " <td align='right'>\n" .
943 " <select name='fld[" . attr($fld_line_no) . "][condition_andor][" . attr($i) . "]'>\n";
944 foreach (array(
945 'and' => xl('And'),
946 'or' => xl('Or'),
947 ) as $key => $value) {
948 $extra_html .= " <option value='" . attr($key) . "'";
949 if ($key == $condition['andor']) {
950 $extra_html .= " selected";
953 $extra_html .= ">" . text($value) . "</option>\n";
956 $extra_html .=
957 " </select>\n" .
958 " </td>\n";
961 $extra_html .=
962 " </tr>\n";
965 $extra_html .=
966 "</table>\n";
968 $extra_html .= "<table width='100%'>\n" .
969 " <tr>\n" .
970 " <td colspan='3' align='left' class='bold'>\"" . text($linedata['field_id']) . "\" " .
971 xlt('will have the following validation rules') . ":</td>\n" .
972 " </tr>\n" .
973 " <tr>\n" .
974 " <td align='left' class='bold'>" . xlt('Validation rule') . " </td>\n" .
975 " </tr>\n".
976 " <tr>\n" .
977 " <td align='left' title='" . xla('Select a validation rule') . "'>\n" .
980 " <select name='fld[" . attr($fld_line_no) . "][validation]' onchange='valChanged(" . attr_js($fld_line_no) . ")'>\n" .
981 " <option value=''";
982 if (empty($linedata['validation'])) {
983 $extra_html .= " selected";
986 $extra_html .= ">-- " . xlt('Please Select') . " --</option>";
987 foreach ($validations as $key => $value) {
988 $extra_html .= " <option value='" . attr($key) . "'";
989 if ($key == $linedata['validation']) {
990 $extra_html .= " selected";
993 $extra_html .= ">" . text($value) . "</option>\n";
996 $extra_html .="</select>\n" .
997 " </td>\n";
999 $extra_html .=
1000 "</table>\n" .
1001 "</div>\n";
1004 <html>
1006 <head>
1008 <?php Header::setupHeader(['select2']); ?>
1010 <title><?php echo xlt('Layout Editor'); ?></title>
1012 <style>
1013 .orgTable tr.head { font-size:8pt; background-color:#cccccc; }
1014 .orgTable tr.detail { font-size:8pt; }
1015 .orgTable td { font-size:8pt; }
1016 .orgTable input { font-size:8pt; }
1017 .orgTable select { font-size:8pt; }
1018 a, a:visited, a:hover { color:#0000cc; }
1019 .optcell { }
1020 .optin { background: transparent; }
1021 .group {
1022 margin: 0pt 0pt 8pt 0pt;
1023 padding :0pt;
1024 width: 100%;
1027 .group table {
1028 border-collapse: collapse;
1029 width: 100%;
1032 .orgTable .odd td {
1033 background-color: #ddddff;
1034 padding: 3px 0px 3px 0px;
1036 .orgTable .even td {
1037 background-color: #ffdddd;
1038 padding: 3px 0px 3px 0px;
1040 .help { cursor: help; }
1041 .layouts_title { font-size: 110%; }
1042 .translation {
1043 color: green;
1044 font-size:8pt;
1046 .highlight * {
1047 border: 2px solid blue;
1048 background-color: yellow;
1049 color: black;
1051 .select2-container--default .select2-selection--multiple {
1052 cursor: pointer;
1054 .select2-search__field {
1055 cursor: pointer;
1056 width: 0 !important;
1058 .select2-selection__choice {
1059 font-size: 12px;
1061 .select2-container {
1062 cursor: pointer;
1063 opacity: 0.99 !important;
1065 .select2-dropdown {
1066 opacity: 0.99 !important;
1068 .tips {
1069 display: none;
1072 </style>
1074 <script>
1075 // Helper functions for positioning the floating divs.
1076 function extGetX(elem) {
1077 var x = 0;
1078 while(elem != null) {
1079 x += elem.offsetLeft;
1080 elem = elem.offsetParent;
1082 return x;
1084 function extGetY(elem) {
1085 var y = 0;
1086 while(elem != null) {
1087 y += elem.offsetTop;
1088 elem = elem.offsetParent;
1090 return y;
1093 // Show or hide the "extras" div for a row.
1094 var extdiv = null;
1095 function extShow(lino, show) {
1096 var thisdiv = document.getElementById("ext_" + lino);
1097 if (extdiv) {
1098 extdiv.style.visibility = 'hidden';
1099 extdiv.style.left = '-1000px';
1100 extdiv.style.top = '0px';
1102 if (show && thisdiv != extdiv) {
1103 extdiv = thisdiv;
1104 var dw = window.innerWidth ? window.innerWidth - 20 : document.body.clientWidth;
1105 x = dw - extdiv.offsetWidth;
1106 if (x < 0) x = 0;
1107 var y = extGetY(show) + show.offsetHeight;
1108 extdiv.style.left = x;
1109 extdiv.style.top = y;
1110 extdiv.style.visibility = 'visible';
1112 else {
1113 extdiv = null;
1117 // Show or hide the value field for a "Set value to" condition.
1118 function actionChanged(lino) {
1119 var f = document.forms[0];
1120 var eaction = f['fld[' + lino + '][action]'];
1121 var evalue = f['fld[' + lino + '][value]'];
1122 evalue.style.display = eaction.value == 'skip' ? 'none' : '';
1125 // Add an extra condition line for the given row.
1126 function extAddCondition(lino, btnelem) {
1127 var f = document.forms[0];
1128 var i = 0;
1130 // Get index of next condition line.
1131 while (f['fld[' + lino + '][condition_id][' + i + ']']) ++i;
1132 if (i == 0) alert('f["fld[' + lino + '][condition_id][' + i + ']"]' + <?php echo xlj('not found') ?>);
1134 // Get containing <td>, <tr> and <table> nodes of the "+" button.
1135 var tdplus = btnelem.parentNode;
1136 var trelem = tdplus.parentNode;
1137 var telem = trelem.parentNode;
1139 // Replace contents of the tdplus cell.
1140 tdplus.innerHTML =
1141 "<select name='fld[" + lino + "][condition_andor][" + (i-1) + "]'>" +
1142 "<option value='and'>" + <?php echo xlj('And') ?> + "</option>" +
1143 "<option value='or' >" + <?php echo xlj('Or') ?> + "</option>" +
1144 "</select>";
1146 // Add the new row.
1147 var newtrelem = telem.insertRow(i+2);
1148 newtrelem.innerHTML =
1149 "<td align='left'>" +
1150 "<select name='fld[" + lino + "][condition_id][" + i + "]' onchange='cidChanged(" + lino + "," + i + ")'>" +
1151 <?php echo js_escape(genFieldOptionList()) ?> +
1152 "</select>" +
1153 "</td>" +
1154 "<td align='left'>" +
1155 "<select name='fld[" + lino + "][condition_itemid][" + i + "]' style='display:none' />" +
1156 "</td>" +
1157 "<td align='left'>" +
1158 "<select name='fld[" + lino + "][condition_operator][" + i + "]'>" +
1159 "<option value='eq'>" + <?php echo xlj('Equals') ?> + "</option>" +
1160 "<option value='ne'>" + <?php echo xlj('Does not equal') ?> + "</option>" +
1161 "<option value='se'>" + <?php echo xlj('Is selected') ?> + "</option>" +
1162 "<option value='ns'>" + <?php echo xlj('Is not selected') ?> + "</option>" +
1163 "</select>" +
1164 "</td>" +
1165 "<td align='left'>" +
1166 "<input type='text' name='fld[" + lino + "][condition_value][" + i + "]' value='' size='15' maxlength='63' />" +
1167 "</td>" +
1168 "<td align='right'>" +
1169 "<input type='button' value='+' onclick='extAddCondition(" + lino + ",this)' />" +
1170 "</td>";
1173 // This is called when a field ID is chosen for testing within a skip condition.
1174 // It checks to see if a corresponding list item must also be chosen for the test, and
1175 // if so then inserts the dropdown for selecting an item from the appropriate list.
1176 function setListItemOptions(lino, seq, init) {
1177 var f = document.forms[0];
1178 var target = 'fld[' + lino + '][condition_itemid][' + seq + ']';
1179 // field_id is the ID of the field that the condition will test.
1180 var field_id = f['fld[' + lino + '][condition_id][' + seq + ']'].value;
1181 if (!field_id) {
1182 f[target].options.length = 0;
1183 f[target].style.display = 'none';
1184 return;
1186 // Find the occurrence of that field in the layout.
1187 var i = 1;
1188 while (true) {
1189 var idname = 'fld[' + i + '][id]';
1190 if (!f[idname]) {
1191 alert(<?php echo xlj('Condition field not found') ?> + ': ' + field_id);
1192 return;
1194 if (f[idname].value == field_id) break;
1195 ++i;
1197 // If this is startup initialization then preserve the current value.
1198 var current = init ? f[target].value : '';
1199 f[target].options.length = 0;
1200 // Get the corresponding data type and list ID.
1201 var data_type = f['fld[' + i + '][datatype]'].value;
1202 var list_id = f['fld[' + i + '][list_id]'].value;
1203 // WARNING: If new data types are defined the following test may need enhancing.
1204 // We're getting out if the type does not generate multiple fields with different names.
1205 if (data_type != '21' && data_type != '22' && data_type != '23' && data_type != '25') {
1206 f[target].style.display = 'none';
1207 return;
1209 // OK, list item IDs do apply so go get 'em.
1210 // This happens asynchronously so the generated code needs to stand alone.
1211 f[target].style.display = '';
1212 $.getScript('layout_listitems_ajax.php' +
1213 '?listid=' + encodeURIComponent(list_id) +
1214 '&target=' + encodeURIComponent(target) +
1215 '&current=' + encodeURIComponent(current) +
1216 '&csrf_token_form=' + <?php echo js_url(collectCsrfToken()); ?>);
1219 // This is called whenever a condition's field ID selection is changed.
1220 function cidChanged(lino, seq) {
1221 changeColor(lino);
1222 setListItemOptions(lino, seq, false);
1225 // This invokes the popup to edit layout properties or add a new layout.
1226 function edit_layout_props(groupid) {
1227 var title = <?php echo xlj('Layout Properties');?>;
1228 dlgopen('edit_layout_props.php?layout_id=' + <?php echo js_url($layout_id); ?> + '&group_id=' + encodeURIComponent(groupid),
1229 '_blank', 775, 550, "", title);
1232 // callback from edit_layout_props.php:
1233 function refreshme(layout_id) {
1234 location.href = 'edit_layout.php?layout_id=' + encodeURIComponent(layout_id);
1237 // This is called whenever a validation rule field ID selection is changed.
1238 function valChanged(lino) {
1239 changeColor(lino);
1242 function changeColor(lino){
1243 var thisid = document.forms[0]['fld[' + lino + '][condition_id][0]'].value;
1244 var thisValId = document.forms[0]['fld[' + lino + '][validation]'].value;
1245 var thistd = document.getElementById("querytd_" + lino);
1246 if(thisid !='' || thisValId!='') {
1247 thistd.style.backgroundColor = '#77ff77';
1248 }else{
1249 thistd.style.backgroundColor ='';
1253 // Call this to disable the warning about unsaved changes and submit the form.
1254 function mySubmit() {
1255 somethingChanged = false;
1256 top.restoreSession();
1257 document.forms[0].submit();
1260 // User is about to do something that would discard any unsaved changes.
1261 // Return true if that is OK.
1262 function myChangeCheck() {
1263 if (somethingChanged) {
1264 if (!confirm(<?php echo xlj('You have unsaved changes. Abandon them?'); ?>)) {
1265 return false;
1267 // Do not set somethingChanged to false here because if they cancel the
1268 // action then the previously changed values will still be of interest.
1270 return true;
1273 </script>
1275 </head>
1277 <body class="body_top admin-layout">
1278 <div class="container-responsive">
1279 <form method='post' name='theform' id='theform' action='edit_layout.php'>
1280 <input type="hidden" name="csrf_token_form" value="<?php echo attr(collectCsrfToken()); ?>" />
1281 <input type="hidden" name="formaction" id="formaction" value="">
1282 <!-- elements used to identify a field to delete -->
1283 <input type="hidden" name="deletefieldid" id="deletefieldid" value="">
1284 <input type="hidden" name="deletefieldgroup" id="deletefieldgroup" value="">
1285 <!-- elements used to identify a group to delete -->
1286 <!--
1287 <input type="hidden" name="deletegroupname" id="deletegroupname" value="">
1289 <!-- elements used to change the group order -->
1290 <input type="hidden" name="movegroupname" id="movegroupname" value="">
1291 <input type="hidden" name="movedirection" id="movedirection" value="">
1292 <!-- elements used to select more than one field -->
1293 <input type="hidden" name="selectedfields" id="selectedfields" value="">
1294 <input type="hidden" id="targetgroup" name="targetgroup" value="">
1296 <div class="menubar" style='padding:5px 0;'>
1298 <b><?php echo xlt('Edit layout'); ?>:</b>&nbsp;
1299 <select name='layout_id' id='layout_id' class='form-control' style='display:inline-block;margin-bottom:5px;width:20%;'>
1300 <option value=''>-- <?php echo xlt('Select') ?> --</option>
1301 <?php
1302 $lastgroup = '';
1303 foreach ($layouts as $key => $value) {
1304 if ($value[0] != $lastgroup) {
1305 if ($lastgroup) {
1306 echo " </optgroup>\n";
1308 echo " <optgroup label='" . attr($value[0]) . "'>\n";
1309 $lastgroup = $value[0];
1311 echo " <option value='" . attr($key) . "'";
1312 if ($key == $layout_id) {
1313 echo " selected";
1315 echo ">" . text($value[1]) . "</option>\n";
1317 if ($lastgroup) {
1318 echo " </optgroup>\n";
1321 </select>
1323 <?php if ($layout_id) { ?>
1324 <input type='button' value='<?php echo xla('Layout Properties'); ?>' onclick='edit_layout_props("")' />&nbsp;
1325 <input type='button' class='addgroup' id='addgroup' value='<?php echo xla('Add Group'); ?>' />
1326 <span style="font-size:90%"> &nbsp;
1327 <input type='button' class="btn btn-danger" name='save' id='save' value='<?php echo xla('Save Changes'); ?>' /></span> &nbsp;&nbsp;
1328 <?php echo xlt('With selected:');?>
1329 <input type='button' name='deletefields' id='deletefields' value='<?php echo xla('Delete'); ?>' style="font-size:90%" disabled="disabled" />
1330 <input type='button' name='movefields' id='movefields' value='<?php echo xla('Move to...'); ?>' style="font-size:90%" disabled="disabled" />
1331 <input type='button' value='<?php echo xla('Tips'); ?>' onclick='$("#tips").toggle();' />&nbsp;
1332 <input type='button' value='<?php echo xla('Encounter Preview'); ?>' onclick='layoutLook();' />
1334 <?php } else { ?>
1335 <input type='button' value='<?php echo xla('New Layout'); ?>' onclick='edit_layout_props("")' />&nbsp;
1336 <?php } ?>
1338 <div id="tips" class="container tips"><section class="panel panel-primary">
1339 <header class="panel-heading">
1340 <h3 class="panel-title"><?php echo xlt('Usage Tips') ?></h3>
1341 </header>
1342 <div class="panel-body">
1343 <ul>
1344 <?php
1345 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>";
1346 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>";
1347 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>";
1348 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>";
1349 echo "<li>" . xlt("If a field's Data Col = 0 the data field will immediately follow its label field on the same line") . "</li>";
1350 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>";
1351 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>";
1352 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>";
1353 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>";
1354 //echo "<li>" . xlt("") . "</li>";
1355 echo "<li>" . xlt("Please see http://www.open-emr.org/wiki/index.php/LBV_Forms for more on this topic") . "</li>";
1357 </ul>
1358 <button class='btn btn-xs btn-success pull-right' onclick='$("#tips").toggle();return false;'><?php echo xlt('Dismiss')?></button>
1359 </div>
1360 </section></div></div>
1361 <?php
1362 // Load array of properties for this layout and its groups.
1363 $grparr = array();
1364 $gres = sqlStatement("SELECT * FROM layout_group_properties WHERE grp_form_id = ? " .
1365 "ORDER BY grp_group_id", array($layout_id));
1366 while ($grow = sqlFetchArray($gres)) {
1367 $grparr[$grow['grp_group_id']] = $grow;
1370 $prevgroup = "!@#asdf1234"; // an unlikely group ID
1371 $firstgroup = true; // flag indicates it's the first group to be displayed
1373 while ($row = sqlFetchArray($res)) {
1374 $group_id = $row['group_id'];
1375 if ($group_id != $prevgroup) {
1376 if ($firstgroup == false) {
1377 echo "</tbody></table></div>\n";
1378 echo "<div id='" . attr($group_id) . "' class='group'>";
1379 } else { // making first group flag useful for maintaining top fixed nav bar.
1380 echo "<div id='" . attr($group_id) . "' class='group' style='padding-top:40px'>";
1382 echo "<div class='text bold layouts_title' style='position:relative; background-color: #c9dbf2;'>";
1384 // Get the fully qualified descriptive name of this group (i.e. including ancestor names).
1385 $gdispname = '';
1386 for ($i = 1; $i <= strlen($group_id); ++$i) {
1387 if ($gdispname) {
1388 $gdispname .= ' / ';
1390 $gdispname .= $grparr[substr($group_id, 0, $i)]['grp_title'];
1392 $gmyname = $grparr[$group_id]['grp_title'];
1394 echo text($gdispname);
1396 // if not english and set to translate layout labels, then show the translation of group name
1397 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1398 echo "<span class='translation'&gt;&gt;&gt;&nbsp; " . xlt($gdispname) . "</span>";
1399 echo "&nbsp; ";
1402 echo "&nbsp; ";
1403 echo " <input type='button' class='addfield' id='addto~" . attr($group_id) . "' value='" . xla('Add Field') . "'/>";
1404 echo "&nbsp; &nbsp; ";
1405 echo " <input type='button' class='renamegroup' id='" . attr($group_id) . "~" . attr($gmyname) . "' value='" . xla('Rename Group') . "'/>";
1406 /******************************************************************
1407 echo "&nbsp; &nbsp; ";
1408 echo " <input type='button' class='deletegroup' id='" . attr($group_id) . "' value='" . xla('Delete Group') . "'/>";
1409 ******************************************************************/
1410 echo "&nbsp; &nbsp; ";
1411 echo " <input type='button' class='movegroup' id='" . attr($group_id) . "~up' value='" . xla('Move Up') . "'/>";
1412 echo "&nbsp; &nbsp; ";
1413 echo " <input type='button' class='movegroup' id='" . attr($group_id) . "~down' value='" . xla('Move Down') . "'/>";
1414 echo "&nbsp; &nbsp; ";
1415 echo "<input type='button' value='" . xla('Group Properties') . "' onclick='edit_layout_props(" . attr_js($group_id) . ")' />";
1416 echo "</div>";
1417 $firstgroup = false;
1419 <table class='table table-condensed table-striped'>
1420 <thead>
1421 <tr class='head'>
1422 <th style='width:1%'><?php echo xlt('Order'); ?></th>
1423 <th <?php echo " $lbfonly"; ?>style='width:5%'><?php echo xlt('Source'); ?></th>
1424 <th style='width:5%'><?php echo xlt('ID'); ?>&nbsp;<span class="help" title='<?php echo xla('A unique value to identify this field, not visible to the user'); ?>' >(?)</span></th>
1425 <th style='width:10%'><?php echo xlt('Label'); ?>&nbsp;<span class="help" title='<?php echo xla('The label that appears to the user on the form'); ?>' >(?)</span></th>
1426 <?php // if not english and showing layout label translations, then show translation header for title
1427 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1428 echo "<th>" . xlt('Translation')."<span class='help' title='" . xla('The translated label that will appear on the form in current language') . "'>&nbsp;(?)</span></th>";
1429 } ?>
1430 <th style='width:6%'><?php echo xlt('UOR'); ?></th>
1431 <th style='width:10%'><?php echo xlt('Data Type'); ?></th>
1432 <th style='width:1%'><?php echo xlt('Size'); ?></th>
1433 <th style='width:3%'><?php echo xlt('Max Size'); ?></th>
1434 <th style='width:10%'><?php echo xlt('List'); ?></th>
1435 <th style='width:10%'><?php echo xlt('Backup List'); ?></th>
1436 <th style='width:1%'><?php echo xlt('Label Cols'); ?></th>
1437 <th style='width:1%'><?php echo xlt('Data Cols'); ?></th>
1438 <th style='width:10%'><?php echo xlt('Options'); ?></th>
1439 <th style='width:20%'><?php echo xlt('Description'); ?></th>
1440 <?php // if not english and showing layout label translations, then show translation header for description
1441 if ($GLOBALS['translate_layout'] && $_SESSION['language_choice'] > 1) {
1442 echo "<th>" . xlt('Translation')."<span class='help' title='" . xla('The translation of description in current language')."'>&nbsp;(?)</span></th>";
1443 } ?>
1444 <th style='width:1%'><?php echo xlt('?'); ?></th>
1445 </tr>
1446 </thead>
1447 <tbody>
1449 <?php
1450 } // end if-group_name
1452 writeFieldLine($row);
1453 $prevgroup = $group_id;
1454 } // end while loop
1457 </tbody>
1458 </table>
1460 <?php echo $extra_html; ?>
1462 </form>
1464 <!-- template DIV that appears when user chooses to rename an existing group -->
1465 <div id="renamegroupdetail"
1466 style="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1467 <input type="hidden" name="renameoldgroupname" id="renameoldgroupname" value="" />
1468 <?php echo xlt('Group Name'); ?>:
1469 <input type="text" size="20" maxlength="30" name="renamegroupname" id="renamegroupname" />
1470 &nbsp;&nbsp;
1471 <?php echo xlt('Parent'); ?>:
1472 <?php echo genGroupSelector('renamegroupparent', $layout_id); ?>
1473 <br>
1474 <input type="button" class="saverenamegroup .btn-save" value="<?php echo xla('Rename Group'); ?>" />
1475 <input type="button" class="cancelrenamegroup" value="<?php echo xla('Cancel'); ?>" />
1476 </div>
1478 <!-- template DIV that appears when user chooses to add a new group -->
1479 <div id="groupdetail"
1480 style="border: 1px solid black; padding: 3px; display: none; visibility: hidden; background-color: lightgrey;">
1481 <span class='bold'>
1482 <?php echo xlt('Group Name'); ?>:
1483 <input type="text" size="20" maxlength="30" name="newgroupname" id="newgroupname" />
1484 &nbsp;&nbsp;
1485 <?php echo xlt('Parent'); ?>:
1486 <?php echo genGroupSelector('newgroupparent', $layout_id); ?>
1487 <br>
1488 <table class='table table-condensed table-striped' style="border-collapse: collapse; margin-top: 5px;">
1489 <thead>
1490 <tr class='head'>
1491 <th style='width:1%'><?php echo xlt('Order'); ?></th>
1492 <th <?php echo " $lbfonly"; ?>style='width:5%'><?php echo xlt('Source'); ?></th>
1493 <th style='width:5%'><?php echo xlt('ID'); ?>&nbsp;<span class="help" title='<?php echo xla('A unique value to identify this field, not visible to the user'); ?>' >(?)</span></th>
1494 <th style='width:10%'><?php echo xlt('Label'); ?>&nbsp;<span class="help" title='<?php echo xla('The label that appears to the user on the form'); ?>' >(?)</span></th>
1495 <th style='width:6%'><?php echo xlt('UOR'); ?></th>
1496 <th style='width:10%'><?php echo xlt('Data Type'); ?></th>
1497 <th style='width:1%'><?php echo xlt('Size'); ?></th>
1498 <th style='width:1%'><?php echo xlt('Max Size'); ?></th>
1499 <th style='width:10%'><?php echo xlt('List'); ?></th>
1500 <th style='width:10%'><?php echo xlt('Backup List'); ?></th>
1501 <th style='width:1%'><?php echo xlt('Label Cols'); ?></th>
1502 <th style='width:1%'><?php echo xlt('Data Cols'); ?></th>
1503 <th style='width:10%'><?php echo xlt('Options'); ?></th>
1504 <th style='width:20%'><?php echo xlt('Description'); ?></th>
1505 </tr>
1506 </thead>
1507 <tbody>
1508 <tr class='center'>
1509 <td ><input type="text" name="gnewseq" id="gnewseq" value="" size="2" maxlength="4"> </td>
1510 <td<?php echo " $lbfonly"; ?>>
1511 <select class='form-control' name='gnewsource' id='gnewsource'>
1512 <?php
1513 foreach ($sources as $key => $value) {
1514 echo "<option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1517 </select>
1518 </td>
1519 <td><input type="text" name="gnewid" id="gnewid" value="" size="10" maxlength="20"
1520 onclick='FieldIDClicked(this)'> </td>
1521 <td><input type="text" name="gnewtitle" id="gnewtitle" value="" size="20" maxlength="63"> </td>
1522 <td>
1523 <select class='form-control' name="gnewuor" id="gnewuor">
1524 <option value="0"><?php echo xlt('Unused'); ?></option>
1525 <option value="1" selected><?php echo xlt('Optional'); ?></option>
1526 <option value="2"><?php echo xlt('Required'); ?></option>
1527 </select>
1528 </td>
1529 <td align='center'>
1530 <select class='form-control' name='gnewdatatype' id='gnewdatatype'>
1531 <option value=''></option>
1532 <?php
1533 global $datatypes;
1534 foreach ($datatypes as $key => $value) {
1535 echo "<option value='" . attr($key) . "'>" . text($value) . "</option>";
1538 </select>
1539 </td>
1540 <td><input type="text" name="gnewlengthWidth" id="gnewlengthWidth" value="" size="1" maxlength="3" title="<?php echo xla('Width'); ?>">
1541 <input type="text" name="gnewlengthHeight" id="gnewlengthHeight" value="" size="1" maxlength="3" title="<?php echo xla('Height'); ?>"></td>
1542 <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>
1543 <td><input type="text" name="gnewlistid" id="gnewlistid" value="" size="8" maxlength="100" class="listid">
1544 <select class='form-control' name='gcontextName' id='gcontextName' style='display:none'>
1545 <?php
1546 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1547 while ($row = sqlFetchArray($res)) {
1548 echo "<option value='" . attr($row['cl_list_item_long']) . "'>" . text($row['cl_list_item_long']) . "</option>";
1551 </select>
1552 </td>
1553 <td><input type="text" name="gnewbackuplistid" id="gnewbackuplistid" value="" size="8" maxlength="100" class="listid"></td>
1554 <td><input type="text" name="gnewtitlecols" id="gnewtitlecols" value="" size="3" maxlength="3"> </td>
1555 <td><input type="text" name="gnewdatacols" id="gnewdatacols" value="" size="3" maxlength="3"> </td>
1556 <td><select name="gnewedit_options[]" id="gnewedit_options" class="typeAddons" multiple style='width:100%' value="" size="3"></select>
1557 <input type="hidden" name="gnewdefault" id="gnewdefault" value="" /> </td>
1558 <td><input type="text" name="gnewdesc" id="gnewdesc" value="" size="30"> </td>
1559 </tr>
1560 </tbody>
1561 </table>
1562 <br>
1563 <input type="button" class="savenewgroup" value='<?php echo xla('Save New Group'); ?>'>
1564 <input type="button" class="cancelnewgroup" value='<?php echo xla('Cancel'); ?>'>
1565 </span>
1566 </div>
1568 <!-- template DIV that appears when user chooses to add a new field to a group -->
1569 <div id="fielddetail" class="fielddetail" style="display: none; visibility: hidden">
1570 <input type="hidden" name="newfieldgroupid" id="newfieldgroupid" value="">
1571 <table class="table table-condensed" style="border-collapse: collapse;">
1572 <thead>
1573 <tr class='head'>
1574 <th style='width:1%'><?php echo xlt('Order'); ?></th>
1575 <th <?php echo " $lbfonly"; ?>style='width:5%'><?php echo xlt('Source'); ?></th>
1576 <th style='width:5%'><?php echo xlt('ID'); ?>&nbsp;<span class="help" title='<?php echo xla('A unique value to identify this field, not visible to the user'); ?>' >(?)</span></th>
1577 <th style='width:10%'><?php echo xlt('Label'); ?>&nbsp;<span class="help" title='<?php echo xla('The label that appears to the user on the form'); ?>' >(?)</span></th>
1578 <th style='width:6%'><?php echo xlt('UOR'); ?></th>
1579 <th style='width:10%'><?php echo xlt('Data Type'); ?></th>
1580 <th style='width:1%'><?php echo xlt('Size'); ?></th>
1581 <th style='width:1%'><?php echo xlt('Max Size'); ?></th>
1582 <th style='width:10%'><?php echo xlt('List'); ?></th>
1583 <th style='width:10%'><?php echo xlt('Backup List'); ?></th>
1584 <th style='width:1%'><?php echo xlt('Label Cols'); ?></th>
1585 <th style='width:1%'><?php echo xlt('Data Cols'); ?></th>
1586 <th style='width:10%'><?php echo xlt('Options'); ?></th>
1587 <th style='width:20%'><?php echo xlt('Description'); ?></th>
1588 </tr>
1589 </thead>
1590 <tbody>
1591 <tr class='center'>
1592 <td ><input type="text" name="newseq" id="newseq" value="" size="2" maxlength="4"> </td>
1593 <td<?php echo " $lbfonly"; ?>>
1594 <select class='form-control' name='newsource' id='newsource'>
1595 <?php
1596 foreach ($sources as $key => $value) {
1597 echo " <option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1600 </select>
1601 </td>
1602 <td ><input type="text" name="newid" id="newid" value="" size="10" maxlength="20"
1603 onclick='FieldIDClicked(this)'> </td>
1604 <td><input type="text" name="newtitle" id="newtitle" value="" size="20" maxlength="63"> </td>
1605 <td>
1606 <select class='form-control' name="newuor" id="newuor">
1607 <option value="0"><?php echo xlt('Unused'); ?></option>
1608 <option value="1" selected><?php echo xlt('Optional'); ?></option>
1609 <option value="2"><?php echo xlt('Required'); ?></option>
1610 </select>
1611 </td>
1612 <td align='center'>
1613 <select class='form-control' name='newdatatype' id='newdatatype'>
1614 <option value=''></option>
1615 <?php
1616 global $datatypes;
1617 foreach ($datatypes as $key => $value) {
1618 echo " <option value='" . attr($key) . "'>" . text($value) . "</option>\n";
1621 </select>
1622 </td>
1623 <td><input type="text" name="newlengthWidth" id="newlengthWidth" value="" size="1" maxlength="3" title="<?php echo xla('Width'); ?>">
1624 <input type="text" name="newlengthHeight" id="newlengthHeight" value="" size="1" maxlength="3" title="<?php echo xla('Height'); ?>"></td>
1625 <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>
1626 <td><input type="text" name="newlistid" id="newlistid" value="" size="8" maxlength="31" class="listid">
1627 <select class='form-control' name='contextName' id='contextName' style='display:none'>
1628 <?php
1629 $res = sqlStatement("SELECT * FROM customlists WHERE cl_list_type=2 AND cl_deleted=0");
1630 while ($row = sqlFetchArray($res)) {
1631 echo "<option value='" . attr($row['cl_list_item_long']) . "'>" . text($row['cl_list_item_long']) . "</option>";
1634 </select>
1635 </td>
1636 <td><input type="text" name="newbackuplistid" id="newbackuplistid" value="" size="8" maxlength="31" class="listid"></td>
1637 <td><input type="text" name="newtitlecols" id="newtitlecols" value="" size="3" maxlength="3"> </td>
1638 <td><input type="text" name="newdatacols" id="newdatacols" value="" size="3" maxlength="3"> </td>
1639 <td><select name="newedit_options[]" id="newedit_options" multiple class='typeAddons' style='width:100%'></select>
1640 <input type="hidden" name="newdefault" id="newdefault" value="" /> </td>
1641 <td><input type="text" name="newdesc" id="newdesc" value="" size="30"> </td>
1642 </tr>
1643 <tr>
1644 <td colspan="9">
1645 <input type="button" class="savenewfield" value='<?php echo xla('Save New Field'); ?>'>
1646 <input type="button" class="cancelnewfield" value='<?php echo xla('Cancel'); ?>'>
1647 </td>
1648 </tr>
1649 </tbody>
1650 </table>
1651 </div>
1652 </div>
1653 </body>
1655 <script>
1656 /* Field modifier objects - heading towards context based.
1657 Used by Select2 so rtl may be enabled*/
1658 <?php echo "var fldOptions = [
1659 {id: 'A',text:" . xlj('Age') . ",ctx:['4'],ctxExcp:['0']},
1660 {id: 'B',text:" . xlj('Gestational Age') . ",ctx:['4'],ctxExcp:['0']},
1661 {id: 'F',text:" . xlj('Add Time to Date') . ",ctx:['4'],ctxExcp:['0']},
1662 {id: 'C',text:" . xlj('Capitalize') . ",ctx:['0'],ctxExcp:['4','15','40']},
1663 {id: 'D',text:" . xlj('Dup Check') . "},
1664 {id: 'E',text:" . xlj('Dup Check on only Edit') . "},
1665 {id: 'W',text:" . xlj('Dup Check on only New') . "},
1666 {id: 'G',text:" . xlj('Graphable') . "},
1667 {id: 'I',text:" . xlj('Initially Open Group') . "},
1668 {id: 'J',text:" . xlj('Jump to Next Row') . "},
1669 {id: 'K',text:" . xlj('Prepend Blank Row') . "},
1670 {id: 'L',text:" . xlj('Lab Order') . "},
1671 {id: 'M',text:" . xlj('Radio Group Master') . "},
1672 {id: 'm',text:" . xlj('Radio Group Member') . "},
1673 {id: 'N',text:" . xlj('New Patient Form') . "},
1674 {id: 'O',text:" . xlj('Order Processor') . "},
1675 {id: 'P',text:" . xlj('Default to previous value') . "},
1676 {id: 'R',text:" . xlj('Distributor') . "},
1677 {id: 'T',text:" . xlj('Description is default text') . "},
1678 {id: 'U',text:" . xlj('Capitalize all') . "},
1679 {id: 'V',text:" . xlj('Vendor') . "},
1680 {id: 'X',text:" . xlj('Do Not Print') . "},
1681 {id:'grp',text:" . xlj('Stylings') . ",children:[
1682 {id: 'RS',text:" . xlj('Add Bottom Border Row') . "},
1683 {id: 'RO',text:" . xlj('Outline Entire Row') . "},
1684 {id: 'DS',text:" . xlj('Add Data Bottom Border') . "},
1685 {id: 'DO',text:" . xlj('Outline Data Col') . "},
1686 {id: 'SP',text:" . xlj('Span Entire Row') . "}
1688 {id: '0',text:" . xlj('Read Only') . "},
1689 {id: '1',text:" . xlj('Write Once') . "},
1690 {id: '2',text:" . xlj('Billing Code Descriptions') . "}];\n";
1692 // Language direction for select2
1693 echo 'var langDirection = ' . js_escape($_SESSION['language_direction']) . ';';
1696 // used when selecting a list-name for a field
1697 var selectedfield;
1699 // Support for beforeunload handler.
1700 var somethingChanged = false;
1702 // Get the next logical sequence number for a field in the specified group.
1703 // Note it guesses and uses the existing increment value.
1704 function getNextSeq(group) {
1705 var f = document.forms[0];
1706 var seq = 0;
1707 var delta = 10;
1708 for (var i = 1; true; ++i) {
1709 var gelem = f['fld[' + i + '][group]'];
1710 if (!gelem) break;
1711 if (gelem.value != group) continue;
1712 var tmp = parseInt(f['fld[' + i + '][seq]'].value);
1713 if (isNaN(tmp)) continue;
1714 if (tmp <= seq) continue;
1715 delta = tmp - seq;
1716 seq = tmp;
1718 return seq + delta;
1721 // Helper function for validating new fields.
1722 function validateNewField(idpfx) {
1723 var f = document.forms[0];
1724 var pfx = '#' + idpfx;
1725 var newid = $(pfx + "id").val();
1727 // seq must be numeric and <= 9999
1728 if (! IsNumeric($(pfx + "seq").val(), 0, 9999)) {
1729 alert(<?php echo xlj('Order must be a number between 1 and 9999'); ?>);
1730 return false;
1732 // length must be numeric and less than 999
1733 if (! IsNumeric($(pfx + "lengthWidth").val(), 0, 999)) {
1734 alert(<?php echo xlj('Size must be a number between 1 and 999'); ?>);
1735 return false;
1737 // titlecols must be numeric and less than 100
1738 if (! IsNumeric($(pfx + "titlecols").val(), 0, 999)) {
1739 alert(<?php echo xlj('LabelCols must be a number between 1 and 999'); ?>);
1740 return false;
1742 // datacols must be numeric and less than 100
1743 if (! IsNumeric($(pfx + "datacols").val(), 0, 999)) {
1744 alert(<?php echo xlj('DataCols must be a number between 1 and 999'); ?>);
1745 return false;
1747 // the id field can only have letters, numbers and underscores
1748 if ($(pfx + "id").val() == "") {
1749 alert(<?php echo xlj('ID cannot be blank'); ?>);
1750 return false;
1753 // Make sure the field ID is not duplicated.
1754 for (var j = 1; f['fld[' + j + '][id]']; ++j) {
1755 if (newid.toLowerCase() == f['fld[' + j + '][id]'].value.toLowerCase() ||
1756 newid.toLowerCase() == f['fld[' + j + '][originalid]'].value.toLowerCase())
1758 alert(<?php echo xlj('Error: Duplicated field ID'); ?> + ': ' + newid);
1759 return false;
1763 // the id field can only have letters, numbers and underscores
1764 var validid = $(pfx + "id").val().replace(/(\s|\W)/g, "_"); // match any non-word characters and replace them
1765 $(pfx + "id").val(validid);
1766 // similarly with the listid field
1767 validid = $(pfx + "listid").val().replace(/(\s|\W)/g, "_");
1768 $(pfx + "listid").val(validid);
1769 // similarly with the backuplistid field
1770 validid = $(pfx + "backuplistid").val().replace(/(\s|\W)/g, "_");
1771 $(pfx + "backuplistid").val(validid);
1773 return true;
1776 // jQuery stuff to make the page a little easier to use
1778 $(function(){
1780 $(function () {
1781 $('.typeAddons').select2({
1782 data: fldOptions,
1783 theme: 'default',
1784 multiple: true,
1785 closeOnSelect: false,
1786 width:'100%',
1787 minimumResultsForSearch: 'Infinity',
1788 containerCssClass: ':all:',
1789 allowClear: false,
1790 <?php require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?>
1793 // Populate field option selects
1794 $(function() {
1795 $('.typeAddons').each(function(i, obj) {
1796 var v = $(this).data('set')
1797 if(typeof v !== 'undefined' && v > ""){
1798 $(this).val(v).trigger("change")
1801 somethingChanged = false;
1804 $("#save").click(function() { SaveChanges(); });
1805 $("#layout_id").change(function() {
1806 if (!myChangeCheck()) {
1807 $("#layout_id").val(<?php echo js_escape($layout_id); ?>);
1808 return;
1810 mySubmit();
1812 $(".addgroup").click(function() { AddGroup(this); });
1813 $(".savenewgroup").click(function() { SaveNewGroup(this); });
1814 /******************************************************************
1815 $(".deletegroup").click(function() { DeleteGroup(this); });
1816 ******************************************************************/
1817 $(".cancelnewgroup").click(function() { CancelNewGroup(this); });
1818 $(".movegroup").click(function() { MoveGroup(this); });
1819 $(".renamegroup").click(function() { RenameGroup(this); });
1820 $(".saverenamegroup").click(function() { SaveRenameGroup(this); });
1821 $(".cancelrenamegroup").click(function() { CancelRenameGroup(this); });
1822 $(".addfield").click(function() { AddField(this); });
1823 $("#deletefields").click(function() { DeleteFields(this); });
1824 $(".selectfield").click(function() {
1825 var TRparent = $(this).parent().parent();
1826 $(TRparent).children("td").toggleClass("highlight");
1827 // disable the delete-move buttons
1828 $("#deletefields").attr("disabled", "disabled");
1829 $("#movefields").attr("disabled", "disabled");
1830 $(".selectfield").each(function(i) {
1831 // if any field is selected, enable the delete-move buttons
1832 if ($(this).prop("checked") == true) {
1833 $("#deletefields").removeAttr("disabled");
1834 $("#movefields").removeAttr("disabled");
1839 $("#movefields").click(function() { ShowGroups(this); });
1840 $(".savenewfield").click(function() { SaveNewField(this); });
1841 $(".cancelnewfield").click(function() { CancelNewField(this); });
1842 $("#newtitle").blur(function() { if ($("#newid").val() == "") $("#newid").val($("#newtitle").val()); });
1843 $("#newdatatype").change(function() { ChangeList(this.value);});
1844 $("#gnewdatatype").change(function() { ChangeListg(this.value);});
1845 $(".listid").click(function() { ShowLists(this); });
1847 // special class that skips the element
1848 $(".noselect").focus(function() { $(this).blur(); });
1850 // Save the changes made to the form
1851 var SaveChanges = function () {
1852 var f = document.forms[0];
1853 for (var i = 1; f['fld['+i+'][id]']; ++i) {
1854 var ival = f['fld['+i+'][id]'].value;
1855 for (var j = i + 1; f['fld['+j+'][id]']; ++j) {
1856 if (ival.toLowerCase() == f['fld['+j+'][id]'].value.toLowerCase() ||
1857 ival.toLowerCase() == f['fld['+j+'][originalid]'].value.toLowerCase())
1859 alert(<?php echo xlj('Error: Duplicated field ID'); ?> + ': ' + ival);
1860 return;
1864 $("#formaction").val("save");
1865 mySubmit();
1868 /****************************************************/
1869 /************ Group functions ***********************/
1870 /****************************************************/
1872 // display the 'new group' DIV
1873 var AddGroup = function(btnObj) {
1874 if (!myChangeCheck()) return;
1875 $("#save").attr("disabled", true);
1876 // show the field details DIV
1877 $('#groupdetail').css('visibility', 'visible');
1878 $('#groupdetail').css('display', 'block');
1879 $('#groupdetail').css('margin-top', '85px');
1880 $(btnObj).parent().after($("#groupdetail"));
1881 $("html, body").animate({ scrollTop: 0 }, "slow");
1882 $('#groupdetail > #newgroupname').focus();
1883 // Assign a sensible default sequence number.
1884 $('#gnewseq').val(10);
1887 // save the new group to the form
1888 var SaveNewGroup = function(btnObj) {
1889 // the group name field can only have letters, numbers, spaces and underscores
1890 // AND it cannot start with a number
1891 if ($("#newgroupname").val() == "") {
1892 alert(<?php echo xlj('Group names cannot be blank'); ?>);
1893 return false;
1895 if ($("#newgroupname").val().match(/^(\d+|\s+)/)) {
1896 alert(<?php echo xlj('Group names cannot start with numbers or spaces.'); ?>);
1897 return false;
1899 var validname = $("#newgroupname").val().replace(/[^A-za-z0-9 ]/g, "_"); // match any non-word characters and replace them
1900 $("#newgroupname").val(validname);
1902 // now, check the first group field values
1903 if (!validateNewField('gnew')) return false;
1905 // submit the form to add a new field to a specific group
1906 $("#formaction").val("addgroup");
1907 mySubmit();
1910 /******************************************************************
1911 // actually delete an entire group from the database
1912 var DeleteGroup = function(btnObj) {
1913 var parts = $(btnObj).attr("id");
1914 var groupname = parts.replace(/^\d+/, "");
1915 if (confirm(<?php echo xlj('WARNING') ?> + " - " + <?php echo xlj('This action cannot be undone.') ?> + "\n" + <?php echo xlj('Are you sure you wish to delete the entire group named'); ?> + " '" + groupname + "'?")) {
1916 // submit the form to add a new field to a specific group
1917 $("#formaction").val("deletegroup");
1918 $("#deletegroupname").val(parts);
1919 $("#theform").submit();
1922 ******************************************************************/
1924 // just hide the new field DIV
1925 var CancelNewGroup = function(btnObj) {
1926 // hide the field details DIV
1927 $('#groupdetail').css('visibility', 'hidden');
1928 $('#groupdetail').css('display', 'none');
1929 // reset the new group values to a default
1930 $('#groupdetail > #newgroupname').val("");
1931 $('#groupdetail > #newgroupparent').val("");
1932 $("#save").attr("disabled", false);
1935 // display the 'new field' DIV
1936 var MoveGroup = function(btnObj) {
1937 if (!myChangeCheck()) return;
1938 var btnid = $(btnObj).attr("id");
1939 var parts = btnid.split("~");
1940 var groupid = parts[0];
1941 var direction = parts[1];
1942 // submit the form to change group order
1943 $("#formaction").val("movegroup");
1944 $("#movegroupname").val(groupid);
1945 $("#movedirection").val(direction);
1946 mySubmit();
1949 // show the rename group DIV
1950 var RenameGroup = function(btnObj) {
1951 if (!myChangeCheck()) return;
1952 $("#save").attr("disabled", true);
1953 $('#renamegroupdetail').css('visibility', 'visible');
1954 $('#renamegroupdetail').css('display', 'block');
1955 $(btnObj).parent().append($("#renamegroupdetail"));
1956 var parts = $(btnObj).attr("id").split("~");
1957 $('#renameoldgroupname').val(parts[0]); // this is actually the existing group ID
1958 $('#renamegroupname').val(parts[1]); // the textual name of just this group
1959 var i = parts[0].length;
1960 $('[name=renamegroupparent]').val(i > 0 ? parts[0].substr(0, i-1) : ''); // parent ID
1963 // save the new group to the form
1964 var SaveRenameGroup = function(btnObj) {
1965 // the group name field can only have letters, numbers, spaces and underscores
1966 // AND it cannot start with a number
1967 if ($("#renamegroupname").val().match(/^\d+/)) {
1968 alert(<?php echo xlj('Group names cannot start with numbers.'); ?>);
1969 return false;
1971 var validname = $("#renamegroupname").val().replace(/[^A-za-z0-9 ]/g, "_"); // match any non-word characters and replace them
1972 $("#renamegroupname").val(validname);
1974 // submit the form to add a new field to a specific group
1975 $("#formaction").val("renamegroup");
1976 mySubmit();
1979 // just hide the new field DIV
1980 var CancelRenameGroup = function(btnObj) {
1981 // hide the field details DIV
1982 $('#renamegroupdetail').css('visibility', 'hidden');
1983 $('#renamegroupdetail').css('display', 'none');
1984 // reset the rename group values to a default
1985 $('#renameoldgroupname').val("");
1986 $('#renamegroupname').val("");
1987 $('#renamegroupparent').val("");
1990 /****************************************************/
1991 /************ Field functions ***********************/
1992 /****************************************************/
1994 // display the 'new field' DIV
1995 var AddField = function(btnObj) {
1996 if (!myChangeCheck()) return;
1997 $("#save").attr("disabled", true);
1998 // update the fieldgroup value to be the groupid
1999 var btnid = $(btnObj).attr("id");
2000 var parts = btnid.split("~");
2001 var groupid = parts[1];
2002 $('#fielddetail > #newfieldgroupid').attr('value', groupid);
2003 // show the field details DIV
2004 $('#fielddetail').css('visibility', 'visible');
2005 $('#fielddetail').css('display', 'block');
2006 $(btnObj).parent().append($("#fielddetail"));
2007 // Assign a sensible default sequence number.
2008 $('#newseq').val(getNextSeq(groupid));
2011 var DeleteFields = function(btnObj) {
2012 if (!myChangeCheck()) return;
2013 if (confirm(<?php echo xlj('WARNING'); ?> + " - " + <?php echo xlj('This action cannot be undone.'); ?> + '\n' + <?php echo xlj('Are you sure you wish to delete the selected fields?'); ?>)) {
2014 var delim = "";
2015 $(".selectfield").each(function(i) {
2016 // build a list of selected field names to be moved
2017 if ($(this).prop("checked") == true) {
2018 var parts = this.id.split("~");
2019 var currval = $("#selectedfields").val();
2020 $("#selectedfields").val(currval+delim+parts[1]);
2021 delim = " ";
2024 // submit the form to delete the field(s)
2025 $("#formaction").val("deletefields");
2026 mySubmit();
2030 // save the new field to the form
2031 var SaveNewField = function(btnObj) {
2032 // check the new field values for correct formatting
2033 if (!validateNewField('new')) return false;
2035 // submit the form to add a new field to a specific group
2036 $("#formaction").val("addfield");
2037 mySubmit();
2040 // just hide the new field DIV
2041 var CancelNewField = function(btnObj) {
2042 // hide the field details DIV
2043 $('#fielddetail').css('visibility', 'hidden');
2044 $('#fielddetail').css('display', 'none');
2045 // reset the new field values to a default
2046 ResetNewFieldValues();
2047 $("#save").attr("disabled", false);
2050 // show the popup choice of lists
2051 var ShowLists = function(btnObj) {
2052 var title = <?php echo xlj('Select List');?>;
2053 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=lists',"_blank", 850, 750, "", title);
2054 selectedfield = btnObj;
2057 // show the popup choice of groups
2058 var ShowGroups = function(btnObj) {
2059 if (!myChangeCheck()) return;
2060 var title = <?php echo xlj('Select Group');?>;
2061 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=groups&layout_id=' + <?php echo js_url($layout_id); ?>,
2062 "_blank",850, 600,"", title);
2065 // Show context DD for NationNotes
2066 var ChangeList = function(btnObj){
2067 if(btnObj==34){
2068 $('#newlistid').hide();
2069 $('#contextName').show();
2071 else{
2072 $('#newlistid').show();
2073 $('#contextName').hide();
2076 var ChangeListg = function(btnObj){
2077 if(btnObj==34){
2078 $('#gnewlistid').hide();
2079 $('#gcontextName').show();
2081 else{
2082 $('#gnewlistid').show();
2083 $('#gcontextName').hide();
2087 // Initialize list item selectors and value field visibilities in skip conditions.
2088 var f = document.forms[0];
2089 for (var lino = 1; f['fld[' + lino + '][id]']; ++lino) {
2090 for (var seq = 0; f['fld[' + lino + '][condition_itemid][' + seq + ']']; ++seq) {
2091 setListItemOptions(lino, seq, true);
2093 actionChanged(lino);
2096 // Support for beforeunload handler.
2097 $('tbody input, tbody select, tbody textarea').not('.selectfield').change(function() {
2098 somethingChanged = true;
2100 window.addEventListener("beforeunload", function (e) {
2101 if (somethingChanged && !top.timed_out) {
2102 var msg = <?php echo xlj('You have unsaved changes.'); ?>;
2103 e.returnValue = msg; // Gecko, Trident, Chrome 34+
2104 return msg; // Gecko, WebKit, Chrome <34
2108 }); /* Ready Done */
2110 function layoutLook(){
2111 var form = <?php echo js_escape($layout_id);?>;
2112 var btnName = <?php echo xlj('Back To Editor');?>;
2113 var url = "../patient_file/encounter/view_form.php?isShow&id=0&formname=" + encodeURIComponent(form);
2114 var title = <?php echo xlj('LBF Encounter Form Preview');?>;
2115 dlgopen(url, '_blank', 1250, 800, "", title);
2116 return false;
2119 function NationNotesContext(lineitem, val) {
2120 // Check if function is needed.
2121 if (!document.getElementById("fld[" + lineitem + "][contextName]") || !document.getElementById("fld[" + lineitem + "][list_id]")) {
2122 return false; // these elements don't exist yet so do nothing.
2124 if (val == 34) {
2125 document.getElementById("fld[" + lineitem + "][contextName]").style.display = '';
2126 document.getElementById("fld[" + lineitem + "][list_id]").style.display = 'none';
2127 document.getElementById("fld[" + lineitem + "][list_id]").value = '';
2129 else {
2130 document.getElementById("fld[" + lineitem + "][list_id]").style.display = '';
2131 document.getElementById("fld[" + lineitem + "][contextName]").style.display = 'none';
2132 document.getElementById("fld[" + lineitem + "][list_id]").value = '';
2136 function SetList(listid) {
2137 $(selectedfield).val(listid);
2140 //////////////////////////////////////////////////////////////////////
2141 // The following supports the field ID selection pop-up.
2142 //////////////////////////////////////////////////////////////////////
2144 var fieldselectfield;
2146 function elemFromPart(part) {
2147 var ename = fieldselectfield.name;
2148 // ename is like one of the following:
2149 // fld[$fld_line_no][id]
2150 // gnewid
2151 // newid
2152 // and "part" is what we substitute for the "id" part.
2153 var i = ename.lastIndexOf('id');
2154 ename = ename.substr(0, i) + part + ename.substr(i+2);
2155 return document.forms[0][ename];
2158 function FieldIDClicked(elem) {
2159 <?php if (substr($layout_id, 0, 3) == 'LBF') { ?>
2160 fieldselectfield = elem;
2161 var srcval = elemFromPart('source').value;
2162 // If the field ID is for the local form, allow direct entry.
2163 if (srcval == 'F') return;
2164 // Otherwise pop up the selection window.
2165 var title = <?php echo xlj('Select Field');?>;
2166 dlgopen('../patient_file/encounter/find_code_dynamic.php?what=fields&source='
2167 + encodeURIComponent(srcval), "_blank", 700, 600, "", title);
2168 <?php } ?>
2171 function SetField(field_id, title, data_type, uor, fld_length, max_length,
2172 list_id, titlecols, datacols, edit_options, description, fld_rows)
2174 fieldselectfield.value = field_id;
2175 elemFromPart('title' ).value = title;
2176 elemFromPart('datatype' ).value = data_type;
2177 elemFromPart('uor' ).value = uor;
2178 elemFromPart('lengthWidth' ).value = fld_length;
2179 elemFromPart('maxSize' ).value = max_length;
2180 elemFromPart('list_id' ).value = list_id;
2181 elemFromPart('titlecols' ).value = titlecols;
2182 elemFromPart('datacols' ).value = datacols;
2183 elemFromPart('edit_options').value = edit_options;
2184 elemFromPart('desc' ).value = description;
2185 elemFromPart('lengthHeight').value = fld_rows;
2188 //////////////////////////////////////////////////////////////////////
2189 // End code for field ID selection pop-up.
2190 //////////////////////////////////////////////////////////////////////
2192 /* this is called after the user chooses a new group from the popup window
2193 * it will submit the page so the selected fields can be moved into
2194 * the target group
2196 function MoveFields(targetgroup) {
2197 $("#targetgroup").val(targetgroup);
2198 var delim = "";
2199 $(".selectfield").each(function(i) {
2200 // build a list of selected field names to be moved
2201 if ($(this).prop("checked") == true) {
2202 var parts = this.id.split("~");
2203 var currval = $("#selectedfields").val();
2204 $("#selectedfields").val(currval+delim+parts[1]);
2205 delim = " ";
2208 $("#formaction").val("movefields");
2209 mySubmit();
2212 // set the new-field values to a default state
2213 function ResetNewFieldValues () {
2214 $("#newseq").val("");
2215 $("#newsource").val("");
2216 $("#newid").val("");
2217 $("#newtitle").val("");
2218 $("#newuor").val(1);
2219 $("#newlengthWidth").val("");
2220 $("#newlengthHeight").val("");
2221 $("#newmaxSize").val("");
2222 $("#newdatatype").val("");
2223 $("#newlistid").val("");
2224 $("#newbackuplistid").val("");
2225 $("#newtitlecols").val("");
2226 $("#newdatacols").val("");
2227 $("#newedit_options").val("");
2228 $("#newdefault").val("");
2229 $("#newdesc").val("");
2232 // is value an integer and between min and max
2233 function IsNumeric(value, min, max) {
2234 if (value == "" || value == null) return false;
2235 if (! IsN(value) ||
2236 parseInt(value) < min ||
2237 parseInt(value) > max)
2238 return false;
2240 return true;
2243 /****************************************************/
2244 /****************************************************/
2245 /****************************************************/
2247 // tell if num is an Integer
2248 function IsN(num) { return !/\D/.test(num); }
2250 </script>
2252 </html>