PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.15
VikBooking Hotel Booking Engine & PMS v1.8.15
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / site / views / tableaux / tmpl / default.php

default.php in VikBooking Hotel Booking Engine & PMS 1.8.15, at site/views/tableaux/tmpl/default.php

1,055 lines 42.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 $rooms = $this->rooms;
14 $rooms_busy = $this->rooms_busy;
15 $fromts = $this->fromts;
16 $tots = $this->tots;
17
18 $operator_perms = !empty($this->operator['perms']) && is_array($this->operator['perms']) ? $this->operator['perms'] : [];
19
20 $pitemid = VikRequest::getInt('Itemid', 0, 'request');
21
22 // JS lang vars
23 JText::script('VBFORMADULTS');
24 JText::script('VBFORMCHILDREN');
25 JText::script('ORDER_SPREQUESTS');
26 JText::script('VBOCUSTOMERNOMINATIVE');
27 JText::script('VBPICKUP');
28 JText::script('VBRETURN');
29 JText::script('VBSEARCHRESROOM');
30 JText::script('VBOEXTRASERVICES');
31 JText::script('VBO_PETS');
32 JText::script('ORDER_PHONE');
33
34 $nowdf = VikBooking::getDateFormat();
35 if ($nowdf == "%d/%m/%Y") {
36 $df = 'd/m/Y';
37 } elseif ($nowdf == "%m/%d/%Y") {
38 $df = 'm/d/Y';
39 } else {
40 $df = 'Y/m/d';
41 }
42 $datesep = VikBooking::getDateSeparator();
43
44 //load jQuery
45 if (VikBooking::loadJquery()) {
46 JHtml::fetch('jquery.framework', true, true);
47 }
48
49 $days_labels = array(
50 JText::translate('VBSUN'),
51 JText::translate('VBMON'),
52 JText::translate('VBTUE'),
53 JText::translate('VBWED'),
54 JText::translate('VBTHU'),
55 JText::translate('VBFRI'),
56 JText::translate('VBSAT')
57 );
58 $months_labels = array(
59 JText::translate('VBMONTHONE'),
60 JText::translate('VBMONTHTWO'),
61 JText::translate('VBMONTHTHREE'),
62 JText::translate('VBMONTHFOUR'),
63 JText::translate('VBMONTHFIVE'),
64 JText::translate('VBMONTHSIX'),
65 JText::translate('VBMONTHSEVEN'),
66 JText::translate('VBMONTHEIGHT'),
67 JText::translate('VBMONTHNINE'),
68 JText::translate('VBMONTHTEN'),
69 JText::translate('VBMONTHELEVEN'),
70 JText::translate('VBMONTHTWELVE')
71 );
72
73 // count the cells per month
74 $months_days = array();
75 $nowinfo = getdate($fromts);
76 while ($nowinfo[0] <= $tots) {
77 $mkey = $nowinfo['mon'] . '_' . $nowinfo['year'];
78 if (!isset($months_days[$mkey])) {
79 $months_days[$mkey] = 0;
80 }
81 $months_days[$mkey]++;
82 // next loop
83 $nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
84 }
85
86 // today
87 $todaydt = date('Y-m-d');
88 $todayts = strtotime($todaydt);
89
90 // tomorrow
91 $tomorrowts = strtotime("+1 day", $todayts);
92
93 // count today and tomorrow bookings
94 $tod_arrive = 0;
95 $tom_arrive = 0;
96 $tod_depart = 0;
97 $tom_depart = 0;
98 $tod_stays = 0;
99 $tom_stays = 0;
100 foreach ($rooms_busy as $rid => $busy) {
101 foreach ($busy as $b) {
102 $tmpone = getdate($b['checkin']);
103 $ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']);
104 $tmptwo = getdate($b['checkout']);
105 $conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']);
106 if ($todayts == $ritts) {
107 $tod_arrive++;
108 }
109 if ($tomorrowts == $ritts) {
110 $tom_arrive++;
111 }
112 if ($todayts == $conts) {
113 $tod_depart++;
114 }
115 if ($tomorrowts == $conts) {
116 $tom_depart++;
117 }
118 if ($todayts > $ritts && $todayts < $conts) {
119 $tod_stays++;
120 }
121 if ($tomorrowts > $ritts && $tomorrowts < $conts) {
122 $tom_stays++;
123 }
124 }
125 }
126 ?>
127
128 <div id="vbdialog-overlay">
129 <a class="vbdialog-overlay-close">&nbsp;</a>
130 <div class="vbdialog-inner">
131 <div class="vbdialog-inner-tableaux"></div>
132 </div>
133 </div>
134
135 <div class="vbo-modal-overlay-block vbo-modal-overlay-block-fests">
136 <a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
137 <div class="vbo-modal-overlay-content vbo-modal-overlay-content-fests">
138 <div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-fests">
139 <h3><?php VikBookingIcons::e('star'); ?> <span></span></h3>
140 </div>
141 <div class="vbo-modal-overlay-content-body">
142 <div class="vbo-overlay-fests-list"></div>
143 </div>
144 </div>
145 </div>
146
147 <div class="vbo-modal-overlay-block vbo-modal-overlay-block-roomdaynotes">
148 <a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
149 <div class="vbo-modal-overlay-content vbo-modal-overlay-content-roomdaynotes">
150 <div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-roomdaynotes">
151 <h3>
152 <?php VikBookingIcons::e('exclamation-circle'); ?>
153 <span class="vbo-modal-roomdaynotes-dt"></span>
154 <span class="vbo-modal-overlay-close-times" onclick="hideVboDialogRdaynotes();">&times;</span>
155 </h3>
156 </div>
157 <div class="vbo-modal-overlay-content-body">
158 <div class="vbo-modal-roomdaynotes-list"></div>
159 <div class="vbo-modal-roomdaynotes-addnew" data-readymd="" data-ymd="" data-roomid="" data-subroomid="">
160 <h4><?php echo JText::translate('VBOADDCUSTOMNOTETODAY'); ?></h4>
161 <div class="vbo-modal-roomdaynotes-addnew-elem">
162 <label for="vbo-newrdnote-name"><?php echo JText::translate('VBNAME'); ?></label>
163 <input type="text" id="vbo-newrdnote-name" value="" />
164 </div>
165 <div class="vbo-modal-roomdaynotes-addnew-elem">
166 <label for="vbo-newrdnote-descr"><?php echo JText::translate('VBOINVCOLDESCR'); ?></label>
167 <textarea id="vbo-newrdnote-descr"></textarea>
168 </div>
169 <div class="vbo-modal-roomdaynotes-addnew-elem">
170 <label for="vbo-newrdnote-cdays"><?php echo JText::translate('VBOCONSECUTIVEDAYS'); ?></label>
171 <input type="number" id="vbo-newrdnote-cdays" min="0" max="365" value="0" onchange="vboRdayNoteCdaysCount();" onkeyup="vboRdayNoteCdaysCount();" />
172 <span class="vbo-newrdnote-dayto">
173 <span class="vbo-newrdnote-dayto-lbl"><?php echo JText::translate('VBOUNTIL'); ?></span>
174 <span class="vbo-newrdnote-dayto-val"></span>
175 </span>
176 </div>
177 <div class="vbo-modal-roomdaynotes-addnew-save">
178 <button type="button" class="btn vbo-pref-color-btn" onclick="vboAddRoomDayNote(this);"><?php echo JText::translate('VBOSIGNATURESAVE'); ?></button>
179 </div>
180 </div>
181 </div>
182 </div>
183 </div>
184
185 <div class="vbo-operator-tool-container">
186 <div class="vbo-operator-tool-breadcrumbs">
187 <span class="vbo-operator-tool-breadcrumb vbo-operator-tool-breadcrumb-home">
188 <a class="vbo-pref-color-text" href="<?php echo JRoute::rewrite('index.php?option=com_vikbooking&view=operators' . (!empty($pitemid) ? '&Itemid=' . $pitemid : '')); ?>">
189 <?php VikBookingIcons::e('th-list'); ?>
190 <span class="vbo-operator-tool-breadcrumb-name"><?php echo JText::translate('VBMENUDASHBOARD'); ?></span>
191 <span class="vbo-operator-tool-breadcrumb-separator"><?php VikBookingIcons::e('chevron-right'); ?></span>
192 </a>
193 </span>
194 <!-- use .vbo-operator-tool-breadcrumb-step-current to define a previous breadcrump-step, not the home, not the current -->
195 <span class="vbo-operator-tool-breadcrumb vbo-operator-tool-breadcrumb-step vbo-operator-tool-breadcrumb-step-current">
196 <?php VikBookingIcons::e('stream'); ?>
197 <span class="vbo-operator-tool-breadcrumb-name"><?php echo VikBooking::getOperatorInstance()->getToolName('tableaux'); ?></span>
198 </span>
199 </div>
200 </div>
201
202 <div class="vbo-tableaux-todaystats">
203 <div class="vbo-tableaux-todaystat">
204 <div class="vbo-tableaux-todaystat-inner">
205 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXARRTD'); ?></span>
206 <span class="vbo-tableaux-today-val"><?php echo $tod_arrive; ?></span>
207 </div>
208 <div class="vbo-tableaux-todaystat-inner">
209 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXARRTM'); ?></span>
210 <span class="vbo-tableaux-today-val"><?php echo $tom_arrive; ?></span>
211 </div>
212 </div>
213 <div class="vbo-tableaux-todaystat">
214 <div class="vbo-tableaux-todaystat-inner">
215 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXDEPTD'); ?></span>
216 <span class="vbo-tableaux-today-val"><?php echo $tod_depart; ?></span>
217 </div>
218 <div class="vbo-tableaux-todaystat-inner">
219 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXDEPTM'); ?></span>
220 <span class="vbo-tableaux-today-val"><?php echo $tom_depart; ?></span>
221 </div>
222 </div>
223 <div class="vbo-tableaux-todaystat">
224 <div class="vbo-tableaux-todaystat-inner">
225 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXSTYTD'); ?></span>
226 <span class="vbo-tableaux-today-val"><?php echo $tod_stays; ?></span>
227 </div>
228 <div class="vbo-tableaux-todaystat-inner">
229 <span class="vbo-tableaux-today-lbl"><?php echo JText::translate('VBOTABLEAUXSTYTM'); ?></span>
230 <span class="vbo-tableaux-today-val"><?php echo $tom_stays; ?></span>
231 </div>
232 </div>
233 </div>
234
235 <div class="vbo-tableaux-outer">
236 <div class="vbo-tableaux-container">
237 <div class="vbo-tableaux-tbl-container">
238 <div class="vbo-table-responsive vbo-tableaux-tbl-wrap">
239 <table class="vbo-table vbo-tableaux-table">
240 <tbody>
241 <tr class="vbo-tableaux-monthsrow">
242 <td class="vbo-tableaux-emptycell">
243 <a href="javascript: void(0);" class="vbo-tableaux-togglefullscreen" title="<?php echo htmlentities(JText::translate('VBOTGLFULLSCREEN')); ?>"><?php VikBookingIcons::e('expand'); ?></a>
244 </td>
245 <?php
246 foreach ($months_days as $mkey => $totdays) {
247 $mkeyparts = explode('_', $mkey);
248 ?>
249 <td class="vbo-tableaux-monthcell" colspan="<?php echo $totdays; ?>">
250 <h4><?php echo $months_labels[($mkeyparts[0] - 1)] . ' ' . $mkeyparts[1]; ?></h4>
251 </td>
252 <?php
253 }
254 ?>
255 </tr>
256 <tr class="vbo-tableaux-firstrow">
257 <td class="vbo-tableaux-emptycell">&nbsp;</td>
258 <?php
259 $newmonth = 0;
260 $nowinfo = getdate($fromts);
261 while ($nowinfo[0] <= $tots) {
262 $nowinfo_ymd = date('Y-m-d', $nowinfo[0]);
263 $monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : '';
264 $monthclass = date('Y-m-d', $nowinfo[0]) == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass;
265 $newmonth = $nowinfo['mon'];
266 $read_day = $days_labels[$nowinfo['wday']] . ' ' . $nowinfo['mday'] . ' ' . $months_labels[($nowinfo['mon'] - 1)] . ' ' . $nowinfo['year'];
267 $fest_class = isset($this->festivities[$nowinfo_ymd]) ? ' vbo-tableaux-festcell' : '';
268 ?>
269 <td class="vbo-tableaux-daycell<?php echo $monthclass . $fest_class; ?>" data-ymd="<?php echo $nowinfo_ymd; ?>" data-readymd="<?php echo $read_day; ?>">
270 <div class="vbo-tableaux-day-cont">
271 <span class="vbo-tableaux-day-wday"><?php echo $days_labels[$nowinfo['wday']]; ?></span>
272 <span class="vbo-tableaux-day-mday"><?php echo $nowinfo['mday']; ?></span>
273 </div>
274 </td>
275 <?php
276 // next loop
277 $nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
278 }
279 ?>
280 </tr>
281 <?php
282 $rooms_features_map = array();
283 $rooms_features_bookings = array();
284 $rooms_loop_count = array();
285 foreach ($rooms as $rid => $rdata) {
286 // distinctive features
287 $room_params = !empty($rdata['params']) ? json_decode($rdata['params'], true) : array();
288 if (is_array($room_params) && array_key_exists('features', $room_params) && count($room_params['features']) > 0) {
289 $rooms_features_map[$rid] = array();
290 foreach ($room_params['features'] as $rind => $rfeatures) {
291 foreach ($rfeatures as $fname => $fval) {
292 if (strlen($fval)) {
293 $rooms_features_map[$rid][$rind] = '#'.$fval;
294 break;
295 }
296 }
297 }
298 if (!(count($rooms_features_map[$rid]) > 0)) {
299 unset($rooms_features_map[$rid]);
300 }
301 }
302 //
303 ?>
304 <tr class="vbo-tableaux-roomrow">
305 <td class="vbo-tableaux-roomname"><?php echo $rdata['name']; ?></td>
306 <?php
307 $nowinfo = getdate($fromts);
308 $bookbuffer = array();
309 $prevbuffer = array();
310 $positions = array();
311 $newmonth = 0;
312 while ($nowinfo[0] <= $tots) {
313 $nowinfo_ymd = date('Y-m-d', $nowinfo[0]);
314 $monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : '';
315 $monthclass = date('Y-m-d', $nowinfo[0]) == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass;
316 $newmonth = $nowinfo['mon'];
317
318 /**
319 * Critical dates defined at room-day level, or for any sub-unit.
320 *
321 * @since 1.13.5
322 */
323 $rdaynote_class = ' vbo-roomdaynote-empty';
324 $rdaynote_icn = 'far fa-sticky-note';
325 $cell_rdnotes = '';
326 $rdnkeys_lookup = range(0, $rdata['units']);
327 $rdaynote_keyids = array();
328 $glob_rdn_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_0';
329 // find room-day note keys with some notes (room-day level or subroom-day level)
330 foreach ($rdnkeys_lookup as $lookup_index) {
331 $rdaynote_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_' . $lookup_index;
332 if (isset($this->rdaynotes[$rdaynote_keyid])) {
333 // push associative index with notes
334 $rdaynote_keyids[$lookup_index] = $rdaynote_keyid;
335 }
336 }
337 if (count($rdaynote_keyids)) {
338 // some notes exist for this combination of date, room ID and subunit
339 $rdaynote_class = ' vbo-roomdaynote-full';
340 $rdaynote_icn = 'sticky-note';
341 /**
342 * Try to populate the notes for this room-day cell
343 * only if the previous day does not have the same note.
344 * Just the first readable room-day cell should have notes.
345 */
346 $notes_titles = array();
347 $yesterday_ts = mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] - 1), $nowinfo['year']);
348 $yesterday_ymd = date('Y-m-d', $yesterday_ts);
349 // loop through all the keys with notes
350 foreach ($rdaynote_keyids as $lookup_index => $rdaynote_keyid) {
351 $yesterday_keyid = $yesterday_ymd . '_' . $rdata['id'] . '_' . $lookup_index;
352 foreach ($this->rdaynotes[$rdaynote_keyid]['info'] as $today_note) {
353 // only manual (custom) room-day notes will be displayed
354 $display_note = ($today_note->type == 'custom');
355 if (isset($this->rdaynotes[$yesterday_keyid])) {
356 // make sure the same note is not present for yesterday
357 foreach ($this->rdaynotes[$yesterday_keyid]['info'] as $yesterday_note) {
358 if ($today_note->type == $yesterday_note->type && $today_note->name == $yesterday_note->name) {
359 // same note available also for yesterday
360 $display_note = false;
361 break;
362 }
363 }
364 }
365 if ($display_note) {
366 // push just the name of the note
367 array_push($notes_titles, $today_note->name);
368 }
369 }
370 }
371 // separate all notes (if any) with comma
372 $cell_rdnotes = implode(', ', $notes_titles);
373 //
374 }
375 //
376
377 ?>
378 <td class="vbo-tableaux-roombooks<?php echo $monthclass . $rdaynote_class; ?>" data-day="<?php echo $nowinfo_ymd; ?>" data-dayrid="<?php echo $nowinfo_ymd . $rdata['id']; ?>" data-rdnkeys="<?php echo implode(',', array_keys($rdaynote_keyids)); ?>" data-notes="<?php echo $this->escape($cell_rdnotes); ?>">
379 <?php
380 $room_bookings = array();
381 if (isset($rooms_busy[$rid])) {
382 foreach ($rooms_busy[$rid] as $b) {
383 $tmpone = getdate($b['checkin']);
384 $ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']);
385 $tmptwo = getdate($b['checkout']);
386 $conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']);
387 $b['basefrom'] = $ritts;
388 $b['baseto'] = $conts;
389 if ($nowinfo[0] >= $ritts && $nowinfo[0] <= $conts) {
390 array_push($room_bookings, $b);
391 }
392 }
393 /**
394 * By default, we attempt to sort the bookings for this day by room index.
395 *
396 * @since 1.13.5
397 */
398 if (count($room_bookings)) {
399 $rindexes_map = array();
400 foreach ($room_bookings as $rbk => $rbval) {
401 $rindexes_map[$rbk] = isset($rbval['indexes']) ? $rbval['indexes'] : '';
402 }
403 asort($rindexes_map);
404 $room_bookings_copy = array();
405 foreach ($rindexes_map as $rbk => $rbval) {
406 array_push($room_bookings_copy, $room_bookings[$rbk]);
407 }
408 $room_bookings = $room_bookings_copy;
409 }
410 //
411 }
412 if (count($room_bookings) && count($bookbuffer)) {
413 // sort bookings according to the previous map
414 $newbookings = array();
415 foreach ($bookbuffer as $oid) {
416 foreach ($room_bookings as $kb => $rbook) {
417 if ($oid == $rbook['idorder']) {
418 // get this key first
419 $newbookings[$kb] = $rbook;
420 // do not break the loop as there could be multiple idorder, just continue
421 continue;
422 }
423 }
424 }
425 if (count($newbookings)) {
426 // merge array by keys by unsetting double keys from second array
427 $room_bookings = $newbookings + $room_bookings;
428 }
429 // copy buffer before reset to see whether this is the first cell displayed for the booking
430 $prevbuffer = $bookbuffer;
431 // reset buffer to fill the current day bookings
432 $bookbuffer = array();
433 }
434 $indexpos = 0;
435 foreach ($room_bookings as $k => $rbook) {
436 $contclass = 'stay';
437 if ($rbook['basefrom'] == $nowinfo[0]) {
438 $contclass = 'checkin';
439 } elseif ($rbook['baseto'] == $nowinfo[0]) {
440 $contclass = 'checkout';
441 }
442 $shortstaycls = '';
443 if (ceil(($rbook['baseto'] - $rbook['basefrom']) / 86400) < 2) {
444 $shortstaycls = ' vbo-tableaux-booking-short';
445 }
446 //check position
447 $pos = $indexpos;
448 if (isset($positions[$rbook['idorder']]) && $indexpos < $positions[$rbook['idorder']]) {
449 // print empty blocks to give the right position to this booking
450 $pos = $indexpos.'-'.$positions[$rbook['idorder']];
451 $looplim = ($positions[$rbook['idorder']] - $indexpos);
452 for ($i = 0; $i < $looplim; $i++) {
453 $indexpos++;
454 ?>
455 <div class="vbo-tableaux-booking vbo-tableaux-booking-empty">
456 <span>&nbsp;</span>
457 </div>
458 <?php
459 }
460 $pos .= '-'.$indexpos;
461 }
462 // push position
463 if (!isset($positions[$rbook['idorder']])) {
464 $positions[$rbook['idorder']] = $indexpos;
465 }
466 // push booking to the buffer for the ordering in the next loop
467 array_push($bookbuffer, $rbook['idorder']);
468
469 // cell content
470 $cellcont = '&nbsp;';
471 // container attributes
472 $cont_attrs = array();
473 if (!in_array($rbook['idorder'], $prevbuffer)) {
474 // first time we print the details for this booking - compose the content of the element
475 $cellcont = '';
476 // get the key to use for reading values that were grouped and separated with the query
477 if (!isset($rooms_loop_count[$rbook['idorder']])) {
478 // the index to read of the feature depending on how many times this booking was printed (in case of multiple same rooms in one booking)
479 $rooms_loop_count[$rbook['idorder']] = 0;
480 } else {
481 // increment index for this room booking
482 $rooms_loop_count[$rbook['idorder']]++;
483 }
484 $nowdataindex = $rooms_loop_count[$rbook['idorder']];
485 // add data attribute for adults, children and pets
486 $adultsinfo = explode(';', $rbook['adults']);
487 $childreninfo = explode(';', $rbook['children']);
488 $petsinfo = explode(';', $rbook['pets']);
489 if (isset($adultsinfo[$nowdataindex]) && isset($childreninfo[$nowdataindex])) {
490 $cont_attrs['party'] = $adultsinfo[$nowdataindex] . ';' . $childreninfo[$nowdataindex];
491 if (isset($petsinfo[$nowdataindex])) {
492 $cont_attrs['party'] .= ';' . $petsinfo[$nowdataindex];
493 }
494 }
495 // add data attribute for traveler first and last name
496 $namesinfo = explode(';', $rbook['tnames']);
497 $lnamesinfo = explode(';', $rbook['tlnames']);
498 if (isset($namesinfo[$nowdataindex]) && isset($lnamesinfo[$nowdataindex]) && !empty($namesinfo[$nowdataindex])) {
499 /**
500 * Make sure permissions allow to see the guest name.
501 *
502 * @since 1.15.0 (J) - 1.5.0 (WP)
503 */
504 if (!empty($operator_perms['guestname'])) {
505 $cont_attrs['tnominative'] = htmlspecialchars($namesinfo[$nowdataindex] . ' ' . $lnamesinfo[$nowdataindex]);
506 }
507 }
508 // check-in time
509 $cont_attrs['checkin'] = date(str_replace("/", $datesep, $df).' H:i', $rbook['checkin']);
510 $cont_attrs['checkout'] = date(str_replace("/", $datesep, $df).' H:i', $rbook['checkout']);
511
512 /**
513 * Check if permissions allow to see the guest phone number.
514 *
515 * @since 1.17.3 (J) - 1.7.3 (WP)
516 */
517 if (!empty($rbook['phone']) && !empty($operator_perms['guestphone'])) {
518 $cont_attrs['phone'] = $rbook['phone'];
519 }
520
521 /**
522 * If permissions allow to see extra services, build a list of services included.
523 *
524 * @since 1.15.0 (J) - 1.5.0 (WP)
525 */
526 if (!empty($operator_perms['roomextras'])) {
527 // build extra info strings
528 $room_extra_infos = [];
529
530 // parse Website and OTA rate plans
531 $room_rplans = explode('__', (string) $rbook['ridtars']);
532 $room_ota_rplans = explode('__', (string) $rbook['rotarplans']);
533 if (!empty($room_rplans[$nowdataindex])) {
534 $rplan_name = $this->getRatePlanFromTariff(($room_rplans[$nowdataindex]));
535 if ($rplan_name) {
536 $room_extra_infos[] = $rplan_name;
537 }
538 } elseif (!empty($room_ota_rplans[$nowdataindex])) {
539 $room_extra_infos[] = $room_ota_rplans[$nowdataindex];
540 }
541
542 // parse options
543 $room_options = explode('__', (string) $rbook['roptions']);
544 if (!empty($room_options[$nowdataindex])) {
545 $room_options_list = [];
546 $all_room_options = explode(';', $room_options[$nowdataindex]);
547 foreach ($all_room_options as $room_opt) {
548 $room_opt_parts = explode(':', $room_opt);
549 if (count($room_opt_parts) < 2 || empty($room_opt_parts[0]) || !isset($this->all_options[$room_opt_parts[0]])) {
550 continue;
551 }
552 $room_options_list[] = $this->all_options[$room_opt_parts[0]]['name'];
553 }
554 if (count($room_options_list)) {
555 $room_extra_infos[] = JText::translate('VBACCOPZ') . ': ' . implode(', ', $room_options_list);
556 }
557 }
558
559 // parse extra services
560 $room_extras = explode('__', (string) $rbook['rextras']);
561 if (!empty($room_extras[$nowdataindex])) {
562 $room_extras_list = [];
563 $decoded_room_extras = json_decode($room_extras[$nowdataindex]);
564 if (is_array($decoded_room_extras)) {
565 foreach ($decoded_room_extras as $dre) {
566 if (!empty($dre->name)) {
567 $room_extras_list[] = $dre->name;
568 }
569 }
570 }
571 if (count($room_extras_list)) {
572 $room_extra_infos[] = JText::translate('VBOEXTRASERVICES') . ': ' . implode(', ', $room_extras_list);
573 }
574 }
575
576 // set the whole room extra infos string
577 $cont_attrs['rextrainfos'] = implode(' - ', $room_extra_infos);
578 }
579
580 // check for special requests
581 if (preg_match("/special requests: (.*?)(?=[a-z0-9\-_ ]+:|$)/is", $rbook['custdata'], $matches)) {
582 $cont_attrs['sprequest'] = htmlspecialchars($matches[1]);
583 }
584 // distinctive features
585 if (!empty($rbook['indexes']) && isset($rooms_features_map[$rid])) {
586 $bookindexes = explode(';', $rbook['indexes']);
587 if (!isset($rooms_features_bookings[$rid.'_'.$rbook['idorder']])) {
588 // the index to read of the feature depending on how many times this booking was printed (in case of multiple same rooms in one booking)
589 $rooms_features_bookings[$rid.'_'.$rbook['idorder']] = 0;
590 } else {
591 // increment index for this room booking
592 $rooms_features_bookings[$rid.'_'.$rbook['idorder']]++;
593 }
594 $nowfeatindex = $rooms_features_bookings[$rid.'_'.$rbook['idorder']];
595 if (isset($bookindexes[$nowfeatindex]) && isset($rooms_features_map[$rid][$bookindexes[$nowfeatindex]])) {
596 // get this room feature
597 $cellcont .= '<span class="vbo-tableaux-roomindex">'.$rooms_features_map[$rid][$bookindexes[$nowfeatindex]] . '</span> ';
598 }
599 }
600 // customer details
601 if (!empty($rbook['first_name']) || !empty($rbook['last_name'])) {
602 // customer record
603 if (!empty($operator_perms['guestname'])) {
604 $cellcont .= $rbook['first_name'].' '.$rbook['last_name'];
605 } else {
606 $cellcont .= '#' . $rbook['idorder'];
607 }
608 } else {
609 // parse the customer data string
610 $custdata_parts = explode("\n", $rbook['custdata']);
611 $enoughinfo = false;
612 if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) {
613 // get the first two fields
614 $custvalues = array();
615 foreach ($custdata_parts as $custdet) {
616 if (strlen($custdet) < 1) {
617 continue;
618 }
619 $custdet_parts = explode(':', $custdet);
620 if (count($custdet_parts) >= 2) {
621 unset($custdet_parts[0]);
622 array_push($custvalues, trim(implode(':', $custdet_parts)));
623 }
624 if (count($custvalues) > 1) {
625 break;
626 }
627 }
628 if (count($custvalues) > 1) {
629 $enoughinfo = true;
630 $cellcont .= implode(' ', $custvalues);
631 }
632 }
633 if (!$enoughinfo) {
634 $cellcont .= $rbook['idorder'];
635 }
636 }
637 }
638 $data_attrs = array();
639 foreach ($cont_attrs as $datak => $datav) {
640 array_push($data_attrs, "data-{$datak}=\"{$datav}\"");
641 }
642 ?>
643 <div class="vbo-tableaux-booking vbo-tableaux-booking-<?php echo $contclass.$shortstaycls.' vbo-'.$pos; ?>" data-bid="<?php echo $rbook['idorder']; ?>" <?php echo implode(' ', $data_attrs); ?>>
644 <span><?php echo $cellcont; ?></span>
645 </div>
646 <?php
647 // increase the positioning index
648 $indexpos++;
649 }
650 ?>
651 <span class="vbo-roomdaynote-trigger" data-roomday="<?php echo $glob_rdn_keyid; ?>"><?php VikBookingIcons::e($rdaynote_icn, 'vbo-roomdaynote-display'); ?></span>
652 </td>
653 <?php
654 // next loop
655 $nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
656 }
657 ?>
658 </tr>
659 <?php
660 }
661 ?>
662 </tbody>
663 </table>
664 </div>
665 </div>
666 </div>
667 </div>
668
669 <script type="text/javascript">
670 var vboFests = <?php echo json_encode($this->festivities); ?>;
671 var vboRdayNotes = <?php echo json_encode($this->rdaynotes); ?>;
672 var vbdialog_on = false;
673 var vbodialogfests_on = false;
674 var vbodialogrdaynotes_on = false;
675
676 function vbDialogClose() {
677 if (vbdialog_on === true) {
678 jQuery("#vbdialog-overlay").fadeOut();
679 vbdialog_on = false;
680 }
681 }
682
683 /**
684 * Fests
685 */
686 function hideVboDialogFests() {
687 if (vbodialogfests_on === true) {
688 jQuery(".vbo-modal-overlay-block-fests").fadeOut(400, function () {
689 jQuery(".vbo-modal-overlay-content-fests").show();
690 });
691 vbodialogfests_on = false;
692 }
693 }
694
695 function vboRenderFests(day, daytitle) {
696 // set day title
697 if (daytitle) {
698 jQuery('.vbo-modal-overlay-content-fests').find('h3').find('span').text(daytitle);
699 }
700 // compose fests information
701 var fests_html = '';
702 if (vboFests[day] && vboFests[day]['festinfo'] && vboFests[day]['festinfo'].length) {
703 for (var i = 0; i < vboFests[day]['festinfo'].length; i++) {
704 var fest = vboFests[day]['festinfo'][i];
705 fests_html += '<div class="vbo-overlay-fest-details">';
706 fests_html += ' <div class="vbo-fest-info">';
707 fests_html += ' <div class="vbo-fest-name">' + fest['trans_name'] + '</div>';
708 fests_html += ' <div class="vbo-fest-desc">' + fest['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>';
709 fests_html += ' </div>';
710 fests_html += '</div>';
711 }
712 }
713 // set content and display modal
714 jQuery('.vbo-overlay-fests-list').html(fests_html);
715 jQuery('.vbo-modal-overlay-block-fests').fadeIn();
716 vbodialogfests_on = true;
717 }
718
719 /**
720 * Room-day-notes
721 */
722 var rdaynote_icn_full = '<?php echo VikBookingIcons::i('sticky-note', 'vbo-roomdaynote-display'); ?>';
723 var rdaynote_icn_empty = '<?php echo VikBookingIcons::i('far fa-sticky-note', 'vbo-roomdaynote-display'); ?>';
724 var rooms_features_map = JSON.parse('<?php echo isset($rooms_features_map) && count($rooms_features_map) ? json_encode($rooms_features_map) : json_encode(array()); ?>');
725
726 function hideVboDialogRdaynotes() {
727 if (vbodialogrdaynotes_on === true) {
728 jQuery(".vbo-modal-overlay-block-roomdaynotes").fadeOut(400, function () {
729 jQuery(".vbo-modal-overlay-content-roomdaynotes").show();
730 });
731 // reset values
732 jQuery('#vbo-newrdnote-name').val('');
733 jQuery('#vbo-newrdnote-descr').val('');
734 jQuery('#vbo-newrdnote-cdays').val('0').trigger('change');
735 // turn flag off
736 vbodialogrdaynotes_on = false;
737 }
738 }
739
740 function vboRenderRdayNotes(day, idroom, subunit, readymd) {
741 // compose room-day notes information (subunit always = 0 for room-day level)
742 var notes_html = '';
743 var keyids = new Array;
744 // always push 0 as the room-level day note key
745 keyids.push(0);
746 // grab all the other note keys at sub-unit level
747 if (jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').length) {
748 var all_nkeys = jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').attr('data-rdnkeys');
749 if (all_nkeys && all_nkeys.length) {
750 var nkeys = all_nkeys.split(',');
751 for (var k in nkeys) {
752 var int_index = parseInt(nkeys[k]);
753 if (!nkeys.hasOwnProperty(k) || isNaN(int_index) || int_index < 1) {
754 continue;
755 }
756 // push sub-unit key for lookup
757 keyids.push(nkeys[k]);
758 }
759 }
760 }
761 // parse all room keys with notes
762 for (var z = 0; z < keyids.length; z++) {
763 // this is the real sub-unit we are parsing
764 var subunit_index = keyids[z];
765 var keyid = day + '_' + idroom + '_' + subunit_index;
766 if (vboRdayNotes.hasOwnProperty(keyid) && vboRdayNotes[keyid]['info'] && vboRdayNotes[keyid]['info'].length) {
767 for (var i = 0; i < vboRdayNotes[keyid]['info'].length; i++) {
768 var note_data = vboRdayNotes[keyid]['info'][i];
769 var subunit_name = '';
770 if (parseInt(subunit_index) > 0) {
771 subunit_name = '(' + subunit_index + ') ';
772 if (rooms_features_map.hasOwnProperty(idroom) && rooms_features_map[idroom].hasOwnProperty(subunit_index)) {
773 subunit_name = rooms_features_map[idroom][subunit_index] + ' - ';
774 }
775 }
776 notes_html += '<div class="vbo-overlay-fest-details vbo-modal-roomdaynotes-note-details">';
777 notes_html += ' <div class="vbo-fest-info vbo-modal-roomdaynotes-note-info">';
778 notes_html += ' <div class="vbo-fest-name vbo-modal-roomdaynotes-note-name">' + subunit_name + note_data['name'] + '</div>';
779 notes_html += ' <div class="vbo-fest-desc vbo-modal-roomdaynotes-note-desc">' + note_data['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>';
780 notes_html += ' </div>';
781 notes_html += '</div>';
782 }
783 }
784 }
785 // update attributes keys for the selected date, useful for adding new notes (always at room-level)
786 jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd', day).attr('data-roomid', idroom).attr('data-subroomid', '0');
787 if (readymd !== null) {
788 jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd', readymd);
789 jQuery('.vbo-newrdnote-dayto-val').text(readymd);
790 }
791 // set content and display modal
792 jQuery('.vbo-modal-roomdaynotes-list').html(notes_html);
793 }
794
795 function vboAddRoomDayNote(that) {
796 var mainelem = jQuery(that).closest('.vbo-modal-roomdaynotes-addnew');
797 var ymd = mainelem.attr('data-ymd');
798 var roomid = mainelem.attr('data-roomid');
799 var subroomid = mainelem.attr('data-subroomid');
800 var note_name = jQuery('#vbo-newrdnote-name').val();
801 var note_descr = jQuery('#vbo-newrdnote-descr').val();
802 var note_cdays = jQuery('#vbo-newrdnote-cdays').val();
803 if (!note_name.length && !note_descr.length) {
804 alert('Missing required fields');
805 return false;
806 }
807 // make the AJAX request to the controller to add this note to the DB
808 var jqxhr = jQuery.ajax({
809 type: "POST",
810 url: "<?php echo VikBooking::ajaxUrl(JRoute::rewrite('index.php?option=com_vikbooking&task=add_roomdaynote&tmpl=component'.(!empty($pitemid) ? '&Itemid='.$pitemid : ''), false)); ?>",
811 data: {
812 option: "com_vikbooking",
813 task: "add_roomdaynote",
814 dt: ymd,
815 idroom: roomid,
816 subunit: subroomid,
817 type: "custom",
818 name: note_name,
819 descr: note_descr,
820 cdays: note_cdays
821 }
822 }).done(function(res) {
823 // parse the JSON response that contains the note object for the passed date
824 try {
825 var stored_notes = JSON.parse(res);
826 var counter = 0;
827 for (var keyid in stored_notes) {
828 if (!stored_notes.hasOwnProperty(keyid)) {
829 continue;
830 }
831 var is_date_visible = (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').length > 0);
832 if (!vboRdayNotes.hasOwnProperty(keyid) && is_date_visible) {
833 // we need to add the proper class to the cell for this note (if it's visible)
834 jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').removeClass('vbo-roomdaynote-empty').addClass('vbo-roomdaynote-full').find('i').attr('class', rdaynote_icn_full);
835 }
836 // update global object with the new notes in any case
837 vboRdayNotes[keyid] = stored_notes[keyid];
838 // update readable notes in custom data attribute
839 if (counter < 1 && is_date_visible && note_name.length) {
840 // we push just this name
841 var current_cell_notes = jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes');
842 var all_cell_notes = current_cell_notes && current_cell_notes.length ? current_cell_notes.split(', ') : new Array;
843 all_cell_notes.push(note_name);
844 jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes', all_cell_notes.join(', '));
845 }
846 // increase counter
847 counter++;
848 }
849 // close modal
850 hideVboDialogRdaynotes();
851 // reset input fields
852 jQuery('#vbo-newrdnote-name').val('');
853 jQuery('#vbo-newrdnote-descr').val('');
854 jQuery('#vbo-newrdnote-cdays').val('0').trigger('change');
855 } catch (e) {
856 console.log(res);
857 alert('Invalid response');
858 return false;
859 }
860 }).fail(function() {
861 alert('Request failed');
862 });
863 }
864
865 function vboRdayNoteCdaysCount() {
866 var cdays = parseInt(jQuery('#vbo-newrdnote-cdays').val());
867 var defymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd');
868 var defreadymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd');
869 defreadymd = !defreadymd || !defreadymd.length ? defymd : defreadymd;
870 if (isNaN(cdays) || cdays < 1) {
871 jQuery('.vbo-newrdnote-dayto-val').text(defreadymd);
872 return;
873 }
874 // calculate target (until) date
875 var targetdate = new Date(defymd);
876 targetdate.setDate(targetdate.getDate() + cdays);
877 var target_y = targetdate.getFullYear();
878 var target_m = targetdate.getMonth() + 1;
879 target_m = target_m < 10 ? '0' + target_m : target_m;
880 var target_d = targetdate.getDate();
881 target_d = target_d < 10 ? '0' + target_d : target_d;
882 // display target date
883 var display_target = target_y + '-' + target_m + '-' + target_d;
884 // check if we can get the "read ymd property"
885 if (jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').length) {
886 display_target = jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').attr('data-readymd');
887 }
888 jQuery('.vbo-newrdnote-dayto-val').text(display_target);
889 }
890
891 jQuery(function() {
892
893 jQuery('.vbo-tableaux-togglefullscreen').click(function() {
894 if (jQuery('.vbo-tableaux-outer').hasClass('vbo-tableaux-fullscreen')) {
895 jQuery(this).find('i').addClass('fa-expand').removeClass('fa-compress');
896 jQuery('.vbo-tableaux-outer').removeClass('vbo-tableaux-fullscreen');
897 } else {
898 jQuery(this).find('i').addClass('fa-compress').removeClass('fa-expand');
899 jQuery('.vbo-tableaux-outer').addClass('vbo-tableaux-fullscreen');
900 }
901 jQuery(this).blur();
902 });
903
904 jQuery('.vbo-tableaux-booking').click(function() {
905 jQuery('.vbdialog-inner-tableaux').html('');
906 var attrs = jQuery(this).data();
907 var bid = attrs['bid'];
908 if (!attrs.hasOwnProperty('party')) {
909 var first = jQuery(this).closest('tr').find('.vbo-tableaux-booking[data-bid="'+bid+'"]').first();
910 if (!first) {
911 return false;
912 }
913 first.trigger('click');
914 return;
915 }
916 // prepare data to be displayed:
917 var ovcont = '';
918 // find room name
919 var rname = jQuery(this).closest('tr').find('.vbo-tableaux-roomname').text();
920 if (rname && rname.length) {
921 // try to find room index
922 var rindex = '';
923 if (jQuery(this).find('.vbo-tableaux-roomindex').length) {
924 rindex = jQuery(this).find('.vbo-tableaux-roomindex').text();
925 rindex = rindex.length ? ' ' + rindex : rindex;
926 }
927 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBSEARCHRESROOM') + '</span><span class="vbo-tableaux-bookdet-val">' + rname + rindex + '</span></div>';
928 }
929 //
930 if (attrs.hasOwnProperty('tnominative')) {
931 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBOCUSTOMERNOMINATIVE') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['tnominative']+'</span></div>';
932 }
933 if (attrs.hasOwnProperty('phone')) {
934 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('ORDER_PHONE') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['phone']+'</span></div>';
935 }
936 if (attrs.hasOwnProperty('party')) {
937 var guests = attrs['party'].split(';');
938 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBFORMADULTS') + '</span><span class="vbo-tableaux-bookdet-val">' + guests[0] + '</span></div>';
939 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBFORMCHILDREN') + '</span><span class="vbo-tableaux-bookdet-val">' + guests[1] + '</span></div>';
940 if (guests.length > 2 && guests[2] > 0) {
941 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBO_PETS') + '</span><span class="vbo-tableaux-bookdet-val">' + guests[2] + '</span></div>';
942 }
943 }
944 if (attrs.hasOwnProperty('checkin')) {
945 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBPICKUP') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['checkin']+'</span></div>';
946 }
947 if (attrs.hasOwnProperty('checkout')) {
948 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBRETURN') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['checkout']+'</span></div>';
949 }
950 if (attrs.hasOwnProperty('rextrainfos')) {
951 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('VBOEXTRASERVICES') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['rextrainfos']+'</span></div>';
952 }
953 if (attrs.hasOwnProperty('sprequest')) {
954 ovcont += '<div class="vbo-tableaux-bookdet-entry"><span class="vbo-tableaux-bookdet-lbl">' + Joomla.JText._('ORDER_SPREQUESTS') + '</span><span class="vbo-tableaux-bookdet-val">'+attrs['sprequest']+'</span></div>';
955 }
956 jQuery('.vbdialog-inner-tableaux').html(ovcont);
957 jQuery('#vbdialog-overlay').fadeIn();
958 vbdialog_on = true;
959 });
960
961 jQuery(document).keydown(function(e) {
962 if ( e.keyCode == 27 ) {
963 if (vbdialog_on === true) {
964 vbDialogClose();
965 }
966 if (vbodialogfests_on === true) {
967 hideVboDialogFests();
968 }
969 if (vbodialogrdaynotes_on === true) {
970 hideVboDialogRdaynotes();
971 }
972 }
973 });
974
975 jQuery(document).mouseup(function(e) {
976 if (!vbdialog_on && !vbodialogfests_on && !vbodialogrdaynotes_on) {
977 return;
978 }
979 if (vbdialog_on) {
980 var vbdialog_cont = jQuery(".vbdialog-inner");
981 if (!vbdialog_cont.is(e.target) && vbdialog_cont.has(e.target).length === 0) {
982 vbDialogClose();
983 }
984 }
985 if (vbodialogfests_on) {
986 var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-fests");
987 if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
988 hideVboDialogFests();
989 }
990 }
991 if (vbodialogrdaynotes_on) {
992 var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-roomdaynotes");
993 if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
994 hideVboDialogRdaynotes();
995 }
996 }
997 });
998
999 // fests
1000 jQuery(document.body).on("click", "td.vbo-tableaux-daycell.vbo-tableaux-festcell", function() {
1001 if (jQuery(this).hasClass('skip-tableaux-daycell-click')) {
1002 return;
1003 }
1004 var ymd = jQuery(this).attr('data-ymd');
1005 var daytitle = jQuery(this).attr('data-readymd');
1006 // front-end tableaux does not permit to add new fests
1007 if (!vboFests.hasOwnProperty(ymd)) {
1008 return;
1009 }
1010 vboRenderFests(ymd, daytitle);
1011 });
1012
1013 // room-day notes
1014 jQuery(document.body).on("click", ".vbo-roomdaynote-display", function() {
1015 if (!jQuery(this).closest('.vbo-roomdaynote-trigger').length) {
1016 return;
1017 }
1018 var daytitle = new Array;
1019 var roomday_info = jQuery(this).closest('.vbo-roomdaynote-trigger').attr('data-roomday').split('_');
1020 // readable day
1021 var readymd = roomday_info[0];
1022 if (jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').length) {
1023 readymd = jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').attr('data-readymd');
1024 }
1025 daytitle.push(readymd);
1026 // room name
1027 if (jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').length) {
1028 daytitle.push(jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').text());
1029 }
1030 // set day title
1031 jQuery('.vbo-modal-overlay-content-head-roomdaynotes').find('h3').find('span.vbo-modal-roomdaynotes-dt').text(daytitle.join(', '));
1032 // populate current room day notes
1033 vboRenderRdayNotes(roomday_info[0], roomday_info[1], roomday_info[2], readymd);
1034 // display modal
1035 jQuery('.vbo-modal-overlay-block-roomdaynotes').fadeIn();
1036 vbodialogrdaynotes_on = true;
1037 //
1038 });
1039
1040 <?php
1041 if ($this->past_days) {
1042 // let the tableaux horizontal scroll reach today's date
1043 ?>
1044 let today_cell_el = document.querySelector('.vbo-tableaux-daycell.vbo-tableaux-todaycell');
1045 if (today_cell_el) {
1046 let first_cell_width = document.querySelector('.vbo-tableaux-firstrow')?.querySelector('.vbo-tableaux-emptycell')?.offsetWidth;
1047 let yscroll = today_cell_el.offsetLeft - first_cell_width - document.querySelector('.vbo-table-responsive.vbo-tableaux-tbl-wrap').offsetLeft
1048 document.querySelector('.vbo-table-responsive.vbo-tableaux-tbl-wrap').scrollLeft = (yscroll > 0 ? yscroll : 0);
1049 }
1050 <?php
1051 }
1052 ?>
1053 });
1054 </script>
1055