2 [-*********************************************************************************-]
3 [-* Copyright (C)
2005-
2006 Rod Roark
<rod@sunsetsystems.com
> and others *-]
4 [-* Copyright (C)
2008 CHEMED (Nethanel Vilensky)
<techsupport@chemedhealth.org
> *-]
6 [-* This program is free software; you can redistribute it and/or *-]
7 [-* modify it under the terms of the GNU General Public License *-]
8 [-* as published by the Free Software Foundation; either version
2 *-]
9 [-* of the License, or (at your option) any later version. *-]
10 [-*********************************************************************************-]
12 [-if $PRINT_VIEW ==
1-]
13 [-* The new calendar interface is not printed correctly by Firefox (because of abs. positioned DOM elements) *-]
14 [-* so we have to use the older interface instead *-]
15 [-include
file=
"$TPL_NAME/views/day/orig_default.html"-]
18 [-config_load
file=
"default.conf"-]
19 [-*Load the Language Definitions*-]
20 [-config_load
file=
"lang.$USER_LANG"-]
21 [-include
file=
"$TPL_NAME/views/header.html"-]
22 [-* we want to include out stylesheet for this view*-]
23 [-fetch
file=
"$TPL_STYLE_PATH/day.css" assign=
"css"-]
27 [-include
file=
"$TPL_NAME/views/global/navigation.html"-]
29 [-assign
var=
"dayname" value=$DATE|date_format:
"%w"-]
30 [-assign
var=
"day" value=$DATE|date_format:
"%d"|string_format:
"%1d"-]
31 [-assign
var=
"month" value=$DATE|date_format:
"%m"|string_format:
"%1d"-]
32 [-assign
var=
"year" value=$DATE|date_format:
"%Y"|string_format:
"%4d"-]
34 [-pc_sort_events
var=
"S_EVENTS" sort=
"time" order=
"asc" value=$A_EVENTS-]
36 <div class='cal_labels'
> [-* START Column labels *-]
37 [-foreach from=$providers item=provider-]
38 <div class='cal_column_line_label'
></div>
39 <div class='cal_column_label'
>[-$provider.lname-]
</div>
41 </div> [-* END Column labels *-]
44 <div class='cal_container'
> [-* Main scrollable container *-]
48 //Used for sorting the event later
49 function compareEvents($a,$b) {
50 $start_a = $a['start_slot'];
51 $start_b = $b['start_slot'];
52 $end_a = $a['end_slot'];
53 $end_b = $b['end_slot'];
54 $dur_a = $a['data']['duration'];
55 $dur_b = $b['data']['duration'];
56 $cat_a = $a['data']['catid'];
57 $cat_b = $b['data']['catid'];
59 //IN-OUT events are always the lowest in the list and show up right-most in the UI
60 if (($cat_a == '
2') || ($cat_a == '
3') || ($cat_a == '
4') || ($cat_a == '
8') || ($cat_a == '
11')) {
63 if (($cat_b == '
2') || ($cat_b == '
3') || ($cat_b == '
4') || ($cat_b == '
8') || ($cat_b == '
11')) {
67 if (($start_a == $start_b) &&
69 ($dur_a == $dur_b)) {return
0;} //Events are alike
71 if ($start_a == $start_b) { //Events start together
72 if ($dur_a != $dur_b) { //Simply sort by duration
73 return ($dur_a
> $dur_b) ? -
1 :
1;
79 if ($start_a < $start_b) { //a starts earlier than b
80 if ($end_a
>= $end_b) { //events share slots
81 if ($dur_a != $dur_b) { //Simply sort by duration
82 return ($dur_a
> $dur_b) ? -
1 :
1;
86 } else { //events do not share slots and $a is earlier than $b
91 if ($start_b < $start_a) { //b starts earlier than a
92 if ($end_b
>= $end_a) { //events share slots
93 if ($dur_a != $dur_b) { //Simply sort by duration
94 return ($dur_a
> $dur_b) ? -
1 :
1;
98 } else { //events do not share slots and $b is earlier than $a
107 ------------------------ <= $calendar_width =
> -------------------------------------------
108 |<= $line_label_width =
> | <= $column_width =
> ||... |... |
109 ------------------------------------------------------------------------------------------
110 |... | ... ||... |... |
111 ------------------------------------------------------------------------------------------
113 In a couple of places I am adding +
1 to sizes. This is to account for extra
1px wide border around elements.
116 $day_start_y =
30; //Used for multiday display
118 $start_hour = $GLOBALS['schedule_start'];
119 $end_hour = $GLOBALS['schedule_end'];
121 $slot_minutes = $GLOBALS['calendar_interval'];
123 if ($PRINT_VIEW !=
1) {
124 $container_width = $_SESSION['pc_framewidth'] -
20;
126 $container_width =
900; //Make it fit to a landscape letter-sized paper
131 $line_label_width =
40;
132 $scrollbar_width =
30;
134 $calendar_width = $container_width - $scrollbar_width;
136 $columns = count($providers);
137 $column_width = ($calendar_width / $columns) - $line_label_width;
139 $hour_slots =
60 / $slot_minutes;
140 $hour_height = $hour_slots * $slot_height;
142 $slots_count = ($end_hour - $start_hour) * $hour_slots +
1; //How many slots will we have per day
143 $calendar_height = $line_height * ($slots_count +
1) +
20;
145 //Generate columns (each column is a provider)
146 // ['count'] how many columns we have altogether
147 // ['pid']['index'] which column is it counting from the left (
0 based)
148 // ['pid']['x'] how far from the left edge the column starts (in pixels)
149 $columns = array('count' =
> 0);
150 foreach ($providers as $provider) {
151 $pid = $provider['id'];
152 $columns[$pid]['index'] = $columns['count']++;
153 $columns[$pid]['x'] = (($columns[$pid]['index'] +
1) * ($line_label_width +
1)) + ($column_width * $columns[$pid]['index']);
156 //Re-Index categories array to make it more usefull
157 $categories = array();
158 foreach ($A_CATEGORY as $category) {
159 $categories[$category['id']] = $category;
163 foreach ($A_EVENTS as $date =
> $event_list) {
165 //Generate labels and positions for all the calendar lines
166 $lines = array(); //This will hold metadata for each visual calendar line
170 for ($i =
1; $i <= $slots_count; $i++) {
171 $lines[$i] = array();
172 $lines[$i]['index'] = $i;
173 $lines[$i]['ampm'] = $hour
>=
12 ? '
2' : '
1'; //For the links
174 $lines[$i]['ampm_char'] = $hour
>=
12 ? 'pm' : 'am'; //Visual representation
175 $lines[$i]['hour'] = $hour
> 12 ? $hour -
12 : $hour;
176 $lines[$i]['min'] = $minutes;
177 $lines[$i]['date'] = $date;
178 $lines[$i]['label'] = $lines[$i]['hour'].
":".str_pad($minutes,
2, '
0', STR_PAD_LEFT).'
<br />'.$lines[$i]['ampm_char'].'
';
179 $lines[$i]['y'] = ($i-
1) * ($line_height +
1) + $day_start_y; //Where to absolutely position the line
181 //Go to the next slot
182 $minutes += $slot_minutes;
183 if (($i % $hour_slots) ==
0) { //New hour starts
189 $arr_events = $S_EVENTS[$date];
191 $events = array(); //Temporary array for enumerating the events
192 $slots = array(); //This is the map of slots showing how many events share the slot and the CSS style for IN-OUT events
193 $provstat = array(); //Used to gray out the slots for which the provider is not available (out of office)
195 //Initialize the slot map with defaul values
196 // ['adj'] Used for adjusting the chip's width and position from the left column edge (see further below)
197 // ['n'] How many events share the same slot
198 // ['provstat'] CSS style name as a visual cue that provider is available or not
199 foreach($providers as $provider) {
200 $slots[$provider['id']] = array();
201 for ($i =
1; $i <= $slots_count; $i++) {
202 $slots[$provider['id']][$i] = array('adj' =
> 0, 'n' =
> 0, 'provstat' =
> 'cal_slot_out');
206 //Go through all the events for the day
207 list($slotkey, $slotevent) = each($arr_events);
208 for (; isset($slotkey); list($slotkey, $slotevent) = each($arr_events)) {
209 $starth = substr($slotevent['startTime'],
0,
2);
210 $startm = substr($slotevent['startTime'],
3,
2);
211 $providerid = $slotevent['aid'];
213 $start_slot = ($starth - $start_hour) * $hour_slots + floor($startm / $slot_minutes) +
1;
214 $durminutes = ceil($slotevent['duration'] /
60); //Convert from seconds to minutes
216 //$durslots is the amount of slots the chip touches, even if it does not fill a complete slot
217 $durslots = ceil((($startm % $slot_minutes) + $durminutes) / $slot_minutes);
218 if ($durslots ==
0) { //Event should take up at least one slot
220 $durminutes = $slot_minutes;
223 if (($start_slot + $durslots)
> $slots_count) { //Event should not be longer than visible calendar
224 $durslots = $slots_count - $start_slot +
1;
225 $durminutes = $durslots * $slot_minutes;
228 $end_slot = $start_slot + $durslots;
230 //Events such as IN, OUT etc. require special handling (setting the CSS class name in the $slots map)
231 if ($slotevent['catid'] ==
2) {
232 for ($i = $start_slot; $i <= $slots_count; $i++) {
233 $slots[$providerid][$i]['provstat'] = 'cal_slot_in';
237 if ($slotevent['catid'] ==
3) {
238 for ($i = $start_slot; $i <= $slots_count; $i++) {
239 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
243 if ($slotevent['catid'] ==
4) {
244 for ($i = $start_slot; $i < $start_slot + $durslots; $i++) {
245 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
249 if ($slotevent['catid'] ==
8) {
250 for ($i = $start_slot; $i < $start_slot + $durslots; $i++) {
251 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
254 //END special events handling
256 //Mark slots as taken and count the chips in each slot
257 for ($i = $start_slot; $i < $end_slot; $i++) {
258 $slots[$providerid][$i]['n']++;
261 //Calculate event chip dimensions
262 $x = $columns[$providerid]['x'];
263 $y = $lines[$start_slot]['y'];
265 $h = $durslots * ($line_height +
1) -
2;
267 $slotevent['duration'] = $durminutes; //Convert from seconds to minutes
269 //Add event to the list for rendering
270 //attaching the category and event data from the database
271 if ($slotevent['eid'] != '') { //For some reason empty $slotevent sometimes exist. TODO: Figure out why
272 $events[$providerid][] = array(
277 'start_slot' =
> $start_slot,
278 'end_slot' =
> $end_slot,
279 'category' =
> $categories[$slotevent['catid']],
286 $ready_events = array(); //This array will hold events with fully adjusted position
289 list($providerid, $events_list) = each($events);
290 for (; isset($providerid); list($providerid, $events_list) = each($events)) {
292 /* Sorting debug: foreach ($events_list as $ev) {
293 print('ID: '.$ev['data']['eid'].'
');
294 print('Start: '.$ev['start_slot'].'
End:'.$ev['end_slot'].'
');
295 print('Duration: '.$ev['data']['duration'].'
');
296 print('Top: '.$ev['top'].'
Left:'.$ev['left'].'
');
297 print('---------------
<br />');
299 print
"#########################################################################Sorting...<br />";*/
301 //Sort events so that they as much as possible do NOT overlap
302 usort($events_list,
"compareEvents");
304 /* Sorting debug: foreach ($events_list as $ev) {
305 print('ID: '.$ev['data']['eid'].'
');
306 print('Start: '.$ev['start_slot'].'
End:'.$ev['end_slot'].'
');
307 print('Duration: '.$ev['data']['duration'].'
');
308 print('Top: '.$ev['top'].'
Left:'.$ev['left'].'
');
309 print('---------------
<br />');
313 if (!isset($ready_events[$providerid])) {$ready_events[$providerid] = array();}
314 foreach ($events_list as $event) {
316 //Find the max neccesary width divisor (how thin to make this chip)
317 //by going over each slot the chip overlays and seeing how many others are there
318 for ($i = $event['start_slot']; $i < $event['end_slot']; $i++) {
319 if ($slots[$providerid][$i]['n']
> $neighbors) {$neighbors = $slots[$providerid][$i]['n'];}
320 $slots[$providerid][$i]['adj']++;
322 //Adjust chip position and width (the magic number
3 adjusts for chip borders and the space between chips)
323 $event['width'] = floor(($column_width - ($neighbors *
3)) / $neighbors);
324 $event['left'] = $event['left'] + (($event['width'] +
3) * ($slots[$providerid][$event['start_slot']]['adj'] -
1));
325 $ready_events[$providerid][] = $event;
327 //usort($ready_events[$providerid],
"compareEvents");
331 //Marshall some variables to Smarty engine
332 $this-
>assign('container_width', $container_width);
333 $this-
>assign('calendar_width', $calendar_width);
334 $this-
>assign('date', $date);
335 $this-
>assign_by_ref('lines', $lines);
336 $this-
>assign('line_height', $line_height);
337 $this-
>assign('hour_height', $hour_height);
338 $this-
>assign('line_label_width', $line_label_width);
339 $this-
>assign('column_width', $column_width);
340 $this-
>assign_by_ref('events', $ready_events);
341 $this-
>assign_by_ref('slots', $slots);
342 $this-
>assign('date_label_y', $day_start_y -
30);
343 $this-
>assign('calendar_height', $calendar_height);
348 <div class='cal_underlay'
>
349 <div class='cal_date_label' style='top: [-$date_label_y-]'
>[-php-]echo dateformat(strtotime($date),true); [-/php-]
</div>
350 [-foreach from=$lines item=line-] [-* START Lines *-]
351 <div class='cal_line' style='top: [-$line.y-]px;'
>
352 [-foreach from=$providers item=provider-] [-* START Columns (Providers) *-]
353 <div class='cal_line_label'
onClick=
"javascript:newEvt([-$line.ampm-], [-$line.hour-], [-$line.min-], [-$line.date|date_format:'%Y%m%d'-], [-$provider.id-], 0)">
354 [-*
<a href=
"javascript:newEvt([-$line.ampm-], [-$line.hour-], [-$line.min-], [-$line.date|date_format:'%Y%m%d'-], [-$provider.id-], 0)">*-]
355 [-$line.label-]
357 </div> [-* Line label (hour:min) *-]
359 [-assign var=pid value=$provider.id-]
360 [-assign var=lineindex value=$line.index-]
361 <div class='cal_slot [-$slots.$pid.$lineindex.provstat-]'
> </div>
362 [-*php-]print_r($slots);Exit;[-/php*-]
363 [-/foreach-] [-* END Columns (Providers) *-]
365 [-/foreach-] [-* END Lines *-]
368 <div class='cal_overlay'
> [-* START Events overlay *-]
369 [-* We should access $events through $provider.id index to only show events for selected providers *-]
370 [-foreach from=$providers item=provider-] [-* START Columns (Providers) *-]
371 [-assign var=pid value=$provider.id-]
372 [-assign var=column value=$events.$pid-]
373 [-foreach from=$column item=event-] [-* START Events *-]
374 [-if $event.data.catid eq
2 || $event.data.catid eq
3 || $event.data.catid eq
4 || $event.data.catid eq
8 || $event.data.catid eq
11-]
375 <div class='cal_event_na' style='top: [-$event.top-]px;
376 left: [-$event.left-]px;
377 width: [-$event.width-]px;
378 height: [-$event.height-]px;'
>
379 <a href='javascript:oldEvt([-$date|date_format:
"%Y%m%d"-], [-$event.data.eid-])'
>
380 [-if $event.data.catid eq
2-]
381 [-php-] xl('IN','e'); [-/php-]
382 [-elseif $event.data.catid eq
3-]
383 [-php-] xl('OUT','e'); [-/php-]
384 [-elseif $event.data.catid eq
4-]
385 [-php-] xl('VACATION','e'); [-/php-]
386 [-elseif $event.data.catid eq
8-]
387 [-php-] xl('LUNCH','e'); [-/php-]
388 [-elseif $event.data.catid eq
11-]
389 [-php-] xl('RESERVED','e'); [-/php-]
391 [-php-] xl('Not Available','e'); [-/php-]
396 <div class='cal_event' style='top: [-$event.top-]px;
397 left: [-$event.left-]px;
398 width: [-$event.width-]px;
399 height: [-$event.height-]px;
400 background-color: [-$event.category.color-];'
>
402 <span class='cal_event_status'
>[-$event.data.apptstatus-]
</span>
403 <a href='javascript:oldEvt([-$date|date_format:
"%Y%m%d"-], [-$event.data.eid-])'
>
404 [-$event.data.startTime|date_format:
"%I:%M %p"-]
408 <p><font color=
"[-$event.data.facility.color-]">
409 [-$event.data.facility.name-]
412 <p>[-$event.data.duration-][-php-] xl('min','e'); [-/php-]
</p>
414 [-if $event.data.pid gt
0-]
415 <p><a href='javascript:goPid([-$event.data.pid-])'
>[-$event.data.patient_name|default:'No name'-]
</a></p>
416 <p>[-if $event.data.patient_dob ne ''-][-php-] xl('Age','e'); [-/php-]: [-$event.data.patient_age-][-/if-]
</p>
418 [-if $event.data.title ne ''-]
<p>[-$event.data.title|escape-]
</p>[-/if-]
419 [-if $event.data.hometext ne ''-]
<p>([-$event.data.hometext|escape-])
</p>[-/if-]
423 [-/foreach-] [-* END Events *-]
424 [-/foreach-] [-* END Columns (Providers) *-]
425 </div> [-* END Events overlay *-]
429 //For multiday display we have to make the calendar larger
430 $day_start_y += ($line_height * ($slots_count+
1)) +
50;
431 $calendar_height += $calendar_height;
435 </div> [-* END Main scrollable container *-]
438 margin:
0px
0px
0px
2px;
443 [-if $PRINT_VIEW !=
1-]
451 width: [-$container_width-]px;
452 [-if $PRINT_VIEW !=
1-]
453 height:
82%; /* Unfortunately there is no way to reliably get a viewport height. */
456 height: [-$calendar_height-]px;
459 border: solid
1px #A2BBDD;
486 height: [-$line_height-]px;
487 border-bottom: solid
1px #CCCCCC;
493 width: [-$column_width-]px;
496 border-left: solid
1px #CCCCCC;
502 background-color: #FFFFFF;
505 background-color: #EEEEEE;
509 width: [-$line_label_width-]px;
510 height: [-$line_height-]px;
512 background-color: #E8EEF7;
514 font-family: Arial, Helvetica, sans-serif;
519 padding:
0px
0px
0px
0px;
523 .cal_column_line_label {
524 width: [-$line_label_width-]px;
529 background-color: #E8EEF7;
531 font-family: Arial, Helvetica, sans-serif;
536 padding:
0px
0px
0px
0px;
543 width: [-$container_width-]px;
545 border: solid
1px #CCCCCC;
548 [-if $PRINT_VIEW !=
1-]
558 width: [-$column_width-]px;
561 border-left: solid
1px #CCCCCC;
577 background-color: #B0C4DE;
583 border-top: solid
1px #EEEEEE;
584 border-bottom: solid
1px #
000000;
585 border-left: solid
1px #EEEEEE;
586 border-right: solid
1px #
000000;
590 background-color: #FFFFFF;
591 font-family: Arial, Helvetica, sans-serif;
604 font-family: Arial, Helvetica, sans-serif;
611 background-color: #E8EEF7;
613 font-family: Courier, mono;
618 border-left: solid
1px #CCCCCC;
619 border-bottom: solid
1px #CCCCCC;
621 padding:
0px
1px
0px
2px;