| 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 |
$app = JFactory::getApplication(); |
| 14 |
$vat_included = VikBooking::ivaInclusa(); |
| 15 |
$tax_summary = !$vat_included && VikBooking::showTaxOnSummaryOnly() ? true : false; |
| 16 |
|
| 17 |
$currencysymb = VikBooking::getCurrencySymb(); |
| 18 |
$pitemid = VikRequest::getInt('Itemid', '', 'request'); |
| 19 |
|
| 20 |
// whether to use links to room details |
| 21 |
$link_to_details = VBOFactory::getConfig()->getBool('search_link_roomdetails', false); |
| 22 |
|
| 23 |
// search map |
| 24 |
$is_search_map_enabled = VikBooking::interactiveMapEnabled(); |
| 25 |
|
| 26 |
/** |
| 27 |
* Search results (classic layout) style: list or grid. |
| 28 |
* |
| 29 |
* @since 1.18.3 (J) - 1.8.3 (WP) |
| 30 |
*/ |
| 31 |
$layouts = [ |
| 32 |
'list' => [ |
| 33 |
'title' => JText::translate('VBO_LIST'), |
| 34 |
'icon' => 'th-list', |
| 35 |
], |
| 36 |
'grid' => [ |
| 37 |
'title' => JText::translate('VBO_GRID'), |
| 38 |
'icon' => 'table', |
| 39 |
'class' => 'vblistcontainer-grid', |
| 40 |
], |
| 41 |
]; |
| 42 |
|
| 43 |
// default style (name) |
| 44 |
$default_style = $is_search_map_enabled ? 'grid' : 'list'; |
| 45 |
|
| 46 |
?> |
| 47 |
<div class="vbo-results-filtering"> |
| 48 |
<?php |
| 49 |
if (VBOFactory::getConfig()->getBool('search_filters')) { |
| 50 |
// count the active filters |
| 51 |
$current_filters = (array) $app->input->get('filters', [], 'array'); |
| 52 |
$active_filters = 0; |
| 53 |
foreach ($current_filters as $filter_type => $filter_data) { |
| 54 |
if (empty($filter_data)) { |
| 55 |
continue; |
| 56 |
} |
| 57 |
if (is_array($filter_data)) { |
| 58 |
if (range(0, count($filter_data) - 1) === array_keys($filter_data)) { |
| 59 |
// count non-empty values for this linear array |
| 60 |
$active_filters += count(array_filter($filter_data)); |
| 61 |
} else { |
| 62 |
// associative array filter will count as a single filter |
| 63 |
$is_active_filter = true; |
| 64 |
if ($filter_type === 'price' && !empty($filter_data['min']) && !empty($filter_data['max'])) { |
| 65 |
// ensure the value is not the default range of rates pool or even greater |
| 66 |
if (!$this->rates_pool || (floor((float) $filter_data['min']) == floor(min($this->rates_pool)) && ceil((float) $filter_data['max']) == ceil(max($this->rates_pool)))) { |
| 67 |
// do not count the filter as applied |
| 68 |
$is_active_filter = false; |
| 69 |
} elseif ($this->rates_pool && $filter_data['min'] <= min($this->rates_pool) && $filter_data['max'] >= max($this->rates_pool)) { |
| 70 |
// do not count the filter as applied |
| 71 |
$is_active_filter = false; |
| 72 |
} |
| 73 |
} |
| 74 |
if ($is_active_filter) { |
| 75 |
$active_filters++; |
| 76 |
} |
| 77 |
} |
| 78 |
} else { |
| 79 |
// non empty value will count as a single filter |
| 80 |
$active_filters++; |
| 81 |
} |
| 82 |
} |
| 83 |
// normalize active filters counter, if needed |
| 84 |
if ($active_filters > 99) { |
| 85 |
// convert it to a string |
| 86 |
$active_filters = '99+'; |
| 87 |
} |
| 88 |
?> |
| 89 |
<div class="vbo-results-filters-wrap"> |
| 90 |
<button type="button" class="vbo-results-filters-toggle" data-counter="<?php echo $active_filters ?: ''; ?>"><?php VikBookingIcons::e('sliders-h'); ?> <?php echo JText::translate('VBO_FILTERS'); ?></button> |
| 91 |
<div class="vbo-results-filters-form-helper" style="display: none;"> |
| 92 |
<?php echo $this->loadTemplate('filters'); ?> |
| 93 |
</div> |
| 94 |
</div> |
| 95 |
<?php |
| 96 |
} |
| 97 |
?> |
| 98 |
<div class="vbo-results-style-wrap"> |
| 99 |
<div class="vbo-results-style"> |
| 100 |
<?php |
| 101 |
foreach ($layouts as $layout_type => $layout_data) { |
| 102 |
?> |
| 103 |
<span class="vbo-results-style-option<?php echo $layout_type == $default_style ? ' vbo-results-style-option-active' : ''; ?>" data-type="<?php echo $layout_type; ?>" data-toggle="<?php echo $layout_data['class'] ?? ''; ?>"><?php VikBookingIcons::e($layout_data['icon']); ?> <?php echo $layout_data['title'] ?? ''; ?></span> |
| 104 |
<?php |
| 105 |
} |
| 106 |
?> |
| 107 |
</div> |
| 108 |
</div> |
| 109 |
</div> |
| 110 |
<div class="vbo-results-content<?php echo !$is_search_map_enabled ? ' vbo-results-without-geomap' : ''; ?>"> |
| 111 |
<?php |
| 112 |
/** |
| 113 |
* Interactive map booking. Only for classic booking layout. |
| 114 |
* |
| 115 |
* @since 1.14 (J) - 1.4.0 (WP) |
| 116 |
*/ |
| 117 |
if ($is_search_map_enabled) { |
| 118 |
echo $this->loadTemplate('interactive_map'); |
| 119 |
} |
| 120 |
?> |
| 121 |
<div class="vbo-searchresults-classic-wrap<?php echo !empty($layouts[$default_style]['class']) ? ' ' . $layouts[$default_style]['class'] : ''; ?>"> |
| 122 |
<?php |
| 123 |
$writeroomnum = []; |
| 124 |
foreach ($this->res as $indroom => $rooms) { |
| 125 |
if ($this->roomsnum > 1 && !in_array($indroom, $writeroomnum) && $rooms) { |
| 126 |
$writeroomnum[] = $indroom; |
| 127 |
?> |
| 128 |
<div class="vbo-searchresults-step-content"> |
| 129 |
<div id="vbpositionroom<?php echo $indroom; ?>"></div> |
| 130 |
<div class="vbsearchproominfo"> |
| 131 |
<span class="vbsearchnroom"><?php echo JText::translate('VBSEARCHROOMNUM'); ?> <?php echo $indroom; ?></span> |
| 132 |
<span class="vbsearchroomparty"><?php VikBookingIcons::e('users', 'vbo-pref-color-text'); ?> <?php echo $this->arrpeople[$indroom]['adults']; ?> <?php echo ($this->arrpeople[$indroom]['adults'] == 1 ? JText::translate('VBSEARCHRESADULT') : JText::translate('VBSEARCHRESADULTS')); ?> <?php echo ($this->showchildren && $this->arrpeople[$indroom]['children'] > 0 ? ", ".$this->arrpeople[$indroom]['children']." ".($this->arrpeople[$indroom]['children'] == 1 ? JText::translate('VBSEARCHRESCHILD') : JText::translate('VBSEARCHRESCHILDREN')) : ""); ?></span> |
| 133 |
</div> |
| 134 |
</div> |
| 135 |
<?php |
| 136 |
} |
| 137 |
?> |
| 138 |
<div class="vbo-searchresults-party-content"> |
| 139 |
<?php |
| 140 |
foreach ($rooms as $room) { |
| 141 |
// set a different class to the main div in case the rooms usage is for less people than the capacity |
| 142 |
$rdiffusage = array_key_exists('diffusage', $room[0]) && $this->arrpeople[$indroom]['adults'] < $room[0]['toadult'] ? true : false; |
| 143 |
$has_promotion = array_key_exists('promotion', $room[0]) ? true : false; |
| 144 |
$maindivclass = $rdiffusage ? "room_resultdiffusage" : "room_result"; |
| 145 |
$carats = VikBooking::getRoomCaratOriz($room[0]['idcarat'], $this->vbo_tn); |
| 146 |
|
| 147 |
// prepare CMS contents depending on platform |
| 148 |
$room[0] = VBORoomHelper::getInstance()->prepareCMSContents($room[0], ['smalldesc']); |
| 149 |
|
| 150 |
$saylastavail = false; |
| 151 |
$showlastavail = (int)VikBooking::getRoomParam('lastavail', $room[0]['params']); |
| 152 |
if (!empty($showlastavail) && $showlastavail > 0) { |
| 153 |
if ($room[0]['unitsavail'] <= $showlastavail) { |
| 154 |
$saylastavail = true; |
| 155 |
} |
| 156 |
} |
| 157 |
$searchdet_link = JRoute::rewrite('index.php?option=com_vikbooking&view=searchdetails&roomid='.$room[0]['idroom'].'&checkin='.$this->checkin.'&checkout='.$this->checkout.'&adults='.$this->arrpeople[$indroom]['adults'].'&children='.$this->arrpeople[$indroom]['children'].'&tmpl=component'.(!empty($pitemid) ? '&Itemid='.$pitemid : '')); |
| 158 |
|
| 159 |
/** |
| 160 |
* Build image gallery, if available |
| 161 |
* |
| 162 |
* @since 1.14 (J) - 1.4.0 (WP) |
| 163 |
*/ |
| 164 |
$gallery_data = []; |
| 165 |
if (!empty($room[0]['moreimgs'])) { |
| 166 |
$moreimages = explode(';;', $room[0]['moreimgs']); |
| 167 |
foreach (array_filter($moreimages) as $mimg) { |
| 168 |
// push thumb URL |
| 169 |
$gallery_data[] = $mimg; |
| 170 |
} |
| 171 |
} |
| 172 |
|
| 173 |
// build listing details URI components |
| 174 |
$listing_uri_data = [ |
| 175 |
'option' => 'com_vikbooking', |
| 176 |
'view' => 'roomdetails', |
| 177 |
'roomid' => $room[0]['idroom'], |
| 178 |
'start_date' => date('Y-m-d', $this->checkin), |
| 179 |
'end_date' => date('Y-m-d', $this->checkout), |
| 180 |
'num_adults' => $this->arrpeople[$indroom]['adults'], |
| 181 |
'num_children' => $this->arrpeople[$indroom]['children'], |
| 182 |
'Itemid' => ($pitemid ?: null), |
| 183 |
]; |
| 184 |
// route proper URI |
| 185 |
$listing_page_uri = JRoute::rewrite('index.php?' . http_build_query($listing_uri_data), false); |
| 186 |
|
| 187 |
// use link to listing details page or plain text |
| 188 |
$main_listing_elem = $room[0]['name']; |
| 189 |
if ($link_to_details) { |
| 190 |
// embed HTML link |
| 191 |
$main_listing_elem = '<a class="vbo-search-results-listing-link" href="' . $listing_page_uri . '" target="_blank">' . $room[0]['name'] . '</a>'; |
| 192 |
} |
| 193 |
|
| 194 |
// cut off long descriptions by eventually adding a "read more" link |
| 195 |
$descr_length = strlen((string) $room[0]['smalldesc']); |
| 196 |
$visible_descr = $room[0]['smalldesc']; |
| 197 |
$hidden_descr = ''; |
| 198 |
if ($descr_length > 200 && ($descr_length - 200) > 100) { |
| 199 |
$visible_descr = strip_tags($visible_descr); |
| 200 |
$hidden_descr = '1'; |
| 201 |
if (function_exists('mb_substr')) { |
| 202 |
$visible_descr = mb_substr($visible_descr, 0, 200, 'UTF-8'); |
| 203 |
} else { |
| 204 |
$visible_descr = substr($visible_descr, 0, 200); |
| 205 |
} |
| 206 |
$visible_descr .= '...'; |
| 207 |
} |
| 208 |
?> |
| 209 |
<div class="room_item <?php echo $maindivclass; ?><?php echo $has_promotion === true ? ' vbo-promotion-price' : ''; ?>" id="vbcontainer<?php echo $indroom.'_'.$room[0]['idroom']; ?>"> |
| 210 |
<div class="vblistroomblock"> |
| 211 |
<div class="vbimglistdiv"> |
| 212 |
<div class="vbo-dots-slider-selector"> |
| 213 |
<a href="<?php echo $searchdet_link; ?>" class="vbmodalframe" target="_blank" data-gallery="<?php echo implode('|', $gallery_data); ?>"> |
| 214 |
<?php |
| 215 |
if (!empty($room[0]['img']) && is_file(VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . $room[0]['img'])) { |
| 216 |
?> |
| 217 |
<img class="vblistimg" alt="<?php echo htmlspecialchars($room[0]['name']); ?>" id="vbroomimg<?php echo $indroom.'_'.$room[0]['idroom']; ?>" src="<?php echo VBO_SITE_URI; ?>resources/uploads/<?php echo $room[0]['img']; ?>"/> |
| 218 |
<?php |
| 219 |
} |
| 220 |
?> |
| 221 |
</a> |
| 222 |
</div> |
| 223 |
<div class="vbmodalrdetails"> |
| 224 |
<a href="<?php echo $searchdet_link; ?>" class="vbmodalframe" target="_blank"><?php VikBookingIcons::e('plus'); ?></a> |
| 225 |
</div> |
| 226 |
</div> |
| 227 |
<div class="vbo-info-room"> |
| 228 |
<div class="vbdescrlistdiv"> |
| 229 |
<h4 class="vbrowcname" id="vbroomname<?php echo $indroom.'_'.$room[0]['idroom']; ?>"><?php echo $main_listing_elem; ?></h4> |
| 230 |
<div class="vbrowcdescr"><?php echo $visible_descr; ?></div> |
| 231 |
<?php |
| 232 |
if ($hidden_descr) { |
| 233 |
// display a button to read the full description |
| 234 |
?> |
| 235 |
<div class="vbo-result-readmore-wrap"> |
| 236 |
<a class="vbo-result-readmore-trig" href="JavaScript: void(0);"><?php echo JText::translate('VBO_READ_MORE'); ?></a> |
| 237 |
<div class="vbo-result-readmore-hidden" style="display: none;"><?php echo $room[0]['smalldesc']; ?></div> |
| 238 |
</div> |
| 239 |
<?php |
| 240 |
} |
| 241 |
?> |
| 242 |
</div> |
| 243 |
<?php |
| 244 |
if (!empty($carats)) { |
| 245 |
?> |
| 246 |
<div class="roomlist_carats"> |
| 247 |
<?php echo $carats; ?> |
| 248 |
</div> |
| 249 |
<?php |
| 250 |
} |
| 251 |
?> |
| 252 |
<?php |
| 253 |
if ($has_promotion === true && !empty($room[0]['promotion']['promotxt'])) { |
| 254 |
?> |
| 255 |
<div class="vbo-promotion-block"> |
| 256 |
<div class="vbo-promotion-icon"><?php VikBookingIcons::e('percentage'); ?></div> |
| 257 |
<div class="vbo-promotion-description"> |
| 258 |
<?php echo $room[0]['promotion']['promotxt']; ?> |
| 259 |
</div> |
| 260 |
</div> |
| 261 |
<?php |
| 262 |
} |
| 263 |
?> |
| 264 |
</div> |
| 265 |
</div> |
| 266 |
<div class="vbcontdivtot"> |
| 267 |
<div class="vbdivtot"> |
| 268 |
<div class="vbdivtotinline"> |
| 269 |
<div class="vbsrowprice"> |
| 270 |
<div class="vbrowroomcapacity"> |
| 271 |
<?php |
| 272 |
for ($i = 1; $i <= $room[0]['toadult']; $i++) { |
| 273 |
if ($i <= $this->arrpeople[$indroom]['adults']) { |
| 274 |
VikBookingIcons::e('male', 'vbo-pref-color-text'); |
| 275 |
} else { |
| 276 |
VikBookingIcons::e('male', 'vbo-empty-personicn'); |
| 277 |
} |
| 278 |
} |
| 279 |
$raw_roomcost = $tax_summary ? $room[0]['cost'] : VikBooking::sayCostPlusIva($room[0]['cost'], $room[0]['idprice']); |
| 280 |
?> |
| 281 |
</div> |
| 282 |
<div class="vbsrowpricediv"> |
| 283 |
<span class="room_cost"> |
| 284 |
<?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($raw_roomcost), $currencysymb, ['<span class="vbo_currency">%s</span>', '<span class="vbo_price">%s</span>']); ?> |
| 285 |
</span> |
| 286 |
<?php |
| 287 |
if (isset($room[0]['promotion']) && isset($room[0]['promotion']['discount'])) { |
| 288 |
if ($room[0]['promotion']['discount']['pcent']) { |
| 289 |
/** |
| 290 |
* Do not make an upper-cent operation, but rather calculate the original price proportionally: |
| 291 |
* final price : (100 - discount amount) = x : 100 |
| 292 |
* |
| 293 |
* @since 1.13.5 |
| 294 |
*/ |
| 295 |
$prev_amount = $raw_roomcost * 100 / (100 - $room[0]['promotion']['discount']['amount']); |
| 296 |
} else { |
| 297 |
$prev_amount = $raw_roomcost + $room[0]['promotion']['discount']['amount']; |
| 298 |
} |
| 299 |
if ($prev_amount > 0) { |
| 300 |
?> |
| 301 |
<div class="vbo-room-result-price-before-discount"> |
| 302 |
<span class="room_cost"> |
| 303 |
<?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($prev_amount), $currencysymb, ['<span class="vbo_currency">%s</span>', '<span class="vbo_price">%s</span>']); ?> |
| 304 |
</span> |
| 305 |
</div> |
| 306 |
<?php |
| 307 |
if ($room[0]['promotion']['discount']['pcent']) { |
| 308 |
// hide by default the DIV containing the percent of discount |
| 309 |
?> |
| 310 |
<div class="vbo-room-result-price-before-discount-percent" style="display: none;"> |
| 311 |
<span class="room_cost"> |
| 312 |
<span><?php echo '-' . (float)$room[0]['promotion']['discount']['amount'] . ' %'; ?></span> |
| 313 |
</span> |
| 314 |
</div> |
| 315 |
<?php |
| 316 |
} |
| 317 |
} |
| 318 |
} |
| 319 |
?> |
| 320 |
</div> |
| 321 |
<?php |
| 322 |
if ($saylastavail === true) { |
| 323 |
?> |
| 324 |
<span class="vblastavail"><?php echo JText::sprintf('VBLASTUNITSAVAIL', $room[0]['unitsavail']); ?></span> |
| 325 |
<?php |
| 326 |
} |
| 327 |
?> |
| 328 |
</div> |
| 329 |
<div class="vbselectordiv"> |
| 330 |
<button type="button" id="vbselector<?php echo $indroom.'_'.$room[0]['idroom']; ?>" class="btn vbselectr-result vbo-pref-color-btn" onclick="vbSelectRoom('<?php echo $indroom; ?>', '<?php echo $room[0]['idroom']; ?>');"><?php echo JText::translate('VBSELECTR'); ?></button> |
| 331 |
</div> |
| 332 |
</div> |
| 333 |
</div> |
| 334 |
</div> |
| 335 |
</div> |
| 336 |
<?php |
| 337 |
} |
| 338 |
?> |
| 339 |
</div> |
| 340 |
<?php |
| 341 |
} |
| 342 |
|
| 343 |
/** |
| 344 |
* Unavailable listings. |
| 345 |
* |
| 346 |
* @since 1.17.2 (J) - 1.7.2 (WP) |
| 347 |
*/ |
| 348 |
if ($this->roomsnum === 1 && $this->unavailable_listings && VBOFactory::getConfig()->getBool('search_show_busy_listings', false)) { |
| 349 |
?> |
| 350 |
<div class="vbo-searchresults-party-content vbo-searchresults-party-unavailable-content"> |
| 351 |
<?php |
| 352 |
foreach ($this->unavailable_listings as $listing_id) { |
| 353 |
// fetch the room details |
| 354 |
$listing_details = [VikBooking::getRoomInfo($listing_id)]; |
| 355 |
if (!$listing_details[0]) { |
| 356 |
continue; |
| 357 |
} |
| 358 |
|
| 359 |
// translate records list |
| 360 |
$this->vbo_tn->translateContents($listing_details, '#__vikbooking_rooms'); |
| 361 |
|
| 362 |
// convert list into associative |
| 363 |
$listing_details = $listing_details[0]; |
| 364 |
|
| 365 |
// prepare CMS contents depending on platform |
| 366 |
$listing_details = VBORoomHelper::getInstance()->prepareCMSContents($listing_details, ['smalldesc']); |
| 367 |
|
| 368 |
// build listing details URI components |
| 369 |
$listing_uri_data = [ |
| 370 |
'option' => 'com_vikbooking', |
| 371 |
'view' => 'roomdetails', |
| 372 |
'roomid' => $listing_details['id'], |
| 373 |
'num_adults' => ($this->arrpeople[1]['adults'] ?? 2), |
| 374 |
'num_children' => ($this->arrpeople[1]['children'] ?? 0), |
| 375 |
'Itemid' => ($pitemid ?: null), |
| 376 |
]; |
| 377 |
// route proper URI |
| 378 |
$listing_page_uri = JRoute::rewrite('index.php?' . http_build_query($listing_uri_data), false); |
| 379 |
|
| 380 |
// listing amenities |
| 381 |
$carats = VikBooking::getRoomCaratOriz($listing_details['idcarat'], $this->vbo_tn); |
| 382 |
|
| 383 |
// build image gallery, if available |
| 384 |
$gallery_data = []; |
| 385 |
if (!empty($listing_details['moreimgs'])) { |
| 386 |
$moreimages = explode(';;', $listing_details['moreimgs']); |
| 387 |
foreach (array_filter($moreimages) as $mimg) { |
| 388 |
// push thumb URL |
| 389 |
$gallery_data[] = $mimg; |
| 390 |
} |
| 391 |
} |
| 392 |
|
| 393 |
// cut off long descriptions by eventually adding a "read more" link |
| 394 |
$descr_length = strlen((string) $listing_details['smalldesc']); |
| 395 |
$visible_descr = $listing_details['smalldesc']; |
| 396 |
$hidden_descr = ''; |
| 397 |
if ($descr_length > 200 && ($descr_length - 200) > 100) { |
| 398 |
$visible_descr = strip_tags($visible_descr); |
| 399 |
$hidden_descr = '1'; |
| 400 |
if (function_exists('mb_substr')) { |
| 401 |
$visible_descr = mb_substr($visible_descr, 0, 200, 'UTF-8'); |
| 402 |
} else { |
| 403 |
$visible_descr = substr($visible_descr, 0, 200); |
| 404 |
} |
| 405 |
$visible_descr .= '...'; |
| 406 |
} |
| 407 |
|
| 408 |
// print unavailable listing details |
| 409 |
?> |
| 410 |
<div class="room_item room_result vbo-result-listing-unavailable" data-unavailable-id="<?php echo $listing_details['id']; ?>"> |
| 411 |
<div class="vblistroomblock"> |
| 412 |
<div class="vbimglistdiv"> |
| 413 |
<div class="vbo-dots-slider-selector"> |
| 414 |
<a href="<?php echo $listing_page_uri; ?>" target="_blank" data-gallery="<?php echo implode('|', $gallery_data); ?>"> |
| 415 |
<?php |
| 416 |
if (!empty($listing_details['img']) && is_file(VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . $listing_details['img'])) { |
| 417 |
?> |
| 418 |
<img class="vblistimg" alt="<?php echo htmlspecialchars($listing_details['name']); ?>" src="<?php echo VBO_SITE_URI; ?>resources/uploads/<?php echo $listing_details['img']; ?>"/> |
| 419 |
<?php |
| 420 |
} |
| 421 |
?> |
| 422 |
</a> |
| 423 |
</div> |
| 424 |
<div class="vbmodalrdetails"> |
| 425 |
<a href="<?php echo $listing_page_uri; ?>" target="_blank"><?php VikBookingIcons::e('plus'); ?></a> |
| 426 |
</div> |
| 427 |
</div> |
| 428 |
<div class="vbo-info-room"> |
| 429 |
<div class="vbdescrlistdiv"> |
| 430 |
<h4 class="vbrowcname"><a class="vbo-search-results-listing-link" href="<?php echo $listing_page_uri; ?>" target="_blank"><?php echo $listing_details['name']; ?></a></h4> |
| 431 |
<div class="vbrowcdescr"><?php echo $visible_descr; ?></div> |
| 432 |
<?php |
| 433 |
if ($hidden_descr) { |
| 434 |
// display a button to read the full description |
| 435 |
?> |
| 436 |
<div class="vbo-result-readmore-wrap"> |
| 437 |
<a class="vbo-result-readmore-trig" href="JavaScript: void(0);"><?php echo JText::translate('VBO_READ_MORE'); ?></a> |
| 438 |
<div class="vbo-result-readmore-hidden" style="display: none;"><?php echo $listing_details['smalldesc']; ?></div> |
| 439 |
</div> |
| 440 |
<?php |
| 441 |
} |
| 442 |
?> |
| 443 |
</div> |
| 444 |
<?php |
| 445 |
if (!empty($carats)) { |
| 446 |
?> |
| 447 |
<div class="roomlist_carats"> |
| 448 |
<?php echo $carats; ?> |
| 449 |
</div> |
| 450 |
<?php |
| 451 |
} |
| 452 |
?> |
| 453 |
<div class="vbo-unavailable-block"> |
| 454 |
<div class="vbo-unavailable-icon"><?php VikBookingIcons::e('ban'); ?></div> |
| 455 |
<div class="vbo-unavailable-description"><?php echo JText::translate('VBLEGBUSY'); ?></div> |
| 456 |
</div> |
| 457 |
</div> |
| 458 |
</div> |
| 459 |
<div class="vbcontdivtot"> |
| 460 |
<div class="vbdivtot"> |
| 461 |
<div class="vbdivtotinline"> |
| 462 |
<div class="vbsrowprice"> |
| 463 |
<div class="vbrowroomcapacity"> |
| 464 |
<?php |
| 465 |
for ($i = 1; $i <= $listing_details['toadult']; $i++) { |
| 466 |
if ($i <= ($this->arrpeople[1]['adults'] ?? 2)) { |
| 467 |
VikBookingIcons::e('male', 'vbo-pref-color-text'); |
| 468 |
} else { |
| 469 |
VikBookingIcons::e('male', 'vbo-empty-personicn'); |
| 470 |
} |
| 471 |
} |
| 472 |
?> |
| 473 |
</div> |
| 474 |
</div> |
| 475 |
<div class="vbselectordiv"> |
| 476 |
<a class="btn vbselectr-result vbo-result-unavailable vbo-pref-color-btn" href="<?php echo $listing_page_uri; ?>" target="_blank"><?php echo JText::translate('VBSEARCHRESDETAILS'); ?></a> |
| 477 |
</div> |
| 478 |
</div> |
| 479 |
</div> |
| 480 |
</div> |
| 481 |
</div> |
| 482 |
<?php |
| 483 |
} |
| 484 |
?> |
| 485 |
</div> |
| 486 |
<?php |
| 487 |
} |
| 488 |
?> |
| 489 |
</div> |
| 490 |
</div> |
| 491 |
|
| 492 |
<script type="text/javascript"> |
| 493 |
jQuery(function() { |
| 494 |
|
| 495 |
/** |
| 496 |
* Configure thumbnails gallery. |
| 497 |
*/ |
| 498 |
jQuery('.vbo-dots-slider-selector').each(function() { |
| 499 |
var sliderLink = jQuery(this).find('a').first(); |
| 500 |
if (!sliderLink.length) { |
| 501 |
return; |
| 502 |
} |
| 503 |
var gallery = sliderLink.data('gallery'); |
| 504 |
if (!gallery || !gallery.length) { |
| 505 |
return; |
| 506 |
} |
| 507 |
var thumbs_base_uri = '<?php echo VBO_SITE_URI . 'resources/uploads/thumb_'; ?>'; |
| 508 |
var gallery_data = gallery.split('|'); |
| 509 |
var images = []; |
| 510 |
for (var i = 0; i < gallery_data.length; i++) { |
| 511 |
if (!gallery_data[i].length) { |
| 512 |
continue; |
| 513 |
} |
| 514 |
images.push(thumbs_base_uri + gallery_data[i]); |
| 515 |
} |
| 516 |
if (!images.length) { |
| 517 |
return; |
| 518 |
} |
| 519 |
// move original main photo and make it hidden so that the dialog will keep showing it |
| 520 |
var room_main_photo = jQuery(this).find('img.vblistimg'); |
| 521 |
if (room_main_photo.length) { |
| 522 |
room_main_photo.hide().appendTo(jQuery(this).parent()); |
| 523 |
} |
| 524 |
// render slider |
| 525 |
var slideWrap = sliderLink.clone(); |
| 526 |
jQuery(this).html('').vikDotsSlider({ |
| 527 |
images: images, |
| 528 |
navButPrevContent: '<?php VikBookingIcons::e('chevron-left'); ?>', |
| 529 |
navButNextContent: '<?php VikBookingIcons::e('chevron-right'); ?>', |
| 530 |
onDisplaySlide: function() { |
| 531 |
var content = jQuery(this).children().clone(true, true); |
| 532 |
<?php |
| 533 |
if (VBOPlatformDetection::isWordPress()) { |
| 534 |
/** |
| 535 |
* @wponly In order to avoid delays with Fancybox, we do not re-construct the A tag. |
| 536 |
* We just append the slide image. |
| 537 |
*/ |
| 538 |
?> |
| 539 |
jQuery(this).html('').append(content); |
| 540 |
<?php |
| 541 |
} else { |
| 542 |
?> |
| 543 |
var link = jQuery('<a target="_blank"></a>').attr('href', slideWrap.attr('href')).attr('class', slideWrap.attr('class')).append(content); |
| 544 |
jQuery(this).html('').append(link); |
| 545 |
<?php |
| 546 |
} |
| 547 |
?> |
| 548 |
} |
| 549 |
}); |
| 550 |
}); |
| 551 |
|
| 552 |
/** |
| 553 |
* Configure layout style actions. |
| 554 |
*/ |
| 555 |
document.querySelectorAll('.vbo-results-style-option').forEach((styleEl) => { |
| 556 |
styleEl.addEventListener('click', (e) => { |
| 557 |
let styleOption = e.target; |
| 558 |
if (!styleOption.matches('.vbo-results-style-option')) { |
| 559 |
styleOption = styleOption.closest('.vbo-results-style-option'); |
| 560 |
} |
| 561 |
let styleType = styleEl.getAttribute('data-type'); |
| 562 |
let styleToggle = styleEl.getAttribute('data-toggle'); |
| 563 |
document.querySelectorAll('.vbo-searchresults-classic-wrap').forEach((wrap) => { |
| 564 |
wrap.setAttribute('class', 'vbo-searchresults-classic-wrap'); |
| 565 |
if (styleToggle) { |
| 566 |
wrap.classList.add(styleToggle); |
| 567 |
} |
| 568 |
}); |
| 569 |
document.querySelectorAll('.vbo-results-style-option-active').forEach((prevActive) => { |
| 570 |
prevActive.classList.remove('vbo-results-style-option-active'); |
| 571 |
}); |
| 572 |
document.querySelectorAll('.vbo-results-style-option[data-type="' + styleType + '"]').forEach((nowActive) => { |
| 573 |
nowActive.classList.add('vbo-results-style-option-active'); |
| 574 |
}); |
| 575 |
}); |
| 576 |
}); |
| 577 |
|
| 578 |
/** |
| 579 |
* Configure description "read more" action links. |
| 580 |
*/ |
| 581 |
document.querySelectorAll('.vbo-result-readmore-trig').forEach((readMore) => { |
| 582 |
readMore.addEventListener('click', (e) => { |
| 583 |
try { |
| 584 |
// get full (HTML & hidden) description |
| 585 |
let fullDescr = readMore.closest('.vbo-result-readmore-wrap').querySelector('.vbo-result-readmore-hidden').innerHTML; |
| 586 |
// replace visible description |
| 587 |
readMore.closest('.vbdescrlistdiv').querySelector('.vbrowcdescr').innerHTML = fullDescr; |
| 588 |
} catch(e) { |
| 589 |
console.error(e); |
| 590 |
} |
| 591 |
|
| 592 |
// delete link from DOM |
| 593 |
readMore.remove(); |
| 594 |
}); |
| 595 |
}); |
| 596 |
|
| 597 |
/** |
| 598 |
* Configure results hovering effects on map. |
| 599 |
*/ |
| 600 |
document.querySelectorAll('.vbo-searchresults-classic-wrap .room_item:not(.vbo-result-listing-unavailable)').forEach((resultEl) => { |
| 601 |
let resultData = resultEl.getAttribute('id').split('_'); |
| 602 |
let resultId = resultData[1] || 0; |
| 603 |
resultEl.addEventListener('mouseenter', () => { |
| 604 |
const mapTarget = document.querySelector('.vbo-map-listing-cost[data-room-id="' + resultId + '"]'); |
| 605 |
if (mapTarget) { |
| 606 |
mapTarget.classList.add('vbo-map-listing-cost-highlight'); |
| 607 |
} |
| 608 |
if (typeof vbo_geomarker_units !== 'undefined' && typeof vbo_geomarker_units[resultId + '_1'] !== 'undefined') { |
| 609 |
// take marker on top of the others overlapping the same zoomed coordinates |
| 610 |
vbo_geomarker_units[resultId + '_1'].zIndex = 9999; |
| 611 |
} |
| 612 |
}); |
| 613 |
resultEl.addEventListener('mouseleave', () => { |
| 614 |
const mapTarget = document.querySelector('.vbo-map-listing-cost[data-room-id="' + resultId + '"]'); |
| 615 |
if (mapTarget) { |
| 616 |
mapTarget.classList.remove('vbo-map-listing-cost-highlight'); |
| 617 |
} |
| 618 |
if (typeof vbo_geomarker_units !== 'undefined' && typeof vbo_geomarker_units[resultId + '_1'] !== 'undefined') { |
| 619 |
// restore marker z-index property |
| 620 |
vbo_geomarker_units[resultId + '_1'].zIndex = 1; |
| 621 |
} |
| 622 |
}); |
| 623 |
}); |
| 624 |
|
| 625 |
/** |
| 626 |
* Register event for activating the search filters. |
| 627 |
*/ |
| 628 |
const filtersBtn = document.querySelector('.vbo-results-filters-toggle'); |
| 629 |
if (filtersBtn) { |
| 630 |
filtersBtn.addEventListener('click', () => { |
| 631 |
// modal cancel filters button |
| 632 |
let filtersCancelBtn = document.createElement('button'); |
| 633 |
filtersCancelBtn.setAttribute('type', 'button'); |
| 634 |
filtersCancelBtn.classList.add('btn', 'vbo-pref-color-btn-secondary', 'vbo-modal-dismiss-btn'); |
| 635 |
filtersCancelBtn.innerText = <?php echo json_encode(JText::translate('VBDIALOGBTNCANCEL')); ?>; |
| 636 |
filtersCancelBtn.addEventListener('click', () => { |
| 637 |
let filtersForm = document.querySelector('form#vbo-results-filters-form'); |
| 638 |
if (filtersForm) { |
| 639 |
// clean up checkbox and radio elements |
| 640 |
filtersForm |
| 641 |
.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked') |
| 642 |
.forEach((el) => { |
| 643 |
el.checked = false; |
| 644 |
}); |
| 645 |
// clean up input text, number and textarea elements |
| 646 |
filtersForm |
| 647 |
.querySelectorAll('input[type="text"], input[type="number"], textarea') |
| 648 |
.forEach((el) => { |
| 649 |
el.value = ''; |
| 650 |
}); |
| 651 |
// clean up select elements |
| 652 |
filtersForm |
| 653 |
.querySelectorAll('select') |
| 654 |
.forEach((el) => { |
| 655 |
el.value = ''; |
| 656 |
}); |
| 657 |
// clean up range elements |
| 658 |
filtersForm |
| 659 |
.querySelectorAll('input[type="range"]') |
| 660 |
.forEach((el) => { |
| 661 |
el.disabled = true; |
| 662 |
}); |
| 663 |
// submit the form with no filters set |
| 664 |
filtersForm.submit(); |
| 665 |
} |
| 666 |
VBOCore.emitEvent('vbo-dismiss-search-results-filters-modal'); |
| 667 |
}); |
| 668 |
|
| 669 |
// modal apply filters button |
| 670 |
let filtersApplyBtn = document.createElement('button'); |
| 671 |
filtersApplyBtn.setAttribute('type', 'button'); |
| 672 |
filtersApplyBtn.classList.add('btn', 'vbo-pref-color-btn', 'vbo-modal-apply-btn'); |
| 673 |
filtersApplyBtn.innerText = <?php echo json_encode(JText::translate('VBSUBMITCOUPON')); ?>; |
| 674 |
filtersApplyBtn.addEventListener('click', () => { |
| 675 |
let filtersForm = document.querySelector('form#vbo-results-filters-form'); |
| 676 |
if (filtersForm) { |
| 677 |
// submit the form with the current filters set |
| 678 |
filtersForm.submit(); |
| 679 |
} |
| 680 |
VBOCore.emitEvent('vbo-dismiss-search-results-filters-modal'); |
| 681 |
}); |
| 682 |
|
| 683 |
// display modal |
| 684 |
let filtersModal = VBOCore.displayModal({ |
| 685 |
suffix: 'search-results-filters-modal', |
| 686 |
title: <?php echo json_encode(JText::translate('VBO_FILTERS')); ?>, |
| 687 |
extra_class: 'vbo-modal-tall vbo-modal-sticky-head vbo-modal-sticky-footer', |
| 688 |
body_prepend: true, |
| 689 |
lock_scroll: true, |
| 690 |
dismiss_event: 'vbo-dismiss-search-results-filters-modal', |
| 691 |
onDismiss: () => { |
| 692 |
document |
| 693 |
.querySelector('.vbo-results-filters-form-helper') |
| 694 |
.append( |
| 695 |
document.querySelector('.vbo-results-filters-form-wrapper') |
| 696 |
); |
| 697 |
}, |
| 698 |
footer_left: filtersCancelBtn, |
| 699 |
footer_right: filtersApplyBtn, |
| 700 |
}); |
| 701 |
|
| 702 |
// populate modal body |
| 703 |
filtersModal[0].append(document.querySelector('.vbo-results-filters-form-wrapper')); |
| 704 |
}); |
| 705 |
} |
| 706 |
}); |
| 707 |
</script> |
| 708 |
|