| 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 |
$roomids = $this->roomids; |
| 14 |
$rooms = $this->rooms; |
| 15 |
$rooms_busy = $this->rooms_busy; |
| 16 |
$months = $this->months; |
| 17 |
$fromts = $this->fromts; |
| 18 |
$tots = $this->tots; |
| 19 |
|
| 20 |
$vbo_app = VikBooking::getVboApplication(); |
| 21 |
$vbo_app->loadSelect2(); |
| 22 |
$vbo_app->loadDatePicker(); |
| 23 |
$vbo_app->prepareJavaScriptCurrency(); |
| 24 |
|
| 25 |
JHtml::fetch('script', VBO_ADMIN_URI . 'resources/js_upload/jquery.stickytableheaders.min.js'); |
| 26 |
|
| 27 |
$nowdf = VikBooking::getDateFormat(true); |
| 28 |
if ($nowdf == "%d/%m/%Y") { |
| 29 |
$df = 'd/m/Y'; |
| 30 |
} elseif ($nowdf == "%m/%d/%Y") { |
| 31 |
$df = 'm/d/Y'; |
| 32 |
} else { |
| 33 |
$df = 'Y/m/d'; |
| 34 |
} |
| 35 |
$datesep = VikBooking::getDateSeparator(true); |
| 36 |
$juidf = $nowdf == "%d/%m/%Y" ? 'dd/mm/yy' : ($nowdf == "%m/%d/%Y" ? 'mm/dd/yy' : 'yy/mm/dd'); |
| 37 |
|
| 38 |
$month = VikRequest::getInt('month', 0, 'request'); |
| 39 |
$printtableaux = VikRequest::getInt('printtableaux', 0, 'request'); |
| 40 |
|
| 41 |
$colortags = VikBooking::loadBookingsColorTags(); |
| 42 |
|
| 43 |
$days_labels = array( |
| 44 |
JText::translate('VBSUN'), |
| 45 |
JText::translate('VBMON'), |
| 46 |
JText::translate('VBTUE'), |
| 47 |
JText::translate('VBWED'), |
| 48 |
JText::translate('VBTHU'), |
| 49 |
JText::translate('VBFRI'), |
| 50 |
JText::translate('VBSAT'), |
| 51 |
); |
| 52 |
$months_labels = array( |
| 53 |
JText::translate('VBMONTHONE'), |
| 54 |
JText::translate('VBMONTHTWO'), |
| 55 |
JText::translate('VBMONTHTHREE'), |
| 56 |
JText::translate('VBMONTHFOUR'), |
| 57 |
JText::translate('VBMONTHFIVE'), |
| 58 |
JText::translate('VBMONTHSIX'), |
| 59 |
JText::translate('VBMONTHSEVEN'), |
| 60 |
JText::translate('VBMONTHEIGHT'), |
| 61 |
JText::translate('VBMONTHNINE'), |
| 62 |
JText::translate('VBMONTHTEN'), |
| 63 |
JText::translate('VBMONTHELEVEN'), |
| 64 |
JText::translate('VBMONTHTWELVE'), |
| 65 |
); |
| 66 |
$long_months_labels = $months_labels; |
| 67 |
foreach ($months_labels as $i => $v) { |
| 68 |
$months_labels[$i] = function_exists('mb_substr') ? mb_substr($v, 0, 3, 'UTF-8') : substr($v, 0, 3); |
| 69 |
} |
| 70 |
|
| 71 |
?> |
| 72 |
<div class="vbo-tableaux-container"> |
| 73 |
<form name="adminForm" action="index.php?option=com_vikbooking&task=tableaux" method="post" id="adminForm"> |
| 74 |
<div class="vbo-tableaux-months-wrap"> |
| 75 |
<?php |
| 76 |
foreach ($months as $mdata) { |
| 77 |
?> |
| 78 |
<div class="vbo-tableaux-month-cont"> |
| 79 |
<div class="vbo-tableaux-month-link<?php echo $month == $mdata['from'] ? ' vbo-tableaux-month-link-active' : ''; ?>"> |
| 80 |
<span class="vbo-tableaux-selmonth" data-ts="<?php echo $mdata['from']; ?>" data-from="<?php echo date($df, $mdata['from']); ?>" data-to="<?php echo date($df, $mdata['to']); ?>"><?php echo $mdata['name']; ?></span> |
| 81 |
</div> |
| 82 |
</div> |
| 83 |
<?php |
| 84 |
} |
| 85 |
?> |
| 86 |
</div> |
| 87 |
<div id="filter-bar" class="btn-toolbar vbo-btn-toolbar vbo-tableaux-filters" style="width: 100%; display: inline-block;"> |
| 88 |
<div class="btn-group pull-left" style="font-size: 12px;"> |
| 89 |
<span class="vbo-toolbar-multiselect-wrap"> |
| 90 |
<?php |
| 91 |
echo $vbo_app->renderElementsDropDown([ |
| 92 |
'id' => 'roomsel', |
| 93 |
'elements' => 'listings', |
| 94 |
'placeholder' => JText::translate('VBO_LISTINGS'), |
| 95 |
'allow_clear' => 1, |
| 96 |
'attributes' => [ |
| 97 |
'name' => 'roomids[]', |
| 98 |
'multiple' => 'multiple', |
| 99 |
], |
| 100 |
'load_categories' => 1, |
| 101 |
'selected_values' => (array) JFactory::getApplication()->input->get('roomids', [], 'array'), |
| 102 |
]); |
| 103 |
?> |
| 104 |
</span> |
| 105 |
</div> |
| 106 |
<div class="btn-group pull-left"> |
| 107 |
<span style="font-size: 15px;"> </span> |
| 108 |
</div> |
| 109 |
<div class="btn-group pull-left input-append"> |
| 110 |
<input type="text" id="vbo-date-from" placeholder="<?php echo JText::translate('VBNEWSEASONONE'); ?>" value="<?php echo date($df, $fromts); ?>" size="14" name="tbxfromdate" onfocus="this.blur();" /> |
| 111 |
<button type="button" class="btn" id="vbo-date-from-trig"><i class="icon-calendar"></i></button> |
| 112 |
</div> |
| 113 |
<div class="btn-group pull-left input-append"> |
| 114 |
<input type="text" id="vbo-date-to" placeholder="<?php echo JText::translate('VBNEWSEASONTWO'); ?>" value="<?php echo date($df, $tots); ?>" size="14" name="tbxtodate" onfocus="this.blur();" /> |
| 115 |
<button type="button" class="btn" id="vbo-date-to-trig"><i class="icon-calendar"></i></button> |
| 116 |
</div> |
| 117 |
<div class="btn-group pull-left"> |
| 118 |
<span style="font-size: 15px;"> </span> |
| 119 |
</div> |
| 120 |
<div class="btn-group pull-left"> |
| 121 |
<button type="submit" class="btn"><i class="icon-search"></i> <?php echo JText::translate('VBAPPLY'); ?></button> |
| 122 |
</div> |
| 123 |
<div class="btn-group pull-right"> |
| 124 |
<a href="javascript: void(0);" onclick="VBOCore.emitEvent('vbo-tool-permissions-modal-toggle');" class="vbo-perms-operators"><i class="vboicn-user-plus icn-nomargin"></i> <span><?php echo JText::translate('VBOPERMSOPERATORS'); ?></span></a> |
| 125 |
</div> |
| 126 |
<div class="btn-group pull-right"> |
| 127 |
<a href="javascript: void(0);" onclick="vboSendPrintTableaux();" class="vbcsvexport"><?php VikBookingIcons::e('print'); ?> <span><?php echo JText::translate('VBOPRINT'); ?></span></a> |
| 128 |
</div> |
| 129 |
</div> |
| 130 |
<input type="hidden" name="month" id="vbo-month" value="<?php echo $month; ?>" /> |
| 131 |
<input type="hidden" name="task" value="tableaux" /> |
| 132 |
<input type="hidden" name="option" value="com_vikbooking" /> |
| 133 |
</form> |
| 134 |
|
| 135 |
<?php |
| 136 |
/** |
| 137 |
* Render the permissions layout to manage the permissions of |
| 138 |
* a specific tool, tableaux, for all the operators. |
| 139 |
* |
| 140 |
* @since 1.16.9 (J) - 1.6.9 (WP) |
| 141 |
*/ |
| 142 |
$layout_data = [ |
| 143 |
'tool' => 'tableaux', |
| 144 |
]; |
| 145 |
// render the permissions layout |
| 146 |
echo JLayoutHelper::render('operators.permissions', $layout_data); |
| 147 |
|
| 148 |
// count the cells per month |
| 149 |
$thead_info = array(); |
| 150 |
$months_days = array(); |
| 151 |
$nowinfo = getdate($fromts); |
| 152 |
while ($nowinfo[0] <= $tots) { |
| 153 |
$mkey = $nowinfo['mon'] . '_' . $nowinfo['year']; |
| 154 |
if (!isset($months_days[$mkey])) { |
| 155 |
$months_days[$mkey] = 0; |
| 156 |
} |
| 157 |
$months_days[$mkey]++; |
| 158 |
// push information for the table head |
| 159 |
array_push($thead_info, array( |
| 160 |
'mon' => $long_months_labels[($nowinfo['mon'] - 1)], |
| 161 |
'mday' => $nowinfo['mday'], |
| 162 |
'wday' => $days_labels[$nowinfo['wday']], |
| 163 |
'year' => $nowinfo['year'], |
| 164 |
'ts' => $nowinfo[0], |
| 165 |
)); |
| 166 |
// next loop |
| 167 |
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year'])); |
| 168 |
} |
| 169 |
|
| 170 |
// today |
| 171 |
$todaydt = date('Y-m-d'); |
| 172 |
?> |
| 173 |
|
| 174 |
<div class="vbo-tableaux-tbl-container"> |
| 175 |
<div class="vbo-table-responsive vbo-tableaux-tbl-wrap" id="vbo-tableaux-table-scroller"> |
| 176 |
<table class="vbo-table vbo-tableaux-table"> |
| 177 |
<thead class="vbo-tableaux-table-head" style="display: none;"> |
| 178 |
<tr class="vbo-tableaux-table-head-row"> |
| 179 |
<th class="vbo-tableaux-table-head-cell vbo-tableaux-table-head-cell-empty"> </th> |
| 180 |
<?php |
| 181 |
foreach ($thead_info as $head_day) { |
| 182 |
?> |
| 183 |
<th class="vbo-tableaux-table-head-cell"> |
| 184 |
<div class="vbo-tableaux-table-head-cell-monyear"> |
| 185 |
<span><?php echo $head_day['mon'] . ' ' . $head_day['year']; ?></span> |
| 186 |
</div> |
| 187 |
<div class="vbo-tableaux-table-head-cell-wmday"> |
| 188 |
<span><?php echo $head_day['wday'] . ' ' . $head_day['mday']; ?></span> |
| 189 |
</div> |
| 190 |
</th> |
| 191 |
<?php |
| 192 |
} |
| 193 |
?> |
| 194 |
</tr> |
| 195 |
</thead> |
| 196 |
<tbody> |
| 197 |
<tr class="vbo-tableaux-monthsrow"> |
| 198 |
<td class="vbo-tableaux-emptycell"> </td> |
| 199 |
<?php |
| 200 |
foreach ($months_days as $mkey => $totdays) { |
| 201 |
$mkeyparts = explode('_', $mkey); |
| 202 |
?> |
| 203 |
<td class="vbo-tableaux-monthcell" colspan="<?php echo $totdays; ?>"><?php echo $long_months_labels[($mkeyparts[0] - 1)] . ' ' . $mkeyparts[1]; ?></td> |
| 204 |
<?php |
| 205 |
} |
| 206 |
?> |
| 207 |
</tr> |
| 208 |
<tr class="vbo-tableaux-firstrow"> |
| 209 |
<td class="vbo-tableaux-emptycell"> </td> |
| 210 |
<?php |
| 211 |
$newmonth = 0; |
| 212 |
$nowinfo = getdate($fromts); |
| 213 |
while ($nowinfo[0] <= $tots) { |
| 214 |
$nowinfo_ymd = date('Y-m-d', $nowinfo[0]); |
| 215 |
$monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : ''; |
| 216 |
$monthclass = $nowinfo_ymd == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass; |
| 217 |
$newmonth = $nowinfo['mon']; |
| 218 |
$read_day = $days_labels[$nowinfo['wday']] . ' ' . $nowinfo['mday'] . ' ' . $months_labels[($nowinfo['mon'] - 1)] . ' ' . $nowinfo['year']; |
| 219 |
$fest_class = isset($this->festivities[$nowinfo_ymd]) ? ' vbo-tableaux-festcell' : ''; |
| 220 |
?> |
| 221 |
<td class="vbo-tableaux-daycell<?php echo $monthclass . $fest_class; ?>"<?php echo $printtableaux > 0 ? ' width="100' : ''; ?> data-ymd="<?php echo $nowinfo_ymd; ?>" data-readymd="<?php echo $read_day; ?>"> |
| 222 |
<div class="vbo-tableaux-day-cont"> |
| 223 |
<span class="vbo-tableaux-day-wday"><?php echo $days_labels[$nowinfo['wday']]; ?></span> |
| 224 |
<span class="vbo-tableaux-day-mday"><?php echo $nowinfo['mday']; ?></span> |
| 225 |
</div> |
| 226 |
</td> |
| 227 |
<?php |
| 228 |
// next loop |
| 229 |
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year'])); |
| 230 |
} |
| 231 |
?> |
| 232 |
</tr> |
| 233 |
<?php |
| 234 |
$rooms_features_map = array(); |
| 235 |
$rooms_features_bookings = array(); |
| 236 |
$colortags_map = array(); |
| 237 |
foreach ($rooms as $rid => $rdata) { |
| 238 |
// distinctive features |
| 239 |
$room_params = !empty($rdata['params']) ? json_decode($rdata['params'], true) : array(); |
| 240 |
if (is_array($room_params) && array_key_exists('features', $room_params) && count($room_params['features']) > 0) { |
| 241 |
$rooms_features_map[$rid] = array(); |
| 242 |
foreach ($room_params['features'] as $rind => $rfeatures) { |
| 243 |
foreach ($rfeatures as $fname => $fval) { |
| 244 |
if (strlen($fval)) { |
| 245 |
$rooms_features_map[$rid][$rind] = '#'.$fval; |
| 246 |
break; |
| 247 |
} |
| 248 |
} |
| 249 |
} |
| 250 |
if (!(count($rooms_features_map[$rid]) > 0)) { |
| 251 |
unset($rooms_features_map[$rid]); |
| 252 |
} |
| 253 |
} |
| 254 |
// extra class for single-unit rooms |
| 255 |
$room_extra_class = $rdata['units'] == 1 ? 'vbo-tableaux-booking-singleunit ' : ''; |
| 256 |
?> |
| 257 |
<tr class="vbo-tableaux-roomrow"> |
| 258 |
<td class="vbo-tableaux-roomname" data-roomid="<?php echo $rdata['id']; ?>"><?php echo $rdata['name']; ?></td> |
| 259 |
<?php |
| 260 |
$nowinfo = getdate($fromts); |
| 261 |
$bookbuffer = array(); |
| 262 |
$prevbuffer = array(); |
| 263 |
$positions = array(); |
| 264 |
$newmonth = 0; |
| 265 |
while ($nowinfo[0] <= $tots) { |
| 266 |
$nowinfo_ymd = date('Y-m-d', $nowinfo[0]); |
| 267 |
$monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : ''; |
| 268 |
$monthclass = $nowinfo_ymd == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass; |
| 269 |
$newmonth = $nowinfo['mon']; |
| 270 |
|
| 271 |
/** |
| 272 |
* Critical dates defined at room-day level, or for any sub-unit. |
| 273 |
* |
| 274 |
* @since 1.13.5 |
| 275 |
*/ |
| 276 |
$rdaynote_class = ' vbo-roomdaynote-empty'; |
| 277 |
$rdaynote_icn = 'far fa-sticky-note'; |
| 278 |
$cell_rdnotes = ''; |
| 279 |
$rdnkeys_lookup = range(0, $rdata['units']); |
| 280 |
$rdaynote_keyids = array(); |
| 281 |
$glob_rdn_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_0'; |
| 282 |
// find room-day note keys with some notes (room-day level or subroom-day level) |
| 283 |
foreach ($rdnkeys_lookup as $lookup_index) { |
| 284 |
$rdaynote_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_' . $lookup_index; |
| 285 |
if (isset($this->rdaynotes[$rdaynote_keyid])) { |
| 286 |
// push associative index with notes |
| 287 |
$rdaynote_keyids[$lookup_index] = $rdaynote_keyid; |
| 288 |
} |
| 289 |
} |
| 290 |
if (count($rdaynote_keyids)) { |
| 291 |
// some notes exist for this combination of date, room ID and subunit |
| 292 |
$rdaynote_class = ' vbo-roomdaynote-full'; |
| 293 |
$rdaynote_icn = 'sticky-note'; |
| 294 |
/** |
| 295 |
* Try to populate the notes for this room-day cell |
| 296 |
* only if the previous day does not have the same note. |
| 297 |
* Just the first readable room-day cell should have notes. |
| 298 |
*/ |
| 299 |
$notes_titles = array(); |
| 300 |
$yesterday_ts = mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] - 1), $nowinfo['year']); |
| 301 |
$yesterday_ymd = date('Y-m-d', $yesterday_ts); |
| 302 |
// loop through all the keys with notes |
| 303 |
foreach ($rdaynote_keyids as $lookup_index => $rdaynote_keyid) { |
| 304 |
$yesterday_keyid = $yesterday_ymd . '_' . $rdata['id'] . '_' . $lookup_index; |
| 305 |
foreach ($this->rdaynotes[$rdaynote_keyid]['info'] as $today_note) { |
| 306 |
// only manual (custom) room-day notes will be displayed |
| 307 |
$display_note = ($today_note->type == 'custom'); |
| 308 |
if (isset($this->rdaynotes[$yesterday_keyid])) { |
| 309 |
// make sure the same note is not present for yesterday |
| 310 |
foreach ($this->rdaynotes[$yesterday_keyid]['info'] as $yesterday_note) { |
| 311 |
if ($today_note->type == $yesterday_note->type && $today_note->name == $yesterday_note->name) { |
| 312 |
// same note available also for yesterday |
| 313 |
$display_note = false; |
| 314 |
break; |
| 315 |
} |
| 316 |
} |
| 317 |
} |
| 318 |
if ($display_note) { |
| 319 |
// push just the name of the note |
| 320 |
array_push($notes_titles, $today_note->name); |
| 321 |
} |
| 322 |
} |
| 323 |
} |
| 324 |
// separate all notes (if any) with comma |
| 325 |
$cell_rdnotes = implode(', ', $notes_titles); |
| 326 |
// |
| 327 |
} |
| 328 |
// |
| 329 |
|
| 330 |
?> |
| 331 |
<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); ?>"> |
| 332 |
<?php |
| 333 |
$room_bookings = array(); |
| 334 |
if (isset($rooms_busy[$rid])) { |
| 335 |
foreach ($rooms_busy[$rid] as $b) { |
| 336 |
$tmpone = getdate($b['checkin']); |
| 337 |
$ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']); |
| 338 |
$tmptwo = getdate($b['checkout']); |
| 339 |
$conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']); |
| 340 |
$b['basefrom'] = $ritts; |
| 341 |
$b['baseto'] = $conts; |
| 342 |
if ($nowinfo[0] >= $ritts && $nowinfo[0] <= $conts) { |
| 343 |
array_push($room_bookings, $b); |
| 344 |
} |
| 345 |
} |
| 346 |
/** |
| 347 |
* By default, we attempt to sort the bookings for this day by room index. |
| 348 |
* |
| 349 |
* @since 1.13.5 (J) - 1.3.5 (WP) |
| 350 |
*/ |
| 351 |
if (count($room_bookings)) { |
| 352 |
$rindexes_map = array(); |
| 353 |
foreach ($room_bookings as $rbk => $rbval) { |
| 354 |
$rindexes_map[$rbk] = isset($rbval['indexes']) ? $rbval['indexes'] : ''; |
| 355 |
} |
| 356 |
asort($rindexes_map); |
| 357 |
$room_bookings_copy = array(); |
| 358 |
foreach ($rindexes_map as $rbk => $rbval) { |
| 359 |
array_push($room_bookings_copy, $room_bookings[$rbk]); |
| 360 |
} |
| 361 |
$room_bookings = $room_bookings_copy; |
| 362 |
} |
| 363 |
// |
| 364 |
} |
| 365 |
if (count($room_bookings) && count($bookbuffer)) { |
| 366 |
// sort bookings according to the previous map |
| 367 |
$newbookings = array(); |
| 368 |
foreach ($bookbuffer as $oid) { |
| 369 |
foreach ($room_bookings as $kb => $rbook) { |
| 370 |
if ($oid == $rbook['idorder']) { |
| 371 |
// get this key first |
| 372 |
$newbookings[$kb] = $rbook; |
| 373 |
// do not break the loop as there could be multiple idorder, just continue |
| 374 |
continue; |
| 375 |
} |
| 376 |
} |
| 377 |
} |
| 378 |
if (count($newbookings)) { |
| 379 |
// merge array by keys by unsetting double keys from second array |
| 380 |
$room_bookings = $newbookings + $room_bookings; |
| 381 |
} |
| 382 |
// copy buffer before reset to see whether this is the first cell displayed for the booking |
| 383 |
$prevbuffer = $bookbuffer; |
| 384 |
// reset buffer to fill the current day bookings |
| 385 |
$bookbuffer = array(); |
| 386 |
} |
| 387 |
$indexpos = 0; |
| 388 |
foreach ($room_bookings as $k => $rbook) { |
| 389 |
$contclass = 'stay'; |
| 390 |
if ($rbook['basefrom'] == $nowinfo[0]) { |
| 391 |
$contclass = 'checkin'; |
| 392 |
} elseif ($rbook['baseto'] == $nowinfo[0]) { |
| 393 |
$contclass = 'checkout'; |
| 394 |
} |
| 395 |
$shortstaycls = ''; |
| 396 |
if (ceil(($rbook['baseto'] - $rbook['basefrom']) / 86400) < 2) { |
| 397 |
$shortstaycls = ' vbo-tableaux-booking-short'; |
| 398 |
} |
| 399 |
//check position |
| 400 |
$pos = $indexpos; |
| 401 |
if (isset($positions[$rbook['idorder']]) && $indexpos < $positions[$rbook['idorder']]) { |
| 402 |
// print empty blocks to give the right position to this booking |
| 403 |
$pos = $indexpos.'-'.$positions[$rbook['idorder']]; |
| 404 |
$looplim = ($positions[$rbook['idorder']] - $indexpos); |
| 405 |
for ($i = 0; $i < $looplim; $i++) { |
| 406 |
$indexpos++; |
| 407 |
?> |
| 408 |
<div class="<?php echo $room_extra_class; ?>vbo-tableaux-booking vbo-tableaux-booking-empty"> |
| 409 |
<span> </span> |
| 410 |
</div> |
| 411 |
<?php |
| 412 |
} |
| 413 |
$pos .= '-'.$indexpos; |
| 414 |
} |
| 415 |
// push position |
| 416 |
if (!isset($positions[$rbook['idorder']])) { |
| 417 |
$positions[$rbook['idorder']] = $indexpos; |
| 418 |
} |
| 419 |
// push booking to the buffer for the ordering in the next loop |
| 420 |
array_push($bookbuffer, $rbook['idorder']); |
| 421 |
|
| 422 |
// cell content |
| 423 |
$cellcont = ' '; |
| 424 |
|
| 425 |
// booking color tag (if enabled from overv View through cookie or session) |
| 426 |
if ($this->pbmode == 'tags' && !isset($colortags_map[$rbook['idorder']])) { |
| 427 |
$colortags_map[$rbook['idorder']] = VikBooking::applyBookingColorTag($rbook); |
| 428 |
} |
| 429 |
|
| 430 |
if (!in_array($rbook['idorder'], $prevbuffer)) { |
| 431 |
// first time we print the details for this booking - compose the content of the element |
| 432 |
$cellcont = ''; |
| 433 |
|
| 434 |
// customer details |
| 435 |
if (!empty($rbook['first_name']) || !empty($rbook['last_name'])) { |
| 436 |
/** |
| 437 |
* Check if we need to display a profile picture or a channel logo. |
| 438 |
* |
| 439 |
* @since 1.16.0 (J) - 1.6.0 (WP) |
| 440 |
*/ |
| 441 |
$booking_avatar_src = null; |
| 442 |
$booking_avatar_alt = null; |
| 443 |
if (!empty($rbook['pic'])) { |
| 444 |
// customer profile picture |
| 445 |
$booking_avatar_src = strpos($rbook['pic'], 'http') === 0 ? $rbook['pic'] : VBO_SITE_URI . 'resources/uploads/' . $rbook['pic']; |
| 446 |
$booking_avatar_alt = basename($booking_avatar_src); |
| 447 |
} elseif (!empty($rbook['channel'])) { |
| 448 |
// channel logo |
| 449 |
$logo_helper = VikBooking::getVcmChannelsLogo($rbook['channel'], $get_istance = true); |
| 450 |
if ($logo_helper !== false) { |
| 451 |
$booking_avatar_src = $logo_helper->getSmallLogoURL(); |
| 452 |
$booking_avatar_alt = $logo_helper->provenience; |
| 453 |
} |
| 454 |
} |
| 455 |
|
| 456 |
if (!empty($booking_avatar_src)) { |
| 457 |
// make sure the alt attribute is not too long in case of broken images |
| 458 |
$booking_avatar_alt = !empty($booking_avatar_alt) && strlen($booking_avatar_alt) > 15 ? '...' . substr($booking_avatar_alt, -12) : $booking_avatar_alt; |
| 459 |
// append booking avatar image |
| 460 |
$cellcont .= '<span class="vbo-tableaux-booking-avatar"><img src="' . $booking_avatar_src . '" class="vbo-tableaux-booking-avatar-img" ' . (!empty($booking_avatar_alt) ? 'alt="' . htmlspecialchars($booking_avatar_alt) . '" ' : '') . '/></span>'; |
| 461 |
} |
| 462 |
|
| 463 |
// customer record |
| 464 |
$cellcont .= '<span class="vbo-tableaux-guest-name">' . $rbook['first_name'] . ' ' . $rbook['last_name'] . '</span>'; |
| 465 |
} else { |
| 466 |
// parse the customer data string |
| 467 |
$custdata_parts = explode("\n", $rbook['custdata']); |
| 468 |
$enoughinfo = false; |
| 469 |
if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) { |
| 470 |
// get the first two fields |
| 471 |
$custvalues = array(); |
| 472 |
foreach ($custdata_parts as $custdet) { |
| 473 |
if (strlen($custdet) < 1) { |
| 474 |
continue; |
| 475 |
} |
| 476 |
$custdet_parts = explode(':', $custdet); |
| 477 |
if (count($custdet_parts) >= 2) { |
| 478 |
unset($custdet_parts[0]); |
| 479 |
array_push($custvalues, trim(implode(':', $custdet_parts))); |
| 480 |
} |
| 481 |
if (count($custvalues) > 1) { |
| 482 |
break; |
| 483 |
} |
| 484 |
} |
| 485 |
if (count($custvalues) > 1) { |
| 486 |
$enoughinfo = true; |
| 487 |
$cellcont .= '<span class="vbo-tableaux-guest-name">' . implode(' ', $custvalues) . '</span>'; |
| 488 |
} |
| 489 |
} |
| 490 |
if (!$enoughinfo) { |
| 491 |
$cellcont .= '<span class="vbo-tableaux-guest-name">' . $rbook['idorder'] . '</span>'; |
| 492 |
} |
| 493 |
} |
| 494 |
|
| 495 |
// distinctive features |
| 496 |
if (!empty($rbook['indexes']) && isset($rooms_features_map[$rid])) { |
| 497 |
$bookindexes = explode(';', $rbook['indexes']); |
| 498 |
$roomindexes = explode(';', $rbook['roomids']); |
| 499 |
if (!isset($rooms_features_bookings[$rid.'_'.$rbook['idorder']])) { |
| 500 |
// 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) |
| 501 |
$rooms_features_bookings[$rid.'_'.$rbook['idorder']] = 0; |
| 502 |
} else { |
| 503 |
// increment index for this room booking |
| 504 |
$rooms_features_bookings[$rid.'_'.$rbook['idorder']]++; |
| 505 |
} |
| 506 |
// seek for the index occurrence of this room in the list of rooms booked |
| 507 |
$count_pos = -1; |
| 508 |
$room_pos = null; |
| 509 |
foreach ($roomindexes as $rk => $rv) { |
| 510 |
if ((int)$rv == (int)$rid) { |
| 511 |
$count_pos++; |
| 512 |
if ($count_pos == $rooms_features_bookings[$rid.'_'.$rbook['idorder']]) { |
| 513 |
$room_pos = $rk; |
| 514 |
break; |
| 515 |
} |
| 516 |
} |
| 517 |
} |
| 518 |
$nowfeatindex = isset($bookindexes[$room_pos]) ? $room_pos : null; |
| 519 |
if (!is_null($room_pos) && isset($bookindexes[$nowfeatindex]) && isset($rooms_features_map[$rid][$bookindexes[$nowfeatindex]])) { |
| 520 |
// get this room feature |
| 521 |
$cellcont .= '<span class="vbo-tableaux-roomindex">' . $rooms_features_map[$rid][$bookindexes[$nowfeatindex]] . '</span> '; |
| 522 |
} |
| 523 |
} |
| 524 |
|
| 525 |
// add invoice/receipt number if available (taken from booking color tag) |
| 526 |
if (isset($colortags_map[$rbook['idorder']]) && count($colortags_map[$rbook['idorder']])) { |
| 527 |
if (isset($colortags_map[$rbook['idorder']]['invoice_number'])) { |
| 528 |
// invoice number |
| 529 |
$invstyle = isset($colortags_map[$rbook['idorder']]['fontcolor']) ? ' style="color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';"' : ''; |
| 530 |
$cellcont .= ' <a class="vbo-tableaux-invlink"'.$invstyle.' href="'.VBO_SITE_URI.'helpers/invoices/generated/'.$colortags_map[$rbook['idorder']]['invoice_file_name'].'" target="_blank"><i class="'.VikBookingIcons::i('file-text').'"></i> '.$colortags_map[$rbook['idorder']]['invoice_number'].'</a>'; |
| 531 |
} elseif (isset($colortags_map[$rbook['idorder']]['receipt_number'])) { |
| 532 |
// receipt number |
| 533 |
$cellcont .= ' <i class="'.VikBookingIcons::i('file-text-o').'" title="'.JText::translate('VBOFISCRECEIPT').' #'.$colortags_map[$rbook['idorder']]['receipt_number'].'"></i>'; |
| 534 |
} |
| 535 |
} |
| 536 |
} |
| 537 |
|
| 538 |
// color tag styles |
| 539 |
$cont_styles = array(); |
| 540 |
$span_styles = array(); |
| 541 |
if (isset($colortags_map[$rbook['idorder']]) && count($colortags_map[$rbook['idorder']])) { |
| 542 |
$cont_styles[] = 'background-color: '.$colortags_map[$rbook['idorder']]['color'].';'; |
| 543 |
if (isset($colortags_map[$rbook['idorder']]['fontcolor'])) { |
| 544 |
$cont_styles[] = 'color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';'; |
| 545 |
$span_styles[] = 'color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';'; |
| 546 |
} |
| 547 |
} |
| 548 |
|
| 549 |
// try to guess if this will be the last element of the day (single-unit rooms, check-out day with wider space because of no check-ins on the same day) |
| 550 |
$last_checkout_class = ''; |
| 551 |
if ($rdata['units'] == 1 && strpos($contclass, 'checkout') !== false && !isset($room_bookings[($k + 1)])) { |
| 552 |
$last_checkout_class = 'vbo-tableaux-booking-checkout-last '; |
| 553 |
} |
| 554 |
?> |
| 555 |
<div class="<?php echo $room_extra_class . $last_checkout_class; ?>vbo-tableaux-booking vbo-tableaux-booking-<?php echo $contclass . $shortstaycls . ' vbo-' . $pos; ?>"<?php echo count($cont_styles) ? ' style="'.implode('', $cont_styles).'"' : ''; ?> data-bid="<?php echo $rbook['idorder']; ?>"> |
| 556 |
<span<?php echo count($span_styles) ? ' style="'.implode('', $span_styles).'"' : ''; ?>><?php echo $cellcont; ?></span> |
| 557 |
</div> |
| 558 |
<?php |
| 559 |
// increase the positioning index |
| 560 |
$indexpos++; |
| 561 |
} |
| 562 |
?> |
| 563 |
<span class="vbo-roomdaynote-trigger" data-roomday="<?php echo $glob_rdn_keyid; ?>"><?php VikBookingIcons::e($rdaynote_icn, 'vbo-roomdaynote-display'); ?></span> |
| 564 |
</td> |
| 565 |
<?php |
| 566 |
// next loop |
| 567 |
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year'])); |
| 568 |
} |
| 569 |
?> |
| 570 |
</tr> |
| 571 |
<?php |
| 572 |
} |
| 573 |
?> |
| 574 |
</tbody> |
| 575 |
</table> |
| 576 |
</div> |
| 577 |
</div> |
| 578 |
|
| 579 |
</div> |
| 580 |
|
| 581 |
<div class="vbo-modal-overlay-block vbo-modal-overlay-block-fests"> |
| 582 |
<a class="vbo-modal-overlay-close" href="javascript: void(0);"></a> |
| 583 |
<div class="vbo-modal-overlay-content vbo-modal-overlay-content-fests"> |
| 584 |
<div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-fests"> |
| 585 |
<h3><?php VikBookingIcons::e('star'); ?> <span></span></h3> |
| 586 |
</div> |
| 587 |
<div class="vbo-modal-overlay-content-body"> |
| 588 |
<div class="vbo-overlay-fests-list"></div> |
| 589 |
<div class="vbo-overlay-fests-addnew" data-ymd=""> |
| 590 |
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4> |
| 591 |
<div class="vbo-overlay-fests-addnew-elem"> |
| 592 |
<label for="vbo-newfest-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label> |
| 593 |
<input type="text" id="vbo-newfest-name" value="" /> |
| 594 |
</div> |
| 595 |
<div class="vbo-overlay-fests-addnew-elem"> |
| 596 |
<label for="vbo-newfest-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label> |
| 597 |
<textarea id="vbo-newfest-descr"></textarea> |
| 598 |
</div> |
| 599 |
<div class="vbo-overlay-fests-addnew-save"> |
| 600 |
<button type="button" class="btn btn-success" onclick="vboAddFest(this);"><?php echo JText::translate('VBSAVE'); ?></button> |
| 601 |
</div> |
| 602 |
</div> |
| 603 |
</div> |
| 604 |
</div> |
| 605 |
</div> |
| 606 |
|
| 607 |
<div class="vbo-modal-overlay-block vbo-modal-overlay-block-roomdaynotes"> |
| 608 |
<a class="vbo-modal-overlay-close" href="javascript: void(0);"></a> |
| 609 |
<div class="vbo-modal-overlay-content vbo-modal-overlay-content-roomdaynotes"> |
| 610 |
<div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-roomdaynotes"> |
| 611 |
<h3><?php VikBookingIcons::e('exclamation-circle'); ?> <span></span></h3> |
| 612 |
</div> |
| 613 |
<div class="vbo-modal-overlay-content-body"> |
| 614 |
<div class="vbo-modal-roomdaynotes-list"></div> |
| 615 |
<div class="vbo-modal-roomdaynotes-addnew" data-readymd="" data-ymd="" data-roomid="" data-subroomid=""> |
| 616 |
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4> |
| 617 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 618 |
<label for="vbo-newrdnote-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label> |
| 619 |
<input type="text" id="vbo-newrdnote-name" value="" /> |
| 620 |
</div> |
| 621 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 622 |
<label for="vbo-newrdnote-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label> |
| 623 |
<textarea id="vbo-newrdnote-descr"></textarea> |
| 624 |
</div> |
| 625 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 626 |
<label for="vbo-newrdnote-cdays"><?php echo JText::translate('VBOCONSECUTIVEDAYS'); ?></label> |
| 627 |
<input type="number" id="vbo-newrdnote-cdays" min="0" max="365" value="0" onchange="vboRdayNoteCdaysCount();" onkeyup="vboRdayNoteCdaysCount();" /> |
| 628 |
<span class="vbo-newrdnote-dayto"> |
| 629 |
<span class="vbo-newrdnote-dayto-lbl"><?php echo JText::translate('VBOUNTIL'); ?></span> |
| 630 |
<span class="vbo-newrdnote-dayto-val"></span> |
| 631 |
</span> |
| 632 |
</div> |
| 633 |
<div class="vbo-modal-roomdaynotes-addnew-save"> |
| 634 |
<button type="button" class="btn btn-success" onclick="vboAddRoomDayNote(this);"><?php echo JText::translate('VBSAVE'); ?></button> |
| 635 |
</div> |
| 636 |
</div> |
| 637 |
</div> |
| 638 |
</div> |
| 639 |
</div> |
| 640 |
|
| 641 |
<a class="vbo-basenavuri-details" href="index.php?option=com_vikbooking&task=editorder&goto=tableaux&cid[]=%d" style="display: none;"></a> |
| 642 |
<a class="vbo-basenavuri-edit" href="index.php?option=com_vikbooking&task=editbusy&goto=tableaux&cid[]=%d" style="display: none;"></a> |
| 643 |
|
| 644 |
<script type="text/javascript"> |
| 645 |
var vboFests = <?php echo json_encode($this->festivities); ?>; |
| 646 |
var vboRdayNotes = <?php echo json_encode($this->rdaynotes); ?>; |
| 647 |
var vbodialog_on = false; |
| 648 |
var vbodialogfests_on = false; |
| 649 |
var vbodialogrdaynotes_on = false; |
| 650 |
|
| 651 |
/** |
| 652 |
* Fests dialog |
| 653 |
*/ |
| 654 |
function hideVboDialogFests() { |
| 655 |
if (vbodialogfests_on === true) { |
| 656 |
jQuery(".vbo-modal-overlay-block-fests").fadeOut(400, function () { |
| 657 |
jQuery(".vbo-modal-overlay-content-fests").show(); |
| 658 |
}); |
| 659 |
vbodialogfests_on = false; |
| 660 |
} |
| 661 |
} |
| 662 |
|
| 663 |
/** |
| 664 |
* Room-day-notes dialog |
| 665 |
*/ |
| 666 |
function hideVboDialogRdaynotes() { |
| 667 |
if (vbodialogrdaynotes_on === true) { |
| 668 |
jQuery(".vbo-modal-overlay-block-roomdaynotes").fadeOut(400, function () { |
| 669 |
jQuery(".vbo-modal-overlay-content-roomdaynotes").show(); |
| 670 |
}); |
| 671 |
// reset values |
| 672 |
jQuery('#vbo-newrdnote-name').val(''); |
| 673 |
jQuery('#vbo-newrdnote-descr').val(''); |
| 674 |
jQuery('#vbo-newrdnote-cdays').val('0').trigger('change'); |
| 675 |
// turn flag off |
| 676 |
vbodialogrdaynotes_on = false; |
| 677 |
} |
| 678 |
} |
| 679 |
|
| 680 |
/* Hover Tooltip */ |
| 681 |
var hovtimer; |
| 682 |
var hovtip = false; |
| 683 |
var vboMessages = { |
| 684 |
loadingTip: "<?php echo addslashes(JText::translate('VIKLOADING')); ?>", |
| 685 |
numRooms: "<?php echo addslashes(JText::translate('VBEDITORDERROOMSNUM')); ?>", |
| 686 |
numAdults: "<?php echo addslashes(JText::translate('VBEDITORDERADULTS')); ?>", |
| 687 |
numNights: "<?php echo addslashes(JText::translate('VBDAYS')); ?>", |
| 688 |
checkinLbl: "<?php echo addslashes(JText::translate('VBPICKUPAT')); ?>", |
| 689 |
checkoutLbl: "<?php echo addslashes(JText::translate('VBRELEASEAT')); ?>", |
| 690 |
numChildren: "<?php echo addslashes(JText::translate('VBEDITORDERCHILDREN')); ?>", |
| 691 |
totalAmount: "<?php echo addslashes(JText::translate('VBEDITORDERNINE')); ?>", |
| 692 |
totalPaid: "<?php echo addslashes(JText::translate('VBPEDITBUSYTOTPAID')); ?>" |
| 693 |
}; |
| 694 |
|
| 695 |
function registerHoveringTooltip(that) { |
| 696 |
if (hovtip) { |
| 697 |
return false; |
| 698 |
} |
| 699 |
|
| 700 |
if (hovtimer) { |
| 701 |
clearTimeout(hovtimer); |
| 702 |
hovtimer = null; |
| 703 |
} |
| 704 |
|
| 705 |
var elem = jQuery(that); |
| 706 |
var cellheight = elem.outerHeight(); |
| 707 |
|
| 708 |
hovtimer = setTimeout(function() { |
| 709 |
// turn flag on |
| 710 |
hovtip = true; |
| 711 |
|
| 712 |
// calculate cell-element position |
| 713 |
let pos_top = elem.offset().top; |
| 714 |
let pos_left = elem.offset().left; |
| 715 |
let elem_height = elem.outerHeight(); |
| 716 |
let screen_width = window?.screen?.width || 0; |
| 717 |
|
| 718 |
// build tooltip block element |
| 719 |
let tooltip_block = jQuery('<div></div>'); |
| 720 |
tooltip_block.addClass('vbo-overview-tipblock'); |
| 721 |
tooltip_block.append("<div class=\"vbo-overview-tipinner\"><span class=\"vbo-overview-tiploading\">" + vboMessages.loadingTip + "</span></div>"); |
| 722 |
tooltip_block.append("<div class=\"vbo-overview-tipexpander\" style=\"display: none;\"><div class=\"vbo-overview-expandtoggle\"><i class=\"<?php echo VikBookingIcons::i('expand'); ?>\"></i></div></div>"); |
| 723 |
|
| 724 |
// calculate block position |
| 725 |
tooltip_block.css('top', (pos_top + elem_height - 16) + 'px'); |
| 726 |
// tooltip_block.css('left', (pos_left - 6) + 'px'); |
| 727 |
if (screen_width > 600 && (pos_left + 400) > screen_width) { |
| 728 |
// place the tooltip starting from right |
| 729 |
tooltip_block.css('left', (pos_left - (400 - elem.outerWidth())) + 'px'); |
| 730 |
} else { |
| 731 |
// regular placing starting from left |
| 732 |
tooltip_block.css('left', (pos_left - 6) + 'px'); |
| 733 |
} |
| 734 |
|
| 735 |
// append block to body |
| 736 |
tooltip_block.appendTo(jQuery('body')); |
| 737 |
|
| 738 |
// load tooltip bookings |
| 739 |
loadTooltipBookings(elem.attr('data-bid')); |
| 740 |
}, 900); |
| 741 |
} |
| 742 |
|
| 743 |
function unregisterHoveringTooltip() { |
| 744 |
clearTimeout(hovtimer); |
| 745 |
hovtimer = null; |
| 746 |
} |
| 747 |
|
| 748 |
/** |
| 749 |
* @deprecated 1.16.10 (J) - 1.6.10 (WP) |
| 750 |
*/ |
| 751 |
function adjustHoveringTooltip() { |
| 752 |
setTimeout(function() { |
| 753 |
var difflim = 35; |
| 754 |
var otop = jQuery(".vbo-overview-tipblock").offset().top; |
| 755 |
if (otop < difflim) { |
| 756 |
jQuery(".vbo-overview-tipblock").css("bottom", "-="+(difflim - otop)); |
| 757 |
} else { |
| 758 |
// check top position from table |
| 759 |
var tipheight = jQuery(".vbo-overview-tipblock").outerHeight(); |
| 760 |
var blocktop = jQuery(".vbo-overview-tipblock").parent().offset().top; |
| 761 |
var tabletop = jQuery(".vbo-tableaux-table").offset().top; |
| 762 |
if ((blocktop - tabletop) < tipheight) { |
| 763 |
// tooltip is going under the table, move it down the container |
| 764 |
jQuery(".vbo-overview-tipblock").css("bottom", "-"+tipheight+'px'); |
| 765 |
} |
| 766 |
// check left position from second cell |
| 767 |
var tipwidth = jQuery(".vbo-overview-tipblock").outerWidth(); |
| 768 |
var cellscndleft = jQuery('.vbo-tableaux-table').find('tr td').first().next().offset().left; |
| 769 |
var blockleft = jQuery('.vbo-overview-tipblock').parent().offset().left; |
| 770 |
if (tipwidth > (blockleft - cellscndleft)) { |
| 771 |
// tooltip should start from left: 0 going to the right |
| 772 |
jQuery(".vbo-overview-tipblock").css("left", "0px"); |
| 773 |
} |
| 774 |
} |
| 775 |
}, 100); |
| 776 |
} |
| 777 |
|
| 778 |
function hideVboTooltip() { |
| 779 |
jQuery('.vbo-overview-tipblock').remove(); |
| 780 |
hovtip = false; |
| 781 |
} |
| 782 |
|
| 783 |
function loadTooltipBookings(bid) { |
| 784 |
if (!bid || bid === undefined || !bid.length) { |
| 785 |
hideVboTooltip(); |
| 786 |
return false; |
| 787 |
} |
| 788 |
// ajax request |
| 789 |
var jqxhr = jQuery.ajax({ |
| 790 |
type: "POST", |
| 791 |
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=getbookingsinfo'); ?>", |
| 792 |
data: { |
| 793 |
tmpl: "component", |
| 794 |
idorders: bid |
| 795 |
} |
| 796 |
}).done(function(res) { |
| 797 |
try { |
| 798 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 799 |
jQuery('.vbo-overview-tiploading').remove(); |
| 800 |
var container = jQuery('.vbo-overview-tipinner'); |
| 801 |
jQuery(obj_res).each(function(k, v) { |
| 802 |
// get base navigation URIs |
| 803 |
var base_uri_details = jQuery('.vbo-basenavuri-details').attr('href'); |
| 804 |
var base_uri_edit = jQuery('.vbo-basenavuri-edit').attr('href'); |
| 805 |
|
| 806 |
// build content |
| 807 |
var bcont = "<div class=\"vbo-overview-tip-bookingcont\">"; |
| 808 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-left\">"; |
| 809 |
bcont += "<div class=\"vbo-overview-tip-bid\"><span class=\"vbo-overview-tip-lbl\">ID <span class=\"vbo-overview-tip-lbl-innerleft\"><a href=\"" + base_uri_edit.replace('%d', v.id) + "\" target=\"_blank\"><i class=\"<?php echo VikBookingIcons::i('edit'); ?>\"></i></a></span></span><span class=\"vbo-overview-tip-cnt\">"+v.id+"</span></div>"; |
| 810 |
bcont += "<div class=\"vbo-overview-tip-bstatus\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBPVIEWORDERSEIGHT')); ?></span><span class=\"vbo-overview-tip-cnt\"><div class=\"badge "+(v.status == 'confirmed' ? 'badge-success' : 'badge-warning')+"\">"+v.status_lbl+"</div></span></div>"; |
| 811 |
bcont += "<div class=\"vbo-overview-tip-bdate\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBPVIEWORDERSONE')); ?></span><span class=\"vbo-overview-tip-cnt\"><a href=\"" + base_uri_details.replace('%d', v.id) + "\" target=\"_blank\">"+v.ts+"</a></span></div>"; |
| 812 |
bcont += "</div>"; |
| 813 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-right\">"; |
| 814 |
bcont += "<div class=\"vbo-overview-tip-bcustomer\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBOCUSTOMER')); ?></span><span class=\"vbo-overview-tip-cnt\">"+v.cinfo+"</span></div>"; |
| 815 |
if (v.roomsnum > 1) { |
| 816 |
bcont += "<div class=\"vbo-overview-tip-brooms\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.numRooms+"</span><span class=\"vbo-overview-tip-cnt\">"+v.room_names+"</span></div>"; |
| 817 |
} |
| 818 |
bcont += "<div class=\"vbo-overview-tip-bguests\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.numNights+"</span><span class=\"vbo-overview-tip-cnt hasTooltip\" title=\""+vboMessages.checkinLbl+" "+v.checkin+" - "+vboMessages.checkoutLbl+" "+v.checkout+"\">"+v.days+", "+vboMessages.numAdults+": "+v.tot_adults+(v.tot_children > 0 ? ", "+vboMessages.numChildren+": "+v.tot_children : "")+"</span></div>"; |
| 819 |
if (v.hasOwnProperty('rindexes')) { |
| 820 |
for (var rindexk in v.rindexes) { |
| 821 |
if (v.rindexes.hasOwnProperty(rindexk)) { |
| 822 |
bcont += "<div class=\"vbo-overview-tip-brindexes\"><span class=\"vbo-overview-tip-lbl\">"+rindexk+"</span><span class=\"vbo-overview-tip-cnt\">"+v.rindexes[rindexk]+"</span></div>"; |
| 823 |
} |
| 824 |
} |
| 825 |
} |
| 826 |
if (v.hasOwnProperty('channelimg')) { |
| 827 |
bcont += "<div class=\"vbo-overview-tip-bprovenience\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBPVIEWORDERCHANNEL')); ?></span><span class=\"vbo-overview-tip-cnt\">"+v.channelimg+"</span></div>"; |
| 828 |
} |
| 829 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-total\">"; |
| 830 |
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.totalAmount+"</span><span class=\"vbo-overview-tip-cnt\">" + VBOCore.getCurrency().display(v.format_tot) + "</span></div>"; |
| 831 |
if (v.totpaid > 0.00) { |
| 832 |
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.totalPaid+"</span><span class=\"vbo-overview-tip-cnt\">" + VBOCore.getCurrency().display(v.format_totpaid) + "</span></div>"; |
| 833 |
} |
| 834 |
var getnotes = v.adminnotes; |
| 835 |
if (getnotes !== null && getnotes.length) { |
| 836 |
bcont += "<div class=\"vbo-overview-tip-notes\"><span class=\"vbo-overview-tip-lbl\"><span class=\"vbo-overview-tip-notes-inner\"><i class=\"vboicn-info hasTooltip\" title=\""+getnotes+"\"></i></span></span></div>"; |
| 837 |
} |
| 838 |
bcont += "</div>"; |
| 839 |
bcont += "</div>"; |
| 840 |
bcont += "</div>"; |
| 841 |
container.append(bcont); |
| 842 |
jQuery('.vbo-overview-tipexpander').show(); |
| 843 |
}); |
| 844 |
|
| 845 |
/** |
| 846 |
* @deprecated 1.16.10 (J) - 1.6.10 (WP) |
| 847 |
*/ |
| 848 |
// adjust the position so that it won't go under other contents |
| 849 |
// adjustHoveringTooltip(); |
| 850 |
|
| 851 |
} catch(err) { |
| 852 |
// restore |
| 853 |
hideVboTooltip(); |
| 854 |
// display error |
| 855 |
console.error('could not parse JSON response', err, res); |
| 856 |
alert('Could not parse JSON response'); |
| 857 |
} |
| 858 |
}).fail(function(err) { |
| 859 |
// restore |
| 860 |
hideVboTooltip(); |
| 861 |
// display error |
| 862 |
console.error(err); |
| 863 |
alert(err.responseText); |
| 864 |
}); |
| 865 |
} |
| 866 |
|
| 867 |
function vboSendPrintTableaux() { |
| 868 |
jQuery('#adminForm').attr('target', '_blank').append('<input type="hidden" class="vbo-tableaux-rmafterprint" name="tmpl" value="component" /><input type="hidden" class="vbo-tableaux-rmafterprint" name="printtableaux" value="1" />').submit(); |
| 869 |
setTimeout(function() { |
| 870 |
jQuery('#adminForm').attr('target', '_self'); |
| 871 |
jQuery('.vbo-tableaux-rmafterprint').remove(); |
| 872 |
}, 500); |
| 873 |
} |
| 874 |
|
| 875 |
/** |
| 876 |
* Fests |
| 877 |
*/ |
| 878 |
function vboRenderFests(day, daytitle) { |
| 879 |
// set day title |
| 880 |
if (daytitle) { |
| 881 |
jQuery('.vbo-modal-overlay-content-fests').find('h3').find('span').text(daytitle); |
| 882 |
} |
| 883 |
// compose fests information |
| 884 |
var fests_html = ''; |
| 885 |
if (vboFests[day] && vboFests[day]['festinfo'] && vboFests[day]['festinfo'].length) { |
| 886 |
for (var i = 0; i < vboFests[day]['festinfo'].length; i++) { |
| 887 |
var fest = vboFests[day]['festinfo'][i]; |
| 888 |
fests_html += '<div class="vbo-overlay-fest-details">'; |
| 889 |
fests_html += ' <div class="vbo-fest-info">'; |
| 890 |
fests_html += ' <div class="vbo-fest-name">' + fest['trans_name'] + '</div>'; |
| 891 |
fests_html += ' <div class="vbo-fest-desc">' + fest['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>'; |
| 892 |
fests_html += ' </div>'; |
| 893 |
fests_html += ' <div class="vbo-fest-cmds">'; |
| 894 |
fests_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveFest(\'' + day + '\', \'' + i + '\', \'' + fest['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt'); ?></button>'; |
| 895 |
fests_html += ' </div>'; |
| 896 |
fests_html += '</div>'; |
| 897 |
} |
| 898 |
} |
| 899 |
// update ymd key for the selected date, useful for adding new fests |
| 900 |
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', day); |
| 901 |
// set content and display modal |
| 902 |
jQuery('.vbo-overlay-fests-list').html(fests_html); |
| 903 |
jQuery('.vbo-modal-overlay-block-fests').fadeIn(); |
| 904 |
vbodialogfests_on = true; |
| 905 |
} |
| 906 |
|
| 907 |
function vboRemoveFest(day, index, fest_type, that) { |
| 908 |
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) { |
| 909 |
return false; |
| 910 |
} |
| 911 |
var elem = jQuery(that); |
| 912 |
// make the AJAX request to the controller to remove this fest from the DB |
| 913 |
var jqxhr = jQuery.ajax({ |
| 914 |
type: "POST", |
| 915 |
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_fest'); ?>", |
| 916 |
data: { |
| 917 |
tmpl: "component", |
| 918 |
dt: day, |
| 919 |
ind: index, |
| 920 |
type: fest_type |
| 921 |
} |
| 922 |
}).done(function(res) { |
| 923 |
if (res.indexOf('e4j.ok') >= 0) { |
| 924 |
// delete fest also from the json-decode array of objects |
| 925 |
if (vboFests[day] && vboFests[day]['festinfo']) { |
| 926 |
// use splice to remove the desired index from array, or delete would not make the length of the array change |
| 927 |
vboFests[day]['festinfo'].splice(index, 1); |
| 928 |
// re-build indexes of delete buttons, fundamental for removing the right index at next click |
| 929 |
vboRenderFests(day); |
| 930 |
if (!vboFests[day]['festinfo'].length) { |
| 931 |
// delete also this date object from fests |
| 932 |
delete vboFests[day]; |
| 933 |
// no more fests, remove the class for this date from all cells |
| 934 |
jQuery('td.vbo-tableaux-daycell[data-ymd="'+day+'"]').removeClass('vbo-tableaux-festcell'); |
| 935 |
} |
| 936 |
} |
| 937 |
elem.closest('.vbo-overlay-fest-details').remove(); |
| 938 |
} else { |
| 939 |
console.log(res); |
| 940 |
alert('Invalid response'); |
| 941 |
} |
| 942 |
}).fail(function() { |
| 943 |
alert('Request failed'); |
| 944 |
}); |
| 945 |
} |
| 946 |
|
| 947 |
function vboAddFest(that) { |
| 948 |
var elem = jQuery(that); |
| 949 |
var ymd = elem.closest('.vbo-overlay-fests-addnew').attr('data-ymd'); |
| 950 |
var fest_name = jQuery('#vbo-newfest-name').val(); |
| 951 |
var fest_descr = jQuery('#vbo-newfest-descr').val(); |
| 952 |
if (!fest_name.length) { |
| 953 |
return false; |
| 954 |
} |
| 955 |
// make the AJAX request to the controller to add this fest to the DB |
| 956 |
var jqxhr = jQuery.ajax({ |
| 957 |
type: "POST", |
| 958 |
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_fest'); ?>", |
| 959 |
data: { |
| 960 |
tmpl: "component", |
| 961 |
dt: ymd, |
| 962 |
type: "custom", |
| 963 |
name: fest_name, |
| 964 |
descr: fest_descr |
| 965 |
} |
| 966 |
}).done(function(res) { |
| 967 |
// parse the JSON response that contains the fest object for the passed date |
| 968 |
try { |
| 969 |
var stored_fest = typeof res === 'string' ? JSON.parse(res) : res; |
| 970 |
if (!vboFests.hasOwnProperty(stored_fest['dt'])) { |
| 971 |
// we need to add the proper class to all cells to show that there is a fest |
| 972 |
jQuery('td.vbo-tableaux-daycell[data-ymd="'+stored_fest['dt']+'"]').addClass('vbo-tableaux-festcell'); |
| 973 |
} |
| 974 |
vboFests[stored_fest['dt']] = stored_fest; |
| 975 |
hideVboDialogFests(); |
| 976 |
// reset input fields |
| 977 |
jQuery('#vbo-newfest-name').val(''); |
| 978 |
jQuery('#vbo-newfest-descr').val(''); |
| 979 |
} catch (e) { |
| 980 |
console.log(res); |
| 981 |
alert('Invalid response'); |
| 982 |
return false; |
| 983 |
} |
| 984 |
}).fail(function() { |
| 985 |
alert('Request failed'); |
| 986 |
}); |
| 987 |
} |
| 988 |
// |
| 989 |
|
| 990 |
/** |
| 991 |
* Room-day notes |
| 992 |
*/ |
| 993 |
var rdaynote_icn_full = '<?php echo VikBookingIcons::i('sticky-note', 'vbo-roomdaynote-display'); ?>'; |
| 994 |
var rdaynote_icn_empty = '<?php echo VikBookingIcons::i('far fa-sticky-note', 'vbo-roomdaynote-display'); ?>'; |
| 995 |
var rooms_features_map = JSON.parse('<?php echo isset($rooms_features_map) && count($rooms_features_map) ? json_encode($rooms_features_map) : json_encode(array()); ?>'); |
| 996 |
|
| 997 |
function vboRenderRdayNotes(day, idroom, subunit, readymd) { |
| 998 |
// compose room-day notes information (subunit always = 0 for room-day level) |
| 999 |
var notes_html = ''; |
| 1000 |
var keyids = new Array; |
| 1001 |
// always push 0 as the room-level day note key |
| 1002 |
keyids.push(0); |
| 1003 |
// grab all the other note keys at sub-unit level |
| 1004 |
if (jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').length) { |
| 1005 |
var all_nkeys = jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').attr('data-rdnkeys'); |
| 1006 |
if (all_nkeys && all_nkeys.length) { |
| 1007 |
var nkeys = all_nkeys.split(','); |
| 1008 |
for (var k in nkeys) { |
| 1009 |
var int_index = parseInt(nkeys[k]); |
| 1010 |
if (!nkeys.hasOwnProperty(k) || isNaN(int_index) || int_index < 1) { |
| 1011 |
continue; |
| 1012 |
} |
| 1013 |
// push sub-unit key for lookup |
| 1014 |
keyids.push(nkeys[k]); |
| 1015 |
} |
| 1016 |
} |
| 1017 |
} |
| 1018 |
// parse all room keys with notes |
| 1019 |
for (var z = 0; z < keyids.length; z++) { |
| 1020 |
// this is the real sub-unit we are parsing |
| 1021 |
var subunit_index = keyids[z]; |
| 1022 |
var keyid = day + '_' + idroom + '_' + subunit_index; |
| 1023 |
if (vboRdayNotes.hasOwnProperty(keyid) && vboRdayNotes[keyid]['info'] && vboRdayNotes[keyid]['info'].length) { |
| 1024 |
for (var i = 0; i < vboRdayNotes[keyid]['info'].length; i++) { |
| 1025 |
var note_data = vboRdayNotes[keyid]['info'][i]; |
| 1026 |
var subunit_name = ''; |
| 1027 |
if (parseInt(subunit_index) > 0) { |
| 1028 |
subunit_name = '(' + subunit_index + ') '; |
| 1029 |
if (rooms_features_map.hasOwnProperty(idroom) && rooms_features_map[idroom].hasOwnProperty(subunit_index)) { |
| 1030 |
subunit_name = rooms_features_map[idroom][subunit_index] + ' - '; |
| 1031 |
} |
| 1032 |
} |
| 1033 |
notes_html += '<div class="vbo-overlay-fest-details vbo-modal-roomdaynotes-note-details">'; |
| 1034 |
notes_html += ' <div class="vbo-fest-info vbo-modal-roomdaynotes-note-info">'; |
| 1035 |
notes_html += ' <div class="vbo-fest-name vbo-modal-roomdaynotes-note-name">' + subunit_name + note_data['name'] + '</div>'; |
| 1036 |
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>'; |
| 1037 |
notes_html += ' </div>'; |
| 1038 |
notes_html += ' <div class="vbo-fest-cmds vbo-modal-roomdaynotes-note-cmds">'; |
| 1039 |
notes_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveRdayNote(\'' + i + '\', \'' + day + '\', \'' + idroom + '\', \'' + subunit_index + '\', \'' + note_data['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt'); ?></button>'; |
| 1040 |
notes_html += ' </div>'; |
| 1041 |
notes_html += '</div>'; |
| 1042 |
} |
| 1043 |
} |
| 1044 |
} |
| 1045 |
// update attributes keys for the selected date, useful for adding new notes (always at room-level) |
| 1046 |
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd', day).attr('data-roomid', idroom).attr('data-subroomid', '0'); |
| 1047 |
if (readymd !== null) { |
| 1048 |
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd', readymd); |
| 1049 |
jQuery('.vbo-newrdnote-dayto-val').text(readymd); |
| 1050 |
} |
| 1051 |
// set content and display modal |
| 1052 |
jQuery('.vbo-modal-roomdaynotes-list').html(notes_html); |
| 1053 |
} |
| 1054 |
|
| 1055 |
function vboAddRoomDayNote(that) { |
| 1056 |
var mainelem = jQuery(that).closest('.vbo-modal-roomdaynotes-addnew'); |
| 1057 |
var ymd = mainelem.attr('data-ymd'); |
| 1058 |
var roomid = mainelem.attr('data-roomid'); |
| 1059 |
var subroomid = mainelem.attr('data-subroomid'); |
| 1060 |
var note_name = jQuery('#vbo-newrdnote-name').val(); |
| 1061 |
var note_descr = jQuery('#vbo-newrdnote-descr').val(); |
| 1062 |
var note_cdays = jQuery('#vbo-newrdnote-cdays').val(); |
| 1063 |
if (!note_name.length && !note_descr.length) { |
| 1064 |
alert('Missing required fields'); |
| 1065 |
return false; |
| 1066 |
} |
| 1067 |
// make the AJAX request to the controller to add this note to the DB |
| 1068 |
var jqxhr = jQuery.ajax({ |
| 1069 |
type: "POST", |
| 1070 |
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_roomdaynote'); ?>", |
| 1071 |
data: { |
| 1072 |
tmpl: "component", |
| 1073 |
dt: ymd, |
| 1074 |
idroom: roomid, |
| 1075 |
subunit: subroomid, |
| 1076 |
type: "custom", |
| 1077 |
name: note_name, |
| 1078 |
descr: note_descr, |
| 1079 |
cdays: note_cdays |
| 1080 |
} |
| 1081 |
}).done(function(res) { |
| 1082 |
// parse the JSON response that contains the note object for the passed date |
| 1083 |
try { |
| 1084 |
var stored_notes = JSON.parse(res); |
| 1085 |
var counter = 0; |
| 1086 |
for (var keyid in stored_notes) { |
| 1087 |
if (!stored_notes.hasOwnProperty(keyid)) { |
| 1088 |
continue; |
| 1089 |
} |
| 1090 |
var is_date_visible = (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').length > 0); |
| 1091 |
if (!vboRdayNotes.hasOwnProperty(keyid) && is_date_visible) { |
| 1092 |
// we need to add the proper class to the cell for this note (if it's visible) |
| 1093 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').removeClass('vbo-roomdaynote-empty').addClass('vbo-roomdaynote-full').find('i').attr('class', rdaynote_icn_full); |
| 1094 |
} |
| 1095 |
// update global object with the new notes in any case |
| 1096 |
vboRdayNotes[keyid] = stored_notes[keyid]; |
| 1097 |
// update readable notes in custom data attribute |
| 1098 |
if (counter < 1 && is_date_visible && note_name.length) { |
| 1099 |
// we push just this name |
| 1100 |
var current_cell_notes = jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes'); |
| 1101 |
var all_cell_notes = current_cell_notes && current_cell_notes.length ? current_cell_notes.split(', ') : new Array; |
| 1102 |
all_cell_notes.push(note_name); |
| 1103 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes', all_cell_notes.join(', ')); |
| 1104 |
} |
| 1105 |
// increase counter |
| 1106 |
counter++; |
| 1107 |
} |
| 1108 |
// close modal |
| 1109 |
hideVboDialogRdaynotes(); |
| 1110 |
// reset input fields |
| 1111 |
jQuery('#vbo-newrdnote-name').val(''); |
| 1112 |
jQuery('#vbo-newrdnote-descr').val(''); |
| 1113 |
jQuery('#vbo-newrdnote-cdays').val('0').trigger('change'); |
| 1114 |
} catch (e) { |
| 1115 |
console.log(res); |
| 1116 |
alert('Invalid response'); |
| 1117 |
return false; |
| 1118 |
} |
| 1119 |
}).fail(function() { |
| 1120 |
alert('Request failed'); |
| 1121 |
}); |
| 1122 |
} |
| 1123 |
|
| 1124 |
function vboRdayNotesAvailable(day, idroom) { |
| 1125 |
/** |
| 1126 |
* We check whether a room has notes at parent or subunit level for the given date. |
| 1127 |
*/ |
| 1128 |
var base_key = day + '_' + idroom + '_'; |
| 1129 |
var notes_available = false; |
| 1130 |
for (var k in vboRdayNotes) { |
| 1131 |
if (!vboRdayNotes.hasOwnProperty(k) || k.indexOf(base_key) < 0) { |
| 1132 |
continue; |
| 1133 |
} |
| 1134 |
// notes found for this room, either parent or sub-unit |
| 1135 |
if (vboRdayNotes[k]['info'] && vboRdayNotes[k]['info'].length) { |
| 1136 |
notes_available = true; |
| 1137 |
break; |
| 1138 |
} |
| 1139 |
} |
| 1140 |
|
| 1141 |
return notes_available; |
| 1142 |
} |
| 1143 |
|
| 1144 |
function vboRemoveRdayNote(index, day, idroom, subunit, note_type, that) { |
| 1145 |
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) { |
| 1146 |
return false; |
| 1147 |
} |
| 1148 |
var elem = jQuery(that); |
| 1149 |
// make the AJAX request to the controller to remove this note from the DB |
| 1150 |
var jqxhr = jQuery.ajax({ |
| 1151 |
type: "POST", |
| 1152 |
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_roomdaynote'); ?>", |
| 1153 |
data: { |
| 1154 |
tmpl: "component", |
| 1155 |
dt: day, |
| 1156 |
idroom: idroom, |
| 1157 |
subunit: subunit, |
| 1158 |
ind: index, |
| 1159 |
type: note_type |
| 1160 |
} |
| 1161 |
}).done(function(res) { |
| 1162 |
if (res.indexOf('e4j.ok') >= 0) { |
| 1163 |
var keyid = day + '_' + idroom + '_' + subunit; |
| 1164 |
var glob_keyid = day + '_' + idroom + '_0'; |
| 1165 |
// delete note also from the json-decode array of objects |
| 1166 |
if (vboRdayNotes[keyid] && vboRdayNotes[keyid]['info']) { |
| 1167 |
// get the original note name |
| 1168 |
var old_name = vboRdayNotes[keyid]['info'][index]['name']; |
| 1169 |
// use splice to remove the desired index from array, or delete would not make the length of the array change |
| 1170 |
vboRdayNotes[keyid]['info'].splice(index, 1); |
| 1171 |
// re-build indexes of delete buttons, fundamental for removing the right index at next click (reload always at room-level) |
| 1172 |
vboRenderRdayNotes(day, idroom, '0', null); |
| 1173 |
if (!vboRdayNotes[keyid]['info'].length && !vboRdayNotesAvailable(day, idroom)) { |
| 1174 |
// delete also this date object from notes |
| 1175 |
delete vboRdayNotes[keyid]; |
| 1176 |
// no more notes, update the proper class attribute for this cell (should be visible) |
| 1177 |
if (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').length) { |
| 1178 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').parent('td').removeClass('vbo-roomdaynote-full').addClass('vbo-roomdaynote-empty').attr('data-notes', '').find('i').attr('class', rdaynote_icn_empty); |
| 1179 |
} |
| 1180 |
} else if (old_name && old_name.length) { |
| 1181 |
// try to adjust the readable notes in custom data attribute |
| 1182 |
var current_cell_notes = jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').parent('td').attr('data-notes'); |
| 1183 |
var all_cell_notes = current_cell_notes && current_cell_notes.length ? current_cell_notes.split(', ') : new Array; |
| 1184 |
var new_cell_notes = new Array; |
| 1185 |
for (var i = 0; i < all_cell_notes.length; i++) { |
| 1186 |
if (all_cell_notes[i].indexOf(old_name) < 0) { |
| 1187 |
new_cell_notes.push(all_cell_notes[i]); |
| 1188 |
} |
| 1189 |
} |
| 1190 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').parent('td').attr('data-notes', new_cell_notes.join(', ')); |
| 1191 |
} |
| 1192 |
} |
| 1193 |
elem.closest('.vbo-modal-roomdaynotes-note-details').remove(); |
| 1194 |
} else { |
| 1195 |
console.log(res); |
| 1196 |
alert('Invalid response'); |
| 1197 |
} |
| 1198 |
}).fail(function() { |
| 1199 |
alert('Request failed'); |
| 1200 |
}); |
| 1201 |
} |
| 1202 |
|
| 1203 |
function vboRdayNoteCdaysCount() { |
| 1204 |
var cdays = parseInt(jQuery('#vbo-newrdnote-cdays').val()); |
| 1205 |
var defymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd'); |
| 1206 |
var defreadymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd'); |
| 1207 |
defreadymd = !defreadymd || !defreadymd.length ? defymd : defreadymd; |
| 1208 |
if (isNaN(cdays) || cdays < 1) { |
| 1209 |
jQuery('.vbo-newrdnote-dayto-val').text(defreadymd); |
| 1210 |
return; |
| 1211 |
} |
| 1212 |
// calculate target (until) date |
| 1213 |
var targetdate = new Date(defymd); |
| 1214 |
targetdate.setDate(targetdate.getDate() + cdays); |
| 1215 |
var target_y = targetdate.getFullYear(); |
| 1216 |
var target_m = targetdate.getMonth() + 1; |
| 1217 |
target_m = target_m < 10 ? '0' + target_m : target_m; |
| 1218 |
var target_d = targetdate.getDate(); |
| 1219 |
target_d = target_d < 10 ? '0' + target_d : target_d; |
| 1220 |
// display target date |
| 1221 |
var display_target = target_y + '-' + target_m + '-' + target_d; |
| 1222 |
// check if we can get the "read ymd property" |
| 1223 |
if (jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').length) { |
| 1224 |
display_target = jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').attr('data-readymd'); |
| 1225 |
} |
| 1226 |
jQuery('.vbo-newrdnote-dayto-val').text(display_target); |
| 1227 |
} |
| 1228 |
// |
| 1229 |
|
| 1230 |
/** |
| 1231 |
* Tells whether an element can fit entirely in the viewport. |
| 1232 |
* Example: if a table is too high to fit in the screen. |
| 1233 |
* If false, it means that scrolling will always be needed. |
| 1234 |
*/ |
| 1235 |
function vboFitsInViewport(selector) { |
| 1236 |
var elemHeight = jQuery(selector).outerHeight(); |
| 1237 |
var maxHeight = jQuery(window).height(); |
| 1238 |
|
| 1239 |
return elemHeight < maxHeight; |
| 1240 |
} |
| 1241 |
|
| 1242 |
// tableaux scrolling |
| 1243 |
var fittingTableaux = null; |
| 1244 |
var tableauxStickySet = false; |
| 1245 |
|
| 1246 |
/** |
| 1247 |
* Throttle guarantees a constant flow of events at a given time interval, |
| 1248 |
* but it runs immediately when the event takes place. We rather need a |
| 1249 |
* debounce technique to group a flurry of events into one single event. |
| 1250 |
* This is useful for listening to the scrolling event of the table, actually |
| 1251 |
* the DIV that wraps it with overflow, and setting the sticky headers. |
| 1252 |
*/ |
| 1253 |
function vboDebounceScroll(func, wait, immediate) { |
| 1254 |
var timeout; |
| 1255 |
return function() { |
| 1256 |
var context = this, args = arguments; |
| 1257 |
var later = function() { |
| 1258 |
timeout = null; |
| 1259 |
if (!immediate) func.apply(context, args); |
| 1260 |
}; |
| 1261 |
var callNow = immediate && !timeout; |
| 1262 |
clearTimeout(timeout); |
| 1263 |
timeout = setTimeout(later, wait); |
| 1264 |
if (callNow) { |
| 1265 |
func.apply(context, args); |
| 1266 |
} |
| 1267 |
} |
| 1268 |
} |
| 1269 |
/** |
| 1270 |
* We do not need a throttle technique, but this method would |
| 1271 |
* throttle the scroll event rather than debouncing it. |
| 1272 |
*/ |
| 1273 |
function vboThrottleScroll(method, delay) { |
| 1274 |
var time = Date.now(); |
| 1275 |
return function() { |
| 1276 |
if ((time + delay - Date.now()) < 0) { |
| 1277 |
method(); |
| 1278 |
time = Date.now(); |
| 1279 |
} |
| 1280 |
} |
| 1281 |
} |
| 1282 |
|
| 1283 |
/** |
| 1284 |
* This will fire during the throttle of the scrolling event. |
| 1285 |
*/ |
| 1286 |
function vboHandleScroll() { |
| 1287 |
if (fittingTableaux === null) { |
| 1288 |
fittingTableaux = vboFitsInViewport('.vbo-tableaux-table'); |
| 1289 |
} |
| 1290 |
if (fittingTableaux) { |
| 1291 |
// no sticky table headers needed, remove the listener as it is not needed |
| 1292 |
document.getElementById('vbo-tableaux-table-scroller').removeEventListener('scroll', vboDebounceScroll(vboHandleScroll, 1000)); |
| 1293 |
return; |
| 1294 |
} |
| 1295 |
// we have scrolled (vertically or horizontally), update the position of the sticky table head |
| 1296 |
if (tableauxStickySet) { |
| 1297 |
// destroy sticky table head |
| 1298 |
jQuery('table.vbo-tableaux-table').stickyTableHeaders('destroy'); |
| 1299 |
} |
| 1300 |
// re-build sticky head |
| 1301 |
jQuery('table.vbo-tableaux-table').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: jQuery('.navbar')}); |
| 1302 |
tableauxStickySet = true; |
| 1303 |
} |
| 1304 |
|
| 1305 |
jQuery(function() { |
| 1306 |
// add listener to scroll event on the main table |
| 1307 |
document.getElementById('vbo-tableaux-table-scroller').addEventListener('scroll', vboDebounceScroll(vboHandleScroll, 1000)); |
| 1308 |
|
| 1309 |
jQuery('#vbo-date-from').datepicker({ |
| 1310 |
showOn: 'focus', |
| 1311 |
dateFormat: '<?php echo $juidf; ?>', |
| 1312 |
<?php echo ($this->mindate > 0 ? 'minDate: "'.date(str_replace('%', '', $nowdf), $this->mindate).'", ' : '').($this->maxdate > 0 ? 'maxDate: "'.date(str_replace('%', '', $nowdf), $this->maxdate).'", ' : ''); ?> |
| 1313 |
onSelect: function( selectedDate ) { |
| 1314 |
jQuery('#vbo-date-to').datepicker('option', 'minDate', selectedDate); |
| 1315 |
jQuery('#vbo-month').val(''); |
| 1316 |
} |
| 1317 |
}); |
| 1318 |
|
| 1319 |
jQuery('#vbo-date-to').datepicker({ |
| 1320 |
showOn: 'focus', |
| 1321 |
dateFormat: '<?php echo $juidf; ?>', |
| 1322 |
<?php echo ($this->mindate > 0 ? 'minDate: "'.date(str_replace('%', '', $nowdf), $this->mindate).'", ' : '').($this->maxdate > 0 ? 'maxDate: "'.date(str_replace('%', '', $nowdf), $this->maxdate).'", ' : ''); ?> |
| 1323 |
onSelect: function( selectedDate ) { |
| 1324 |
jQuery('#vbo-date-from').datepicker('option', 'maxDate', selectedDate); |
| 1325 |
jQuery('#vbo-month').val(''); |
| 1326 |
} |
| 1327 |
}); |
| 1328 |
|
| 1329 |
jQuery('#vbo-date-from-trig, #vbo-date-to-trig').click(function() { |
| 1330 |
var jdp = jQuery(this).prev('input.hasDatepicker'); |
| 1331 |
if (jdp.length) { |
| 1332 |
jdp.focus(); |
| 1333 |
} |
| 1334 |
}); |
| 1335 |
|
| 1336 |
jQuery('.vbo-tableaux-selmonth').click(function() { |
| 1337 |
var xts = jQuery(this).attr('data-ts'); |
| 1338 |
var xfrom = jQuery(this).attr('data-from'); |
| 1339 |
var xto = jQuery(this).attr('data-to'); |
| 1340 |
jQuery('#vbo-month').val(xts); |
| 1341 |
jQuery('#vbo-date-from').val(xfrom); |
| 1342 |
jQuery('#vbo-date-to').val(xto); |
| 1343 |
jQuery('#adminForm').submit(); |
| 1344 |
}); |
| 1345 |
|
| 1346 |
/* Expand/Collapse tooltip */ |
| 1347 |
jQuery(document.body).on("click", ".vbo-overview-expandtoggle", function() { |
| 1348 |
jQuery(this).closest('.vbo-overview-tipblock').toggleClass('vbo-overview-tipblock-expanded'); |
| 1349 |
}); |
| 1350 |
/* ----------------------- */ |
| 1351 |
|
| 1352 |
/* Hover Tooltip */ |
| 1353 |
jQuery('.vbo-tableaux-booking-checkin, .vbo-tableaux-booking-checkout, .vbo-tableaux-booking-stay').hover(function() { |
| 1354 |
registerHoveringTooltip(this); |
| 1355 |
}, unregisterHoveringTooltip); |
| 1356 |
|
| 1357 |
// view booking snapshot |
| 1358 |
jQuery('.vbo-tableaux-booking').on('click', function(e) { |
| 1359 |
e.stopPropagation(); |
| 1360 |
let bid = jQuery(this).attr('data-bid'); |
| 1361 |
if (bid) { |
| 1362 |
VBOCore.handleDisplayWidgetNotification({widget_id: 'booking_details'}, {booking_id: bid}); |
| 1363 |
} |
| 1364 |
}); |
| 1365 |
|
| 1366 |
jQuery(document).keydown(function(e) { |
| 1367 |
if (e.keyCode == 27) { |
| 1368 |
if (hovtip === true) { |
| 1369 |
hideVboTooltip(); |
| 1370 |
} |
| 1371 |
if (vbodialogfests_on === true) { |
| 1372 |
hideVboDialogFests(); |
| 1373 |
} |
| 1374 |
if (vbodialogrdaynotes_on === true) { |
| 1375 |
hideVboDialogRdaynotes(); |
| 1376 |
} |
| 1377 |
} |
| 1378 |
}); |
| 1379 |
|
| 1380 |
jQuery(document).mouseup(function(e) { |
| 1381 |
if (!hovtip && !vbodialogfests_on && !vbodialogrdaynotes_on) { |
| 1382 |
return; |
| 1383 |
} |
| 1384 |
if (hovtip) { |
| 1385 |
var vbo_overlay_cont = jQuery(".vbo-overview-tipblock"); |
| 1386 |
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) { |
| 1387 |
hideVboTooltip(); |
| 1388 |
return; |
| 1389 |
} |
| 1390 |
} |
| 1391 |
if (vbodialogfests_on) { |
| 1392 |
var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-fests"); |
| 1393 |
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) { |
| 1394 |
hideVboDialogFests(); |
| 1395 |
} |
| 1396 |
} |
| 1397 |
if (vbodialogrdaynotes_on) { |
| 1398 |
var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-roomdaynotes"); |
| 1399 |
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) { |
| 1400 |
hideVboDialogRdaynotes(); |
| 1401 |
} |
| 1402 |
} |
| 1403 |
}); |
| 1404 |
|
| 1405 |
// fests |
| 1406 |
jQuery(document.body).on("click", "td.vbo-tableaux-daycell", function() { |
| 1407 |
if (jQuery(this).hasClass('skip-tableaux-daycell-click')) { |
| 1408 |
return; |
| 1409 |
} |
| 1410 |
var ymd = jQuery(this).attr('data-ymd'); |
| 1411 |
var daytitle = jQuery(this).attr('data-readymd'); |
| 1412 |
if (jQuery(this).hasClass('vbo-tableaux-festcell')) { |
| 1413 |
// cell has fests |
| 1414 |
if (!vboFests.hasOwnProperty(ymd)) { |
| 1415 |
return; |
| 1416 |
} |
| 1417 |
vboRenderFests(ymd, daytitle); |
| 1418 |
} else { |
| 1419 |
// let the admin create a new fest |
| 1420 |
// set day title |
| 1421 |
jQuery('.vbo-modal-overlay-content-fests').find('h3').find('span').text(daytitle); |
| 1422 |
// update ymd key for the selected date, useful for adding new fests |
| 1423 |
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', ymd); |
| 1424 |
// unset content and display modal for just adding a new fest |
| 1425 |
jQuery('.vbo-overlay-fests-list').html(''); |
| 1426 |
jQuery('.vbo-modal-overlay-block-fests').fadeIn(); |
| 1427 |
vbodialogfests_on = true; |
| 1428 |
} |
| 1429 |
}); |
| 1430 |
// |
| 1431 |
|
| 1432 |
// room-day notes |
| 1433 |
jQuery(document.body).on("click", ".vbo-roomdaynote-display", function() { |
| 1434 |
if (!jQuery(this).closest('.vbo-roomdaynote-trigger').length) { |
| 1435 |
return; |
| 1436 |
} |
| 1437 |
var daytitle = new Array; |
| 1438 |
var roomday_info = jQuery(this).closest('.vbo-roomdaynote-trigger').attr('data-roomday').split('_'); |
| 1439 |
// readable day |
| 1440 |
var readymd = roomday_info[0]; |
| 1441 |
if (jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').length) { |
| 1442 |
readymd = jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').attr('data-readymd'); |
| 1443 |
} |
| 1444 |
daytitle.push(readymd); |
| 1445 |
// room name |
| 1446 |
if (jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').length) { |
| 1447 |
daytitle.push(jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').text()); |
| 1448 |
} |
| 1449 |
// set day title |
| 1450 |
jQuery('.vbo-modal-overlay-content-head-roomdaynotes').find('h3').find('span').text(daytitle.join(', ')); |
| 1451 |
// populate current room day notes |
| 1452 |
vboRenderRdayNotes(roomday_info[0], roomday_info[1], roomday_info[2], readymd); |
| 1453 |
// display modal |
| 1454 |
jQuery('.vbo-modal-overlay-block-roomdaynotes').fadeIn(); |
| 1455 |
vbodialogrdaynotes_on = true; |
| 1456 |
// |
| 1457 |
}); |
| 1458 |
// |
| 1459 |
|
| 1460 |
// use sticky headers only if the table is longer than the max viewport height |
| 1461 |
fittingTableaux = vboFitsInViewport('.vbo-tableaux-table'); |
| 1462 |
if (!fittingTableaux) { |
| 1463 |
// display table head |
| 1464 |
jQuery('.vbo-tableaux-table-head').show(); |
| 1465 |
// set sticky head for the vertical scrolling |
| 1466 |
jQuery('table.vbo-tableaux-table').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: jQuery('.navbar')}); |
| 1467 |
tableauxStickySet = true; |
| 1468 |
} else { |
| 1469 |
// hide table head |
| 1470 |
jQuery('.vbo-tableaux-table-head').hide(); |
| 1471 |
} |
| 1472 |
|
| 1473 |
<?php |
| 1474 |
if ($printtableaux > 0) { |
| 1475 |
?> |
| 1476 |
window.print(); |
| 1477 |
<?php |
| 1478 |
} |
| 1479 |
?> |
| 1480 |
}); |
| 1481 |
</script> |
| 1482 |
|