Slimmed down version of class OemrUI - Take 4 (#2044)
[openemr.git] / library / oeUI / src / OemrUI.php
blob6588118a6fc88754ae3916188c33fa0af919dd7d
1 <?php
2 /**
3 * OemrUI class.
5 * @package OpenEMR
6 * @link http://www.open-emr.org
7 * @author Ranganath Pathak <pathak@scrs1.org>
8 * @copyright Copyright (c) 2018 Ranganath Pathak <pathak@scrs1.org>
9 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
11 namespace OpenEMR\OeUI;
13 use OpenEMR\Core\Header;
15 Header::setupHeader(['jquery-ui', 'jquery-ui-base', 'no_jquery', 'no_bootstrap', 'no_fontawesome', 'no_main-theme', 'no_textformat', 'no_dialog' ]);
17 class OemrUI
19 private $action;
20 private $action_bot_js;
21 private $action_href;
22 private $action_icon;
23 private $action_title;
24 private $action_top_js;
25 private $arrAction;
26 private $arrexpandIcon;
27 private $arrFiles;
28 private $arrOeUiSettings;
29 private $arrow_direction;
30 private $close;
31 private $collectToken;
32 private $container;
33 private $contractTitle;
34 private $current_state;
35 private $display_help_icon;
36 private $expand_icon_class;
37 private $expand_title;
38 private $expandable;
39 private $expandable_icon;
40 private $expandTitle;
41 private $header_expand_js;
42 private $heading;
43 private $help_file;
44 private $help_icon;
45 private $help_modal;
46 private $jquery_draggable;
47 private $modal_body;
48 private $print;
49 private $target;
50 private $web_root;
52 /**
53 * Create the html string that will display the formatted heading with selected icons - expandable,
54 * action and help and generate the html code for the help modal and output all the jQuery needed to make it work.
56 * @param array $arrOeUiSettings is an associative array that contains 9 elements, string 'heading_title',
57 * int|bool 'include_patient_name', int|bool 'expandable', array 'expandable_files', string 'action', string 'action_title',
58 * string 'action_href', int|bool 'show_help_icon' and string 'help_file_name'.
59 * The int|bool 'current_state' (expanded = 1, centered = 0) value is obtained from function collectAndOrganizeExpandSetting(array("")),
60 * this function needs an indexed array as an argument (array ('expandable_files')) that contains the file name
61 * of the current file as the first element, the name of any other file that needs to open in a similar state
62 * needs to be included in this array,all names must be unique and have a '_xpd' suffix.
63 * It will be used to generate up to 4 values - string $heading, string $expandable_icon, string $action_icon and string $help_icon
64 * that will form the html string used to output the formatted heading of the page.
65 * If a feature is not required set the corresponding element in the array to an empty string
67 public function __construct($arrOeUiSettings = array())
69 $this->heading = ($arrOeUiSettings['include_patient_name'] && !empty($arrOeUiSettings['heading_title']))? $arrOeUiSettings['heading_title'] . " - " . getPatientNameFirstLast($_SESSION['pid']):$arrOeUiSettings['heading_title'];
70 $this->expandable = $arrOeUiSettings['expandable'];
71 $this->arrFiles = $arrOeUiSettings['expandable_files'];
72 $this->arrAction = array($arrOeUiSettings['action'], $arrOeUiSettings['action_title'], $arrOeUiSettings['action_href']);
73 $this->display_help_icon = $arrOeUiSettings['show_help_icon'];
74 $this->help_file = $arrOeUiSettings['help_file_name'];
75 if ($arrOeUiSettings['expandable'] && $arrOeUiSettings['expandable_files']) {
76 $this->current_state = collectAndOrganizeExpandSetting($arrOeUiSettings['expandable_files']);
78 echo "\r\n<script src='" . $GLOBALS['webroot'] . "/library/js/oeUI/universalTooltip.js?v=" . $v_js_includes. "'></script>\r\n";
81 /**
82 * Creates the html string that will display the formatted heading with selected icons - expandable, action and help.
84 * @return array containing string $heading - the formatted html string of the actual heading and string $container
85 * - the value of the container class 'container' or 'container-fluid'
88 public function pageHeading()
90 $heading = text($this->heading);
91 if (!empty($heading)) {
92 $arrexpandIcon = $this->expandIcon();// returns and array containing expandable icon string and container class string
93 $action_icon = $this->actionIcon();
94 $help_icon = $this->helpIcon();
95 $expandable_icon = $arrexpandIcon[0];
96 $heading = "<h2>$heading $expandable_icon $action_icon $help_icon</h2>";
97 } else {
98 $heading = "<h2>" . xlt("Please supply a heading") . " <i class='fa fa-smile-o' aria-hidden='true'></i></h2>";
100 return $heading;
104 * Creates the html string that will display the formatted expandable icon - fa-expand or fa-compress.
106 * @param $expandable - int|bool - whether form is expandable or not and $current_state int|bool - the current state of the form
108 * @return array containing string $expandable_icon - the formatted html string of the expand icon and string
109 * $container - the value of the container class 'container' or 'container-fluid'
112 private function expandIcon($expandable = '', $current_state = '')
114 $current_state = $this->current_state;
115 $expandable = $this->expandable;
117 if ($current_state) {
118 $container = 'container-fluid';
119 $expand_title = xl('Click to Contract and set to henceforth open in Centered mode');
120 $expand_icon_class = 'fa-compress oe-center';
121 } else {
122 $container = 'container';
123 $expand_title = xl('Click to Expand and set to henceforth open in Expanded mode');
124 $expand_icon_class = 'fa-expand oe-expand';
126 if ($expandable) {
127 $expandable_icon = "<i id='exp_cont_icon' class='oe-superscript-small expand_contract fa " . attr($expand_icon_class) . "'" . " title='" . attr($expand_title) . "'
128 aria-hidden='true'></i>";
130 return array($expandable_icon, $container);
134 * Will return the container class value either 'container' or 'container-fluid'
136 * @return string $container that will reflect the current state of the page i.e. expanded = 'container-fluid' or centered = 'container'
138 public function oeContainer()
140 $arrexpandIcon = $this->expandIcon();
141 $container = $arrexpandIcon[1] ? $arrexpandIcon[1]:'container';
142 return $container;
146 * Creates the html string that will display the formatted action/re-direction icon - for conceal, reveal, search, reset, link and back.
148 * @param array $arrAction has 3 elements - string - type of action, string - optional title to be used in tooltip
149 * and string - the file name or url to be redirected to, only the 3 re-directions reset, link or back need a href value
150 * the 3 actions conceal, reveal, search will only use the default title strings
152 * @return string $action_icon that will output the action icon html string
155 private function actionIcon($arrAction = array())
157 $arrAction = $this->arrAction;
158 if ($arrAction) {
159 $action = $arrAction[0];
160 $action_title = $arrAction[1];
161 $action_href = $arrAction[2];
163 $action_href = ($action_href) ? $action_href : "#";
164 switch ($action) {
165 case "reset":
166 $action_title = ($action_title) ? $action_title : xl("Reset");
167 $action_icon = "<a href='" . attr($action_href) ."' onclick='top.restoreSession()'><i id='advanced-action' class='fa fa-undo fa-2x small' title='" . attr($action_title) ."' aria-hidden='true'></i></a>";
168 break;
169 case "conceal":
170 $action_title = xl("Click to Hide"); // default needed for jQuery to function
171 $action_icon = "<i id='show_hide' class='fa fa-2x small fa-eye-slash' title='" . attr($action_title) . "'></i>";
172 break;
173 case "reveal":
174 $action_title = xl("Click to Show"); // default needed for jQuery to function
175 $action_icon = "<i id='show_hide' class='fa fa-2x small fa-eye' title='" . attr($action_title) . "'></i>";
176 break;
177 case "search":
178 $action_title = xl("Click to show search"); // default needed for jQuery to function
179 $action_icon = "<i id='show_hide' class='fa fa-search-plus fa-2x small' title='" . attr($action_title) . "'></i>";
180 break;
181 case "link":
182 if (strpos($action_href, 'http') !== false) {
183 $target = '_blank';
184 } else {
185 $target = '_self';
187 $action_title = ($action_title) ? $action_title : xl("Click to go to page");
188 $action_icon = "<a href='" . attr($action_href) . "' target = '" .attr($target)."' onclick='top.restoreSession()'><i id='advanced-action' class='fa fa-external-link fa-2x small' title='" . attr($action_title) ."' aria-hidden='true'></i></a>";
189 break;
190 case "back":
191 $action_title = ($action_title) ? $action_title : xl("Go Back");
192 if ($_SESSION ['language_direction'] == 'ltr') {
193 $arrow_direction = 'fa-arrow-circle-left';
194 } elseif ($_SESSION ['language_direction'] == 'rtl') {
195 $arrow_direction = 'fa-arrow-circle-right';
197 $action_icon = "<a href='" . attr($action_href) ."' onclick='top.restoreSession()'><i id='advanced-action' class='fa " . attr($arrow_direction) . " fa-2x small' title='" . attr($action_title) ."' aria-hidden='true'></i></a>";
198 break;
199 default:
200 $action_icon = '';
202 return $action_icon;
206 * Creates the html string that will display the formatted help icon - fa-question-circle.
208 * @param int|bool $display_help_icon
210 * @return string $help_icon that will output the help icon html string
213 private function helpIcon($display_help_icon = '')
215 $display_help_icon = $this->display_help_icon;
216 if ($display_help_icon) {
217 if ($_SESSION ['language_direction'] == 'ltr') {
218 $help_icon_title = xl("To enable help - Go to the User Name on top right > Settings > Features > Enable Help Modal");
219 } elseif ($_SESSION ['language_direction'] == 'rtl') {
220 $help_icon_title = xl("To enable help - Go to the User Name on top left > Settings > Features > Enable Help Modal");
222 if ($GLOBALS['enable_help'] == 1) {
223 $help_icon = '<a class="oe-pull-away oe-help-redirect" data-target="#myModal" data-toggle="modal" href="#" id="help-href" name="help-href" style="color:#676666" title="' . xla("Click to view Help") . '"><i class="fa fa-question-circle" aria-hidden="true"></i></a>';
224 } elseif ($GLOBALS['enable_help'] == 2) {
225 $help_icon = '<a class="oe-pull-away oe-help-redirect" data-target="#myModal" data-toggle="modal" href="#" id="help-href" name="help-href" style="color:#DCD6D0 !Important" title="' . attr($help_icon_title) . '"><i class="fa fa-question-circle" aria-hidden="true"></i></a>';
226 } elseif ($GLOBALS['enable_help'] == 0) {
227 $help_icon = '';
230 return $help_icon;
234 * Output the help modal html along with the jQuery to make it work.
236 * $param string $help_file - name of the help file to be displayed, must exists in Documentation/help_files
237 * will echo the entire html string of the help modal and the jQuery, needs to be used as the first line after the container div
239 * @return void
242 private function helpFileModal($help_file = '')
244 $help_file = $this->help_file;
245 $close = xla("Close");
246 $print = xla("Print");
247 if ($help_file) {
248 $help_file = attr($help_file);
249 $help_file = $GLOBALS['webroot']."/Documentation/help_files/$help_file";
250 $modal_body = "<iframe src=\"$help_file\" id='targetiframe' style='height:100%; width:100%; overflow-x: hidden; border:none'
251 allowtransparency='true'></iframe>";
252 } else {
253 $modal_body = "<h3> <i class='fa fa-exclamation-triangle oe-text-red' aria-hidden='true'></i> " . xlt("Check if a help file exists for this page in") . " " . text("Documentation/help_files") . ".<br><br>" . xlt("Then pass it's name as a value to the element" ." " . text("'help_file_name'") . " " . "in the associative array") . " " . text("\$arrOeUiSettings"). ".<br><br>" . xlt("If the help file does not exist create one and place it in") . " " . text("Documentation/help_files") . ".<br>" . "</h3>";
255 $help_modal = <<<HELP
256 <div class="row">
257 <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
258 <div class="modal-dialog modal-lg">
259 <div class="modal-content oe-modal-content" style="height:700px">
260 <div class="modal-header clearfix">
261 <button type="button" class="close" data-dismiss="modal" aria-label="$close">
262 <span aria-hidden="true" style="color:#000000; font-size:1.5em;">×</span></button>
263 </div>
264 <div class="modal-body" style="height:80%;">
265 $modal_body
266 </div>
267 <div class="modal-footer" style="margin-top:0px;">
268 <button class="btn btn-link btn-cancel oe-pull-away" data-dismiss="modal" type="button">$close</button>
269 <!--<button class="btn btn-default btn-print oe-pull-away" data-dismiss="modal" id="print-help-href" type="button">$print</button>-->
270 </div>
271 </div>
272 </div>
273 </div>
274 </div>
275 HELP;
276 echo $help_modal. "\r\n";
278 $jquery_draggable = <<<JQD
279 <script>
280 // Jquery draggable
281 $('.modal-dialog').draggable({
282 handle: ".modal-header, .modal-footer"
284 $( ".modal-content" ).resizable({
285 aspectRatio: true,
286 minHeight: 300,
287 minWidth: 300
289 var helpTitle = $('#help-href').prop('title');
290 $('#myModal').on('hidden.bs.modal', function (e) {
291 $('#help-href').prop('title', '');
293 $('#help-href').focus( function() {
294 $('#help-href').prop('title', helpTitle);
296 </script>
297 JQD;
298 echo $jquery_draggable. "\r\n";
299 return;
303 * Generates the jQuery for the form to toggle between 'expanded' and 'centered' states.
305 * @param array $arrFiles - that contains the files names that need to be toggled between 'expanded' and 'centered' states
306 * will generate the jQuery that will be outputted on the page by function oeBelowContainerDiv()
308 * @return void
311 private function headerExpandJs($arrFiles = array())
313 $expandTitle = xlj("Click to Contract and set to henceforth open in Centered mode");
314 $contractTitle = xlj("Click to Expand and set to henceforth open in Expanded mode");
315 $arrFiles = json_encode($this->arrFiles);
316 $web_root = $GLOBALS['webroot'];
317 $collectToken = js_escape(collectCsrfToken());
318 $header_expand_js = <<<EXP
319 <script>
320 $(document).ready(function () {
321 $('.expand_contract').click(function () {
322 var elementTitle;
323 var expandTitle = {$expandTitle};
324 var contractTitle = {$contractTitle};
325 var arrFiles = {$arrFiles};
326 if ($(this).is('.oe-expand')) {
327 elementTitle = expandTitle;
328 $(this).toggleClass('fa-expand fa-compress');
329 $(this).toggleClass('oe-expand oe-center');
330 $('#container_div').toggleClass('container container-fluid');
331 if ($(arrFiles).length) {
332 $.each(arrFiles, function (index, value) {
334 $.post(
335 "{$web_root}/library/ajax/user_settings.php",
337 target: arrFiles[index].trim(),
338 setting: 1,
339 csrf_token_form: {$collectToken}
344 } else if ($(this).is('.oe-center')) {
345 elementTitle = contractTitle;
346 $(this).toggleClass('fa-compress fa-expand');
347 $(this).toggleClass('oe-center oe-expand');
348 $('#container_div').toggleClass('container-fluid container');
349 if ($(arrFiles).length) {
350 $.each(arrFiles, function (index, value) {
351 $.post(
352 "{$web_root}/library/ajax/user_settings.php",
354 target: arrFiles[index].trim(),
355 setting: 0,
356 csrf_token_form: {$collectToken}
362 $(this).prop('title', elementTitle);
365 </script>
366 EXP;
367 echo $header_expand_js ."\r\n";
368 return;
372 * Generates the jQuery to enable an element to toggle between hidden and revealed states.
374 * @param array $arrAction - first element contains the string for type of action - needed only for actions search, reveal and conceal
375 * will generate the jQuery that will be outputted on the page by function oeBelowContainerDiv()
377 * @return void
380 private function headerActionJs($arrAction = array())
382 $arrAction = $this->arrAction;
383 $action_top_js = <<<SHWTOP
384 <script>
385 $(document).ready(function () {
386 $('#show_hide').click(function () {
387 var elementTitle = '';
388 SHWTOP;
389 echo $action_top_js ."\r\n";
391 if ($arrAction[0] == 'search') {
392 echo "var showTitle = " . xlj('Click to show search') . "\r\n;";
393 echo "var hideTitle = " . xlj('Click to hide search') . "\r\n;";
394 } elseif ($arrAction[0] == 'reveal' || $arrAction[0] == 'conceal') {
395 echo "var hideTitle = " . xlj('Click to Hide') . "\r\n;";
396 echo "var showTitle = " . xlj('Click to Show') . "\r\n;";
399 if ($arrAction[0] == 'search') {
400 echo "$(this).toggleClass('fa-search-plus fa-search-minus'); \r\n";
401 } elseif ($arrAction[0] == 'reveal') {
402 echo "$(this).toggleClass('fa-eye fa-eye-slash'); \r\n";
403 } elseif ($arrAction[0] == 'conceal') {
404 echo "$(this).toggleClass('fa-eye-slash fa-eye'); \r\n";
407 $action_bot_js = <<<SHWBOT
408 $('.hideaway').toggle(500);
409 if ($(this).is('.fa-eye') || $(this).is('.fa-search-plus')) {
410 elementTitle = showTitle;
411 } else if ($(this).is('.fa-eye-slash') || $(this).is('.fa-search-minus')) {
412 elementTitle = hideTitle;
414 $(this).prop('title', elementTitle);
417 </script>
418 SHWBOT;
419 echo $action_bot_js . "\r\n";
420 return;
424 * Output the help modal html with needed jQuery, jQuery to enable an element to toggle between 'hidden' and 'revealed states'
425 * and/or 'expand' and 'centered' states.
427 * based on the values in the associative array $arrOeUiSettings the relevant code will be outputted to the page
428 * for consistency always call this function just below the container div on the page
430 * @return void
433 public function oeBelowContainerDiv()
435 $this->display_help_icon ? $this->helpFileModal() : '';
436 $this->expandable ? $this->headerExpandJs() : '';
437 $this->arrAction[0] ? $this->headerActionJs() : '';
438 return;