File "default.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/vikbooking/admin/views/tableaux/tmpl/default.php
File size: 59.72 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* @package VikBooking
* @subpackage com_vikbooking
* @author Alessio Gaggii - e4j - Extensionsforjoomla.com
* @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
* @link https://vikwp.com
*/
defined('ABSPATH') or die('No script kiddies please!');
$roomids = $this->roomids;
$rooms = $this->rooms;
$rooms_busy = $this->rooms_busy;
$months = $this->months;
$fromts = $this->fromts;
$tots = $this->tots;
$vbo_app = VikBooking::getVboApplication();
$vbo_app->loadSelect2();
$vbo_app->loadDatePicker();
JHtml::fetch('script', VBO_ADMIN_URI . 'resources/js_upload/jquery.stickytableheaders.min.js');
$nowdf = VikBooking::getDateFormat(true);
if ($nowdf == "%d/%m/%Y") {
$df = 'd/m/Y';
} elseif ($nowdf == "%m/%d/%Y") {
$df = 'm/d/Y';
} else {
$df = 'Y/m/d';
}
$datesep = VikBooking::getDateSeparator(true);
$juidf = $nowdf == "%d/%m/%Y" ? 'dd/mm/yy' : ($nowdf == "%m/%d/%Y" ? 'mm/dd/yy' : 'yy/mm/dd');
$currencysymb = VikBooking::getCurrencySymb();
$month = VikRequest::getInt('month', 0, 'request');
$printtableaux = VikRequest::getInt('printtableaux', 0, 'request');
$colortags = VikBooking::loadBookingsColorTags();
$days_labels = array(
JText::translate('VBSUN'),
JText::translate('VBMON'),
JText::translate('VBTUE'),
JText::translate('VBWED'),
JText::translate('VBTHU'),
JText::translate('VBFRI'),
JText::translate('VBSAT'),
);
$months_labels = array(
JText::translate('VBMONTHONE'),
JText::translate('VBMONTHTWO'),
JText::translate('VBMONTHTHREE'),
JText::translate('VBMONTHFOUR'),
JText::translate('VBMONTHFIVE'),
JText::translate('VBMONTHSIX'),
JText::translate('VBMONTHSEVEN'),
JText::translate('VBMONTHEIGHT'),
JText::translate('VBMONTHNINE'),
JText::translate('VBMONTHTEN'),
JText::translate('VBMONTHELEVEN'),
JText::translate('VBMONTHTWELVE'),
);
$long_months_labels = $months_labels;
foreach ($months_labels as $i => $v) {
$months_labels[$i] = function_exists('mb_substr') ? mb_substr($v, 0, 3, 'UTF-8') : substr($v, 0, 3);
}
?>
<div class="vbo-tableaux-container">
<form name="adminForm" action="index.php?option=com_vikbooking&task=tableaux" method="post" id="adminForm">
<div class="vbo-tableaux-months-wrap">
<?php
foreach ($months as $mdata) {
?>
<div class="vbo-tableaux-month-cont">
<div class="vbo-tableaux-month-link<?php echo $month == $mdata['from'] ? ' vbo-tableaux-month-link-active' : ''; ?>">
<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>
</div>
</div>
<?php
}
?>
</div>
<div id="filter-bar" class="btn-toolbar vbo-btn-toolbar vbo-tableaux-filters" style="width: 100%; display: inline-block;">
<div class="btn-group pull-left" style="font-size: 12px;">
<span class="vbo-toolbar-multiselect-wrap">
<?php
echo $vbo_app->renderElementsDropDown([
'id' => 'roomsel',
'elements' => 'listings',
'placeholder' => JText::translate('VBO_LISTINGS'),
'allow_clear' => 1,
'attributes' => [
'name' => 'roomids[]',
'multiple' => 'multiple',
],
'load_categories' => 1,
'selected_values' => (array) JFactory::getApplication()->input->get('roomids', [], 'array'),
]);
?>
</span>
</div>
<div class="btn-group pull-left">
<span style="font-size: 15px;"> </span>
</div>
<div class="btn-group pull-left input-append">
<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();" />
<button type="button" class="btn" id="vbo-date-from-trig"><i class="icon-calendar"></i></button>
</div>
<div class="btn-group pull-left input-append">
<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();" />
<button type="button" class="btn" id="vbo-date-to-trig"><i class="icon-calendar"></i></button>
</div>
<div class="btn-group pull-left">
<span style="font-size: 15px;"> </span>
</div>
<div class="btn-group pull-left">
<button type="submit" class="btn"><i class="icon-search"></i> <?php echo JText::translate('VBAPPLY'); ?></button>
</div>
<div class="btn-group pull-right">
<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>
</div>
<div class="btn-group pull-right">
<a href="javascript: void(0);" onclick="vboSendPrintTableaux();" class="vbcsvexport"><?php VikBookingIcons::e('print'); ?> <span><?php echo JText::translate('VBOPRINT'); ?></span></a>
</div>
</div>
<input type="hidden" name="month" id="vbo-month" value="<?php echo $month; ?>" />
<input type="hidden" name="task" value="tableaux" />
<input type="hidden" name="option" value="com_vikbooking" />
</form>
<?php
/**
* Render the permissions layout to manage the permissions of
* a specific tool, tableaux, for all the operators.
*
* @since 1.16.9 (J) - 1.6.9 (WP)
*/
$layout_data = [
'tool' => 'tableaux',
];
// render the permissions layout
echo JLayoutHelper::render('operators.permissions', $layout_data);
// count the cells per month
$thead_info = array();
$months_days = array();
$nowinfo = getdate($fromts);
while ($nowinfo[0] <= $tots) {
$mkey = $nowinfo['mon'] . '_' . $nowinfo['year'];
if (!isset($months_days[$mkey])) {
$months_days[$mkey] = 0;
}
$months_days[$mkey]++;
// push information for the table head
array_push($thead_info, array(
'mon' => $long_months_labels[($nowinfo['mon'] - 1)],
'mday' => $nowinfo['mday'],
'wday' => $days_labels[$nowinfo['wday']],
'year' => $nowinfo['year'],
'ts' => $nowinfo[0],
));
// next loop
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
}
// today
$todaydt = date('Y-m-d');
?>
<div class="vbo-tableaux-tbl-container">
<div class="vbo-table-responsive vbo-tableaux-tbl-wrap" id="vbo-tableaux-table-scroller">
<table class="vbo-table vbo-tableaux-table">
<thead class="vbo-tableaux-table-head" style="display: none;">
<tr class="vbo-tableaux-table-head-row">
<th class="vbo-tableaux-table-head-cell vbo-tableaux-table-head-cell-empty"> </th>
<?php
foreach ($thead_info as $head_day) {
?>
<th class="vbo-tableaux-table-head-cell">
<div class="vbo-tableaux-table-head-cell-monyear">
<span><?php echo $head_day['mon'] . ' ' . $head_day['year']; ?></span>
</div>
<div class="vbo-tableaux-table-head-cell-wmday">
<span><?php echo $head_day['wday'] . ' ' . $head_day['mday']; ?></span>
</div>
</th>
<?php
}
?>
</tr>
</thead>
<tbody>
<tr class="vbo-tableaux-monthsrow">
<td class="vbo-tableaux-emptycell"> </td>
<?php
foreach ($months_days as $mkey => $totdays) {
$mkeyparts = explode('_', $mkey);
?>
<td class="vbo-tableaux-monthcell" colspan="<?php echo $totdays; ?>"><?php echo $long_months_labels[($mkeyparts[0] - 1)] . ' ' . $mkeyparts[1]; ?></td>
<?php
}
?>
</tr>
<tr class="vbo-tableaux-firstrow">
<td class="vbo-tableaux-emptycell"> </td>
<?php
$newmonth = 0;
$nowinfo = getdate($fromts);
while ($nowinfo[0] <= $tots) {
$nowinfo_ymd = date('Y-m-d', $nowinfo[0]);
$monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : '';
$monthclass = $nowinfo_ymd == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass;
$newmonth = $nowinfo['mon'];
$read_day = $days_labels[$nowinfo['wday']] . ' ' . $nowinfo['mday'] . ' ' . $months_labels[($nowinfo['mon'] - 1)] . ' ' . $nowinfo['year'];
$fest_class = isset($this->festivities[$nowinfo_ymd]) ? ' vbo-tableaux-festcell' : '';
?>
<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; ?>">
<div class="vbo-tableaux-day-cont">
<span class="vbo-tableaux-day-wday"><?php echo $days_labels[$nowinfo['wday']]; ?></span>
<span class="vbo-tableaux-day-mday"><?php echo $nowinfo['mday']; ?></span>
</div>
</td>
<?php
// next loop
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
}
?>
</tr>
<?php
$rooms_features_map = array();
$rooms_features_bookings = array();
$colortags_map = array();
foreach ($rooms as $rid => $rdata) {
// distinctive features
$room_params = !empty($rdata['params']) ? json_decode($rdata['params'], true) : array();
if (is_array($room_params) && array_key_exists('features', $room_params) && count($room_params['features']) > 0) {
$rooms_features_map[$rid] = array();
foreach ($room_params['features'] as $rind => $rfeatures) {
foreach ($rfeatures as $fname => $fval) {
if (strlen($fval)) {
$rooms_features_map[$rid][$rind] = '#'.$fval;
break;
}
}
}
if (!(count($rooms_features_map[$rid]) > 0)) {
unset($rooms_features_map[$rid]);
}
}
// extra class for single-unit rooms
$room_extra_class = $rdata['units'] == 1 ? 'vbo-tableaux-booking-singleunit ' : '';
?>
<tr class="vbo-tableaux-roomrow">
<td class="vbo-tableaux-roomname" data-roomid="<?php echo $rdata['id']; ?>"><?php echo $rdata['name']; ?></td>
<?php
$nowinfo = getdate($fromts);
$bookbuffer = array();
$prevbuffer = array();
$positions = array();
$newmonth = 0;
while ($nowinfo[0] <= $tots) {
$nowinfo_ymd = date('Y-m-d', $nowinfo[0]);
$monthclass = !empty($newmonth) && $nowinfo['mon'] != $newmonth ? ' vbo-tableaux-newmonthcell' : '';
$monthclass = $nowinfo_ymd == $todaydt ? ' vbo-tableaux-todaycell' : $monthclass;
$newmonth = $nowinfo['mon'];
/**
* Critical dates defined at room-day level, or for any sub-unit.
*
* @since 1.13.5
*/
$rdaynote_class = ' vbo-roomdaynote-empty';
$rdaynote_icn = 'far fa-sticky-note';
$cell_rdnotes = '';
$rdnkeys_lookup = range(0, $rdata['units']);
$rdaynote_keyids = array();
$glob_rdn_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_0';
// find room-day note keys with some notes (room-day level or subroom-day level)
foreach ($rdnkeys_lookup as $lookup_index) {
$rdaynote_keyid = $nowinfo_ymd . '_' . $rdata['id'] . '_' . $lookup_index;
if (isset($this->rdaynotes[$rdaynote_keyid])) {
// push associative index with notes
$rdaynote_keyids[$lookup_index] = $rdaynote_keyid;
}
}
if (count($rdaynote_keyids)) {
// some notes exist for this combination of date, room ID and subunit
$rdaynote_class = ' vbo-roomdaynote-full';
$rdaynote_icn = 'sticky-note';
/**
* Try to populate the notes for this room-day cell
* only if the previous day does not have the same note.
* Just the first readable room-day cell should have notes.
*/
$notes_titles = array();
$yesterday_ts = mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] - 1), $nowinfo['year']);
$yesterday_ymd = date('Y-m-d', $yesterday_ts);
// loop through all the keys with notes
foreach ($rdaynote_keyids as $lookup_index => $rdaynote_keyid) {
$yesterday_keyid = $yesterday_ymd . '_' . $rdata['id'] . '_' . $lookup_index;
foreach ($this->rdaynotes[$rdaynote_keyid]['info'] as $today_note) {
// only manual (custom) room-day notes will be displayed
$display_note = ($today_note->type == 'custom');
if (isset($this->rdaynotes[$yesterday_keyid])) {
// make sure the same note is not present for yesterday
foreach ($this->rdaynotes[$yesterday_keyid]['info'] as $yesterday_note) {
if ($today_note->type == $yesterday_note->type && $today_note->name == $yesterday_note->name) {
// same note available also for yesterday
$display_note = false;
break;
}
}
}
if ($display_note) {
// push just the name of the note
array_push($notes_titles, $today_note->name);
}
}
}
// separate all notes (if any) with comma
$cell_rdnotes = implode(', ', $notes_titles);
//
}
//
?>
<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); ?>">
<?php
$room_bookings = array();
if (isset($rooms_busy[$rid])) {
foreach ($rooms_busy[$rid] as $b) {
$tmpone = getdate($b['checkin']);
$ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']);
$tmptwo = getdate($b['checkout']);
$conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']);
$b['basefrom'] = $ritts;
$b['baseto'] = $conts;
if ($nowinfo[0] >= $ritts && $nowinfo[0] <= $conts) {
array_push($room_bookings, $b);
}
}
/**
* By default, we attempt to sort the bookings for this day by room index.
*
* @since 1.13.5 (J) - 1.3.5 (WP)
*/
if (count($room_bookings)) {
$rindexes_map = array();
foreach ($room_bookings as $rbk => $rbval) {
$rindexes_map[$rbk] = isset($rbval['indexes']) ? $rbval['indexes'] : '';
}
asort($rindexes_map);
$room_bookings_copy = array();
foreach ($rindexes_map as $rbk => $rbval) {
array_push($room_bookings_copy, $room_bookings[$rbk]);
}
$room_bookings = $room_bookings_copy;
}
//
}
if (count($room_bookings) && count($bookbuffer)) {
// sort bookings according to the previous map
$newbookings = array();
foreach ($bookbuffer as $oid) {
foreach ($room_bookings as $kb => $rbook) {
if ($oid == $rbook['idorder']) {
// get this key first
$newbookings[$kb] = $rbook;
// do not break the loop as there could be multiple idorder, just continue
continue;
}
}
}
if (count($newbookings)) {
// merge array by keys by unsetting double keys from second array
$room_bookings = $newbookings + $room_bookings;
}
// copy buffer before reset to see whether this is the first cell displayed for the booking
$prevbuffer = $bookbuffer;
// reset buffer to fill the current day bookings
$bookbuffer = array();
}
$indexpos = 0;
foreach ($room_bookings as $k => $rbook) {
$contclass = 'stay';
if ($rbook['basefrom'] == $nowinfo[0]) {
$contclass = 'checkin';
} elseif ($rbook['baseto'] == $nowinfo[0]) {
$contclass = 'checkout';
}
$shortstaycls = '';
if (ceil(($rbook['baseto'] - $rbook['basefrom']) / 86400) < 2) {
$shortstaycls = ' vbo-tableaux-booking-short';
}
//check position
$pos = $indexpos;
if (isset($positions[$rbook['idorder']]) && $indexpos < $positions[$rbook['idorder']]) {
// print empty blocks to give the right position to this booking
$pos = $indexpos.'-'.$positions[$rbook['idorder']];
$looplim = ($positions[$rbook['idorder']] - $indexpos);
for ($i = 0; $i < $looplim; $i++) {
$indexpos++;
?>
<div class="<?php echo $room_extra_class; ?>vbo-tableaux-booking vbo-tableaux-booking-empty">
<span> </span>
</div>
<?php
}
$pos .= '-'.$indexpos;
}
// push position
if (!isset($positions[$rbook['idorder']])) {
$positions[$rbook['idorder']] = $indexpos;
}
// push booking to the buffer for the ordering in the next loop
array_push($bookbuffer, $rbook['idorder']);
// cell content
$cellcont = ' ';
// booking color tag (if enabled from overv View through cookie or session)
if ($this->pbmode == 'tags' && !isset($colortags_map[$rbook['idorder']])) {
$colortags_map[$rbook['idorder']] = VikBooking::applyBookingColorTag($rbook);
}
if (!in_array($rbook['idorder'], $prevbuffer)) {
// first time we print the details for this booking - compose the content of the element
$cellcont = '';
// customer details
if (!empty($rbook['first_name']) || !empty($rbook['last_name'])) {
/**
* Check if we need to display a profile picture or a channel logo.
*
* @since 1.16.0 (J) - 1.6.0 (WP)
*/
$booking_avatar_src = null;
$booking_avatar_alt = null;
if (!empty($rbook['pic'])) {
// customer profile picture
$booking_avatar_src = strpos($rbook['pic'], 'http') === 0 ? $rbook['pic'] : VBO_SITE_URI . 'resources/uploads/' . $rbook['pic'];
$booking_avatar_alt = basename($booking_avatar_src);
} elseif (!empty($rbook['channel'])) {
// channel logo
$logo_helper = VikBooking::getVcmChannelsLogo($rbook['channel'], $get_istance = true);
if ($logo_helper !== false) {
$booking_avatar_src = $logo_helper->getSmallLogoURL();
$booking_avatar_alt = $logo_helper->provenience;
}
}
if (!empty($booking_avatar_src)) {
// make sure the alt attribute is not too long in case of broken images
$booking_avatar_alt = !empty($booking_avatar_alt) && strlen($booking_avatar_alt) > 15 ? '...' . substr($booking_avatar_alt, -12) : $booking_avatar_alt;
// append booking avatar image
$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>';
}
// customer record
$cellcont .= '<span class="vbo-tableaux-guest-name">' . $rbook['first_name'] . ' ' . $rbook['last_name'] . '</span>';
} else {
// parse the customer data string
$custdata_parts = explode("\n", $rbook['custdata']);
$enoughinfo = false;
if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) {
// get the first two fields
$custvalues = array();
foreach ($custdata_parts as $custdet) {
if (strlen($custdet) < 1) {
continue;
}
$custdet_parts = explode(':', $custdet);
if (count($custdet_parts) >= 2) {
unset($custdet_parts[0]);
array_push($custvalues, trim(implode(':', $custdet_parts)));
}
if (count($custvalues) > 1) {
break;
}
}
if (count($custvalues) > 1) {
$enoughinfo = true;
$cellcont .= '<span class="vbo-tableaux-guest-name">' . implode(' ', $custvalues) . '</span>';
}
}
if (!$enoughinfo) {
$cellcont .= '<span class="vbo-tableaux-guest-name">' . $rbook['idorder'] . '</span>';
}
}
// distinctive features
if (!empty($rbook['indexes']) && isset($rooms_features_map[$rid])) {
$bookindexes = explode(';', $rbook['indexes']);
$roomindexes = explode(';', $rbook['roomids']);
if (!isset($rooms_features_bookings[$rid.'_'.$rbook['idorder']])) {
// 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)
$rooms_features_bookings[$rid.'_'.$rbook['idorder']] = 0;
} else {
// increment index for this room booking
$rooms_features_bookings[$rid.'_'.$rbook['idorder']]++;
}
// seek for the index occurrence of this room in the list of rooms booked
$count_pos = -1;
$room_pos = null;
foreach ($roomindexes as $rk => $rv) {
if ((int)$rv == (int)$rid) {
$count_pos++;
if ($count_pos == $rooms_features_bookings[$rid.'_'.$rbook['idorder']]) {
$room_pos = $rk;
break;
}
}
}
$nowfeatindex = isset($bookindexes[$room_pos]) ? $room_pos : null;
if (!is_null($room_pos) && isset($bookindexes[$nowfeatindex]) && isset($rooms_features_map[$rid][$bookindexes[$nowfeatindex]])) {
// get this room feature
$cellcont .= '<span class="vbo-tableaux-roomindex">' . $rooms_features_map[$rid][$bookindexes[$nowfeatindex]] . '</span> ';
}
}
// add invoice/receipt number if available (taken from booking color tag)
if (isset($colortags_map[$rbook['idorder']]) && count($colortags_map[$rbook['idorder']])) {
if (isset($colortags_map[$rbook['idorder']]['invoice_number'])) {
// invoice number
$invstyle = isset($colortags_map[$rbook['idorder']]['fontcolor']) ? ' style="color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';"' : '';
$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>';
} elseif (isset($colortags_map[$rbook['idorder']]['receipt_number'])) {
// receipt number
$cellcont .= ' <i class="'.VikBookingIcons::i('file-text-o').'" title="'.JText::translate('VBOFISCRECEIPT').' #'.$colortags_map[$rbook['idorder']]['receipt_number'].'"></i>';
}
}
}
// color tag styles
$cont_styles = array();
$span_styles = array();
if (isset($colortags_map[$rbook['idorder']]) && count($colortags_map[$rbook['idorder']])) {
$cont_styles[] = 'background-color: '.$colortags_map[$rbook['idorder']]['color'].';';
if (isset($colortags_map[$rbook['idorder']]['fontcolor'])) {
$cont_styles[] = 'color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';';
$span_styles[] = 'color: '.$colortags_map[$rbook['idorder']]['fontcolor'].';';
}
}
// 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)
$last_checkout_class = '';
if ($rdata['units'] == 1 && strpos($contclass, 'checkout') !== false && !isset($room_bookings[($k + 1)])) {
$last_checkout_class = 'vbo-tableaux-booking-checkout-last ';
}
?>
<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']; ?>">
<span<?php echo count($span_styles) ? ' style="'.implode('', $span_styles).'"' : ''; ?>><?php echo $cellcont; ?></span>
</div>
<?php
// increase the positioning index
$indexpos++;
}
?>
<span class="vbo-roomdaynote-trigger" data-roomday="<?php echo $glob_rdn_keyid; ?>"><?php VikBookingIcons::e($rdaynote_icn, 'vbo-roomdaynote-display'); ?></span>
</td>
<?php
// next loop
$nowinfo = getdate(mktime(0, 0, 0, $nowinfo['mon'], ($nowinfo['mday'] + 1), $nowinfo['year']));
}
?>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
</div>
<div class="vbo-modal-overlay-block vbo-modal-overlay-block-fests">
<a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
<div class="vbo-modal-overlay-content vbo-modal-overlay-content-fests">
<div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-fests">
<h3><?php VikBookingIcons::e('star'); ?> <span></span></h3>
</div>
<div class="vbo-modal-overlay-content-body">
<div class="vbo-overlay-fests-list"></div>
<div class="vbo-overlay-fests-addnew" data-ymd="">
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4>
<div class="vbo-overlay-fests-addnew-elem">
<label for="vbo-newfest-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label>
<input type="text" id="vbo-newfest-name" value="" />
</div>
<div class="vbo-overlay-fests-addnew-elem">
<label for="vbo-newfest-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label>
<textarea id="vbo-newfest-descr"></textarea>
</div>
<div class="vbo-overlay-fests-addnew-save">
<button type="button" class="btn btn-success" onclick="vboAddFest(this);"><?php echo JText::translate('VBSAVE'); ?></button>
</div>
</div>
</div>
</div>
</div>
<div class="vbo-modal-overlay-block vbo-modal-overlay-block-roomdaynotes">
<a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
<div class="vbo-modal-overlay-content vbo-modal-overlay-content-roomdaynotes">
<div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-roomdaynotes">
<h3><?php VikBookingIcons::e('exclamation-circle'); ?> <span></span></h3>
</div>
<div class="vbo-modal-overlay-content-body">
<div class="vbo-modal-roomdaynotes-list"></div>
<div class="vbo-modal-roomdaynotes-addnew" data-readymd="" data-ymd="" data-roomid="" data-subroomid="">
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4>
<div class="vbo-modal-roomdaynotes-addnew-elem">
<label for="vbo-newrdnote-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label>
<input type="text" id="vbo-newrdnote-name" value="" />
</div>
<div class="vbo-modal-roomdaynotes-addnew-elem">
<label for="vbo-newrdnote-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label>
<textarea id="vbo-newrdnote-descr"></textarea>
</div>
<div class="vbo-modal-roomdaynotes-addnew-elem">
<label for="vbo-newrdnote-cdays"><?php echo JText::translate('VBOCONSECUTIVEDAYS'); ?></label>
<input type="number" id="vbo-newrdnote-cdays" min="0" max="365" value="0" onchange="vboRdayNoteCdaysCount();" onkeyup="vboRdayNoteCdaysCount();" />
<span class="vbo-newrdnote-dayto">
<span class="vbo-newrdnote-dayto-lbl"><?php echo JText::translate('VBOUNTIL'); ?></span>
<span class="vbo-newrdnote-dayto-val"></span>
</span>
</div>
<div class="vbo-modal-roomdaynotes-addnew-save">
<button type="button" class="btn btn-success" onclick="vboAddRoomDayNote(this);"><?php echo JText::translate('VBSAVE'); ?></button>
</div>
</div>
</div>
</div>
</div>
<a class="vbo-basenavuri-details" href="index.php?option=com_vikbooking&task=editorder&goto=tableaux&cid[]=%d" style="display: none;"></a>
<a class="vbo-basenavuri-edit" href="index.php?option=com_vikbooking&task=editbusy&goto=tableaux&cid[]=%d" style="display: none;"></a>
<script type="text/javascript">
var vboFests = <?php echo json_encode($this->festivities); ?>;
var vboRdayNotes = <?php echo json_encode($this->rdaynotes); ?>;
var vbodialog_on = false;
var vbodialogfests_on = false;
var vbodialogrdaynotes_on = false;
/**
* Fests dialog
*/
function hideVboDialogFests() {
if (vbodialogfests_on === true) {
jQuery(".vbo-modal-overlay-block-fests").fadeOut(400, function () {
jQuery(".vbo-modal-overlay-content-fests").show();
});
vbodialogfests_on = false;
}
}
/**
* Room-day-notes dialog
*/
function hideVboDialogRdaynotes() {
if (vbodialogrdaynotes_on === true) {
jQuery(".vbo-modal-overlay-block-roomdaynotes").fadeOut(400, function () {
jQuery(".vbo-modal-overlay-content-roomdaynotes").show();
});
// reset values
jQuery('#vbo-newrdnote-name').val('');
jQuery('#vbo-newrdnote-descr').val('');
jQuery('#vbo-newrdnote-cdays').val('0').trigger('change');
// turn flag off
vbodialogrdaynotes_on = false;
}
}
/* Hover Tooltip */
var hovtimer;
var hovtip = false;
var vboMessages = {
loadingTip: "<?php echo addslashes(JText::translate('VIKLOADING')); ?>",
numRooms: "<?php echo addslashes(JText::translate('VBEDITORDERROOMSNUM')); ?>",
numAdults: "<?php echo addslashes(JText::translate('VBEDITORDERADULTS')); ?>",
numNights: "<?php echo addslashes(JText::translate('VBDAYS')); ?>",
checkinLbl: "<?php echo addslashes(JText::translate('VBPICKUPAT')); ?>",
checkoutLbl: "<?php echo addslashes(JText::translate('VBRELEASEAT')); ?>",
numChildren: "<?php echo addslashes(JText::translate('VBEDITORDERCHILDREN')); ?>",
totalAmount: "<?php echo addslashes(JText::translate('VBEDITORDERNINE')); ?>",
totalPaid: "<?php echo addslashes(JText::translate('VBPEDITBUSYTOTPAID')); ?>",
currencySymb: "<?php echo $currencysymb; ?>"
};
function registerHoveringTooltip(that) {
if (hovtip) {
return false;
}
if (hovtimer) {
clearTimeout(hovtimer);
hovtimer = null;
}
var elem = jQuery(that);
var cellheight = elem.outerHeight();
hovtimer = setTimeout(function() {
// turn flag on
hovtip = true;
// calculate cell-element position
let pos_top = elem.offset().top;
let pos_left = elem.offset().left;
let elem_height = elem.outerHeight();
let screen_width = window?.screen?.width || 0;
// build tooltip block element
let tooltip_block = jQuery('<div></div>');
tooltip_block.addClass('vbo-overview-tipblock');
tooltip_block.append("<div class=\"vbo-overview-tipinner\"><span class=\"vbo-overview-tiploading\">" + vboMessages.loadingTip + "</span></div>");
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>");
// calculate block position
tooltip_block.css('top', (pos_top + elem_height - 16) + 'px');
// tooltip_block.css('left', (pos_left - 6) + 'px');
if (screen_width > 600 && (pos_left + 400) > screen_width) {
// place the tooltip starting from right
tooltip_block.css('left', (pos_left - (400 - elem.outerWidth())) + 'px');
} else {
// regular placing starting from left
tooltip_block.css('left', (pos_left - 6) + 'px');
}
// append block to body
tooltip_block.appendTo(jQuery('body'));
// load tooltip bookings
loadTooltipBookings(elem.attr('data-bid'));
}, 900);
}
function unregisterHoveringTooltip() {
clearTimeout(hovtimer);
hovtimer = null;
}
/**
* @deprecated 1.16.10 (J) - 1.6.10 (WP)
*/
function adjustHoveringTooltip() {
setTimeout(function() {
var difflim = 35;
var otop = jQuery(".vbo-overview-tipblock").offset().top;
if (otop < difflim) {
jQuery(".vbo-overview-tipblock").css("bottom", "-="+(difflim - otop));
} else {
// check top position from table
var tipheight = jQuery(".vbo-overview-tipblock").outerHeight();
var blocktop = jQuery(".vbo-overview-tipblock").parent().offset().top;
var tabletop = jQuery(".vbo-tableaux-table").offset().top;
if ((blocktop - tabletop) < tipheight) {
// tooltip is going under the table, move it down the container
jQuery(".vbo-overview-tipblock").css("bottom", "-"+tipheight+'px');
}
// check left position from second cell
var tipwidth = jQuery(".vbo-overview-tipblock").outerWidth();
var cellscndleft = jQuery('.vbo-tableaux-table').find('tr td').first().next().offset().left;
var blockleft = jQuery('.vbo-overview-tipblock').parent().offset().left;
if (tipwidth > (blockleft - cellscndleft)) {
// tooltip should start from left: 0 going to the right
jQuery(".vbo-overview-tipblock").css("left", "0px");
}
}
}, 100);
}
function hideVboTooltip() {
jQuery('.vbo-overview-tipblock').remove();
hovtip = false;
}
function loadTooltipBookings(bid) {
if (!bid || bid === undefined || !bid.length) {
hideVboTooltip();
return false;
}
// ajax request
var jqxhr = jQuery.ajax({
type: "POST",
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=getbookingsinfo'); ?>",
data: {
tmpl: "component",
idorders: bid
}
}).done(function(res) {
try {
var obj_res = typeof res === 'string' ? JSON.parse(res) : res;
jQuery('.vbo-overview-tiploading').remove();
var container = jQuery('.vbo-overview-tipinner');
jQuery(obj_res).each(function(k, v) {
// get base navigation URIs
var base_uri_details = jQuery('.vbo-basenavuri-details').attr('href');
var base_uri_edit = jQuery('.vbo-basenavuri-edit').attr('href');
// build content
var bcont = "<div class=\"vbo-overview-tip-bookingcont\">";
bcont += "<div class=\"vbo-overview-tip-bookingcont-left\">";
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>";
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>";
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>";
bcont += "</div>";
bcont += "<div class=\"vbo-overview-tip-bookingcont-right\">";
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>";
if (v.roomsnum > 1) {
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>";
}
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>";
if (v.hasOwnProperty('rindexes')) {
for (var rindexk in v.rindexes) {
if (v.rindexes.hasOwnProperty(rindexk)) {
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>";
}
}
}
if (v.hasOwnProperty('channelimg')) {
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>";
}
bcont += "<div class=\"vbo-overview-tip-bookingcont-total\">";
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.totalAmount+"</span><span class=\"vbo-overview-tip-cnt\">"+vboMessages.currencySymb+" "+v.format_tot+"</span></div>";
if (v.totpaid > 0.00) {
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">"+vboMessages.totalPaid+"</span><span class=\"vbo-overview-tip-cnt\">"+vboMessages.currencySymb+" "+v.format_totpaid+"</span></div>";
}
var getnotes = v.adminnotes;
if (getnotes !== null && getnotes.length) {
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>";
}
bcont += "</div>";
bcont += "</div>";
bcont += "</div>";
container.append(bcont);
jQuery('.vbo-overview-tipexpander').show();
});
/**
* @deprecated 1.16.10 (J) - 1.6.10 (WP)
*/
// adjust the position so that it won't go under other contents
// adjustHoveringTooltip();
} catch(err) {
// restore
hideVboTooltip();
// display error
console.error('could not parse JSON response', err, res);
alert('Could not parse JSON response');
}
}).fail(function(err) {
// restore
hideVboTooltip();
// display error
console.error(err);
alert(err.responseText);
});
}
function vboSendPrintTableaux() {
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();
setTimeout(function() {
jQuery('#adminForm').attr('target', '_self');
jQuery('.vbo-tableaux-rmafterprint').remove();
}, 500);
}
/**
* Fests
*/
function vboRenderFests(day, daytitle) {
// set day title
if (daytitle) {
jQuery('.vbo-modal-overlay-content-fests').find('h3').find('span').text(daytitle);
}
// compose fests information
var fests_html = '';
if (vboFests[day] && vboFests[day]['festinfo'] && vboFests[day]['festinfo'].length) {
for (var i = 0; i < vboFests[day]['festinfo'].length; i++) {
var fest = vboFests[day]['festinfo'][i];
fests_html += '<div class="vbo-overlay-fest-details">';
fests_html += ' <div class="vbo-fest-info">';
fests_html += ' <div class="vbo-fest-name">' + fest['trans_name'] + '</div>';
fests_html += ' <div class="vbo-fest-desc">' + fest['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>';
fests_html += ' </div>';
fests_html += ' <div class="vbo-fest-cmds">';
fests_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveFest(\'' + day + '\', \'' + i + '\', \'' + fest['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt'); ?></button>';
fests_html += ' </div>';
fests_html += '</div>';
}
}
// update ymd key for the selected date, useful for adding new fests
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', day);
// set content and display modal
jQuery('.vbo-overlay-fests-list').html(fests_html);
jQuery('.vbo-modal-overlay-block-fests').fadeIn();
vbodialogfests_on = true;
}
function vboRemoveFest(day, index, fest_type, that) {
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) {
return false;
}
var elem = jQuery(that);
// make the AJAX request to the controller to remove this fest from the DB
var jqxhr = jQuery.ajax({
type: "POST",
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_fest'); ?>",
data: {
tmpl: "component",
dt: day,
ind: index,
type: fest_type
}
}).done(function(res) {
if (res.indexOf('e4j.ok') >= 0) {
// delete fest also from the json-decode array of objects
if (vboFests[day] && vboFests[day]['festinfo']) {
// use splice to remove the desired index from array, or delete would not make the length of the array change
vboFests[day]['festinfo'].splice(index, 1);
// re-build indexes of delete buttons, fundamental for removing the right index at next click
vboRenderFests(day);
if (!vboFests[day]['festinfo'].length) {
// delete also this date object from fests
delete vboFests[day];
// no more fests, remove the class for this date from all cells
jQuery('td.vbo-tableaux-daycell[data-ymd="'+day+'"]').removeClass('vbo-tableaux-festcell');
}
}
elem.closest('.vbo-overlay-fest-details').remove();
} else {
console.log(res);
alert('Invalid response');
}
}).fail(function() {
alert('Request failed');
});
}
function vboAddFest(that) {
var elem = jQuery(that);
var ymd = elem.closest('.vbo-overlay-fests-addnew').attr('data-ymd');
var fest_name = jQuery('#vbo-newfest-name').val();
var fest_descr = jQuery('#vbo-newfest-descr').val();
if (!fest_name.length) {
return false;
}
// make the AJAX request to the controller to add this fest to the DB
var jqxhr = jQuery.ajax({
type: "POST",
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_fest'); ?>",
data: {
tmpl: "component",
dt: ymd,
type: "custom",
name: fest_name,
descr: fest_descr
}
}).done(function(res) {
// parse the JSON response that contains the fest object for the passed date
try {
var stored_fest = JSON.parse(res);
if (!vboFests.hasOwnProperty(stored_fest['dt'])) {
// we need to add the proper class to all cells to show that there is a fest
jQuery('td.vbo-tableaux-daycell[data-ymd="'+stored_fest['dt']+'"]').addClass('vbo-tableaux-festcell');
}
vboFests[stored_fest['dt']] = stored_fest;
hideVboDialogFests();
// reset input fields
jQuery('#vbo-newfest-name').val('');
jQuery('#vbo-newfest-descr').val('');
} catch (e) {
console.log(res);
alert('Invalid response');
return false;
}
}).fail(function() {
alert('Request failed');
});
}
//
/**
* Room-day notes
*/
var rdaynote_icn_full = '<?php echo VikBookingIcons::i('sticky-note', 'vbo-roomdaynote-display'); ?>';
var rdaynote_icn_empty = '<?php echo VikBookingIcons::i('far fa-sticky-note', 'vbo-roomdaynote-display'); ?>';
var rooms_features_map = JSON.parse('<?php echo isset($rooms_features_map) && count($rooms_features_map) ? json_encode($rooms_features_map) : json_encode(array()); ?>');
function vboRenderRdayNotes(day, idroom, subunit, readymd) {
// compose room-day notes information (subunit always = 0 for room-day level)
var notes_html = '';
var keyids = new Array;
// always push 0 as the room-level day note key
keyids.push(0);
// grab all the other note keys at sub-unit level
if (jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').length) {
var all_nkeys = jQuery('.vbo-tableaux-roombooks[data-dayrid="' + day + idroom + '"]').attr('data-rdnkeys');
if (all_nkeys && all_nkeys.length) {
var nkeys = all_nkeys.split(',');
for (var k in nkeys) {
var int_index = parseInt(nkeys[k]);
if (!nkeys.hasOwnProperty(k) || isNaN(int_index) || int_index < 1) {
continue;
}
// push sub-unit key for lookup
keyids.push(nkeys[k]);
}
}
}
// parse all room keys with notes
for (var z = 0; z < keyids.length; z++) {
// this is the real sub-unit we are parsing
var subunit_index = keyids[z];
var keyid = day + '_' + idroom + '_' + subunit_index;
if (vboRdayNotes.hasOwnProperty(keyid) && vboRdayNotes[keyid]['info'] && vboRdayNotes[keyid]['info'].length) {
for (var i = 0; i < vboRdayNotes[keyid]['info'].length; i++) {
var note_data = vboRdayNotes[keyid]['info'][i];
var subunit_name = '';
if (parseInt(subunit_index) > 0) {
subunit_name = '(' + subunit_index + ') ';
if (rooms_features_map.hasOwnProperty(idroom) && rooms_features_map[idroom].hasOwnProperty(subunit_index)) {
subunit_name = rooms_features_map[idroom][subunit_index] + ' - ';
}
}
notes_html += '<div class="vbo-overlay-fest-details vbo-modal-roomdaynotes-note-details">';
notes_html += ' <div class="vbo-fest-info vbo-modal-roomdaynotes-note-info">';
notes_html += ' <div class="vbo-fest-name vbo-modal-roomdaynotes-note-name">' + subunit_name + note_data['name'] + '</div>';
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>';
notes_html += ' </div>';
notes_html += ' <div class="vbo-fest-cmds vbo-modal-roomdaynotes-note-cmds">';
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>';
notes_html += ' </div>';
notes_html += '</div>';
}
}
}
// update attributes keys for the selected date, useful for adding new notes (always at room-level)
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd', day).attr('data-roomid', idroom).attr('data-subroomid', '0');
if (readymd !== null) {
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd', readymd);
jQuery('.vbo-newrdnote-dayto-val').text(readymd);
}
// set content and display modal
jQuery('.vbo-modal-roomdaynotes-list').html(notes_html);
}
function vboAddRoomDayNote(that) {
var mainelem = jQuery(that).closest('.vbo-modal-roomdaynotes-addnew');
var ymd = mainelem.attr('data-ymd');
var roomid = mainelem.attr('data-roomid');
var subroomid = mainelem.attr('data-subroomid');
var note_name = jQuery('#vbo-newrdnote-name').val();
var note_descr = jQuery('#vbo-newrdnote-descr').val();
var note_cdays = jQuery('#vbo-newrdnote-cdays').val();
if (!note_name.length && !note_descr.length) {
alert('Missing required fields');
return false;
}
// make the AJAX request to the controller to add this note to the DB
var jqxhr = jQuery.ajax({
type: "POST",
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_roomdaynote'); ?>",
data: {
tmpl: "component",
dt: ymd,
idroom: roomid,
subunit: subroomid,
type: "custom",
name: note_name,
descr: note_descr,
cdays: note_cdays
}
}).done(function(res) {
// parse the JSON response that contains the note object for the passed date
try {
var stored_notes = JSON.parse(res);
var counter = 0;
for (var keyid in stored_notes) {
if (!stored_notes.hasOwnProperty(keyid)) {
continue;
}
var is_date_visible = (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').length > 0);
if (!vboRdayNotes.hasOwnProperty(keyid) && is_date_visible) {
// we need to add the proper class to the cell for this note (if it's visible)
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').removeClass('vbo-roomdaynote-empty').addClass('vbo-roomdaynote-full').find('i').attr('class', rdaynote_icn_full);
}
// update global object with the new notes in any case
vboRdayNotes[keyid] = stored_notes[keyid];
// update readable notes in custom data attribute
if (counter < 1 && is_date_visible && note_name.length) {
// we push just this name
var current_cell_notes = jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes');
var all_cell_notes = current_cell_notes && current_cell_notes.length ? current_cell_notes.split(', ') : new Array;
all_cell_notes.push(note_name);
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').attr('data-notes', all_cell_notes.join(', '));
}
// increase counter
counter++;
}
// close modal
hideVboDialogRdaynotes();
// reset input fields
jQuery('#vbo-newrdnote-name').val('');
jQuery('#vbo-newrdnote-descr').val('');
jQuery('#vbo-newrdnote-cdays').val('0').trigger('change');
} catch (e) {
console.log(res);
alert('Invalid response');
return false;
}
}).fail(function() {
alert('Request failed');
});
}
function vboRdayNotesAvailable(day, idroom) {
/**
* We check whether a room has notes at parent or subunit level for the given date.
*/
var base_key = day + '_' + idroom + '_';
var notes_available = false;
for (var k in vboRdayNotes) {
if (!vboRdayNotes.hasOwnProperty(k) || k.indexOf(base_key) < 0) {
continue;
}
// notes found for this room, either parent or sub-unit
if (vboRdayNotes[k]['info'] && vboRdayNotes[k]['info'].length) {
notes_available = true;
break;
}
}
return notes_available;
}
function vboRemoveRdayNote(index, day, idroom, subunit, note_type, that) {
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) {
return false;
}
var elem = jQuery(that);
// make the AJAX request to the controller to remove this note from the DB
var jqxhr = jQuery.ajax({
type: "POST",
url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_roomdaynote'); ?>",
data: {
tmpl: "component",
dt: day,
idroom: idroom,
subunit: subunit,
ind: index,
type: note_type
}
}).done(function(res) {
if (res.indexOf('e4j.ok') >= 0) {
var keyid = day + '_' + idroom + '_' + subunit;
var glob_keyid = day + '_' + idroom + '_0';
// delete note also from the json-decode array of objects
if (vboRdayNotes[keyid] && vboRdayNotes[keyid]['info']) {
// get the original note name
var old_name = vboRdayNotes[keyid]['info'][index]['name'];
// use splice to remove the desired index from array, or delete would not make the length of the array change
vboRdayNotes[keyid]['info'].splice(index, 1);
// re-build indexes of delete buttons, fundamental for removing the right index at next click (reload always at room-level)
vboRenderRdayNotes(day, idroom, '0', null);
if (!vboRdayNotes[keyid]['info'].length && !vboRdayNotesAvailable(day, idroom)) {
// delete also this date object from notes
delete vboRdayNotes[keyid];
// no more notes, update the proper class attribute for this cell (should be visible)
if (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').length) {
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);
}
} else if (old_name && old_name.length) {
// try to adjust the readable notes in custom data attribute
var current_cell_notes = jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').parent('td').attr('data-notes');
var all_cell_notes = current_cell_notes && current_cell_notes.length ? current_cell_notes.split(', ') : new Array;
var new_cell_notes = new Array;
for (var i = 0; i < all_cell_notes.length; i++) {
if (all_cell_notes[i].indexOf(old_name) < 0) {
new_cell_notes.push(all_cell_notes[i]);
}
}
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + glob_keyid + '"]').parent('td').attr('data-notes', new_cell_notes.join(', '));
}
}
elem.closest('.vbo-modal-roomdaynotes-note-details').remove();
} else {
console.log(res);
alert('Invalid response');
}
}).fail(function() {
alert('Request failed');
});
}
function vboRdayNoteCdaysCount() {
var cdays = parseInt(jQuery('#vbo-newrdnote-cdays').val());
var defymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd');
var defreadymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd');
defreadymd = !defreadymd || !defreadymd.length ? defymd : defreadymd;
if (isNaN(cdays) || cdays < 1) {
jQuery('.vbo-newrdnote-dayto-val').text(defreadymd);
return;
}
// calculate target (until) date
var targetdate = new Date(defymd);
targetdate.setDate(targetdate.getDate() + cdays);
var target_y = targetdate.getFullYear();
var target_m = targetdate.getMonth() + 1;
target_m = target_m < 10 ? '0' + target_m : target_m;
var target_d = targetdate.getDate();
target_d = target_d < 10 ? '0' + target_d : target_d;
// display target date
var display_target = target_y + '-' + target_m + '-' + target_d;
// check if we can get the "read ymd property"
if (jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').length) {
display_target = jQuery('.vbo-tableaux-daycell[data-ymd="' + display_target + '"]').attr('data-readymd');
}
jQuery('.vbo-newrdnote-dayto-val').text(display_target);
}
//
/**
* Tells whether an element can fit entirely in the viewport.
* Example: if a table is too high to fit in the screen.
* If false, it means that scrolling will always be needed.
*/
function vboFitsInViewport(selector) {
var elemHeight = jQuery(selector).outerHeight();
var maxHeight = jQuery(window).height();
return elemHeight < maxHeight;
}
// tableaux scrolling
var fittingTableaux = null;
var tableauxStickySet = false;
/**
* Throttle guarantees a constant flow of events at a given time interval,
* but it runs immediately when the event takes place. We rather need a
* debounce technique to group a flurry of events into one single event.
* This is useful for listening to the scrolling event of the table, actually
* the DIV that wraps it with overflow, and setting the sticky headers.
*/
function vboDebounceScroll(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
func.apply(context, args);
}
}
}
/**
* We do not need a throttle technique, but this method would
* throttle the scroll event rather than debouncing it.
*/
function vboThrottleScroll(method, delay) {
var time = Date.now();
return function() {
if ((time + delay - Date.now()) < 0) {
method();
time = Date.now();
}
}
}
/**
* This will fire during the throttle of the scrolling event.
*/
function vboHandleScroll() {
if (fittingTableaux === null) {
fittingTableaux = vboFitsInViewport('.vbo-tableaux-table');
}
if (fittingTableaux) {
// no sticky table headers needed, remove the listener as it is not needed
document.getElementById('vbo-tableaux-table-scroller').removeEventListener('scroll', vboDebounceScroll(vboHandleScroll, 1000));
return;
}
// we have scrolled (vertically or horizontally), update the position of the sticky table head
if (tableauxStickySet) {
// destroy sticky table head
jQuery('table.vbo-tableaux-table').stickyTableHeaders('destroy');
}
// re-build sticky head
jQuery('table.vbo-tableaux-table').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: jQuery('.navbar')});
tableauxStickySet = true;
}
jQuery(function() {
// add listener to scroll event on the main table
document.getElementById('vbo-tableaux-table-scroller').addEventListener('scroll', vboDebounceScroll(vboHandleScroll, 1000));
jQuery('#vbo-date-from').datepicker({
showOn: 'focus',
dateFormat: '<?php echo $juidf; ?>',
<?php echo ($this->mindate > 0 ? 'minDate: "'.date(str_replace('%', '', $nowdf), $this->mindate).'", ' : '').($this->maxdate > 0 ? 'maxDate: "'.date(str_replace('%', '', $nowdf), $this->maxdate).'", ' : ''); ?>
onSelect: function( selectedDate ) {
jQuery('#vbo-date-to').datepicker('option', 'minDate', selectedDate);
jQuery('#vbo-month').val('');
}
});
jQuery('#vbo-date-to').datepicker({
showOn: 'focus',
dateFormat: '<?php echo $juidf; ?>',
<?php echo ($this->mindate > 0 ? 'minDate: "'.date(str_replace('%', '', $nowdf), $this->mindate).'", ' : '').($this->maxdate > 0 ? 'maxDate: "'.date(str_replace('%', '', $nowdf), $this->maxdate).'", ' : ''); ?>
onSelect: function( selectedDate ) {
jQuery('#vbo-date-from').datepicker('option', 'maxDate', selectedDate);
jQuery('#vbo-month').val('');
}
});
jQuery('#vbo-date-from-trig, #vbo-date-to-trig').click(function() {
var jdp = jQuery(this).prev('input.hasDatepicker');
if (jdp.length) {
jdp.focus();
}
});
jQuery('.vbo-tableaux-selmonth').click(function() {
var xts = jQuery(this).attr('data-ts');
var xfrom = jQuery(this).attr('data-from');
var xto = jQuery(this).attr('data-to');
jQuery('#vbo-month').val(xts);
jQuery('#vbo-date-from').val(xfrom);
jQuery('#vbo-date-to').val(xto);
jQuery('#adminForm').submit();
});
/* Expand/Collapse tooltip */
jQuery(document.body).on("click", ".vbo-overview-expandtoggle", function() {
jQuery(this).closest('.vbo-overview-tipblock').toggleClass('vbo-overview-tipblock-expanded');
});
/* ----------------------- */
/* Hover Tooltip */
jQuery('.vbo-tableaux-booking-checkin, .vbo-tableaux-booking-checkout, .vbo-tableaux-booking-stay').hover(function() {
registerHoveringTooltip(this);
}, unregisterHoveringTooltip);
// view booking snapshot
jQuery('.vbo-tableaux-booking').on('click', function(e) {
e.stopPropagation();
let bid = jQuery(this).attr('data-bid');
if (bid) {
VBOCore.handleDisplayWidgetNotification({widget_id: 'booking_details'}, {booking_id: bid});
}
});
jQuery(document).keydown(function(e) {
if (e.keyCode == 27) {
if (hovtip === true) {
hideVboTooltip();
}
if (vbodialogfests_on === true) {
hideVboDialogFests();
}
if (vbodialogrdaynotes_on === true) {
hideVboDialogRdaynotes();
}
}
});
jQuery(document).mouseup(function(e) {
if (!hovtip && !vbodialogfests_on && !vbodialogrdaynotes_on) {
return false;
}
if (hovtip) {
var vbo_overlay_cont = jQuery(".vbo-overview-tipblock");
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
hideVboTooltip();
return true;
}
}
if (vbodialogfests_on) {
var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-fests");
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
hideVboDialogFests();
}
}
if (vbodialogrdaynotes_on) {
var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-roomdaynotes");
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
hideVboDialogRdaynotes();
}
}
});
// fests
jQuery(document.body).on("click", "td.vbo-tableaux-daycell", function() {
if (jQuery(this).hasClass('skip-tableaux-daycell-click')) {
return;
}
var ymd = jQuery(this).attr('data-ymd');
var daytitle = jQuery(this).attr('data-readymd');
if (jQuery(this).hasClass('vbo-tableaux-festcell')) {
// cell has fests
if (!vboFests.hasOwnProperty(ymd)) {
return;
}
vboRenderFests(ymd, daytitle);
} else {
// let the admin create a new fest
// set day title
jQuery('.vbo-modal-overlay-content-fests').find('h3').find('span').text(daytitle);
// update ymd key for the selected date, useful for adding new fests
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', ymd);
// unset content and display modal for just adding a new fest
jQuery('.vbo-overlay-fests-list').html('');
jQuery('.vbo-modal-overlay-block-fests').fadeIn();
vbodialogfests_on = true;
}
});
//
// room-day notes
jQuery(document.body).on("click", ".vbo-roomdaynote-display", function() {
if (!jQuery(this).closest('.vbo-roomdaynote-trigger').length) {
return;
}
var daytitle = new Array;
var roomday_info = jQuery(this).closest('.vbo-roomdaynote-trigger').attr('data-roomday').split('_');
// readable day
var readymd = roomday_info[0];
if (jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').length) {
readymd = jQuery('.vbo-tableaux-daycell[data-ymd="' + roomday_info[0] + '"]').attr('data-readymd');
}
daytitle.push(readymd);
// room name
if (jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').length) {
daytitle.push(jQuery('.vbo-tableaux-roomname[data-roomid="' + roomday_info[1] + '"]').text());
}
// set day title
jQuery('.vbo-modal-overlay-content-head-roomdaynotes').find('h3').find('span').text(daytitle.join(', '));
// populate current room day notes
vboRenderRdayNotes(roomday_info[0], roomday_info[1], roomday_info[2], readymd);
// display modal
jQuery('.vbo-modal-overlay-block-roomdaynotes').fadeIn();
vbodialogrdaynotes_on = true;
//
});
//
// use sticky headers only if the table is longer than the max viewport height
fittingTableaux = vboFitsInViewport('.vbo-tableaux-table');
if (!fittingTableaux) {
// display table head
jQuery('.vbo-tableaux-table-head').show();
// set sticky head for the vertical scrolling
jQuery('table.vbo-tableaux-table').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: jQuery('.navbar')});
tableauxStickySet = true;
} else {
// hide table head
jQuery('.vbo-tableaux-table-head').hide();
}
<?php
if ($printtableaux > 0) {
?>
window.print();
<?php
}
?>
});
</script>