| 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 |
$geo = VikBooking::getGeocodingInstance(); |
| 14 |
|
| 15 |
$currencysymb = VikBooking::getCurrencySymb(); |
| 16 |
$vat_included = VikBooking::ivaInclusa(); |
| 17 |
$tax_summary = (!$vat_included && VikBooking::showTaxOnSummaryOnly()); |
| 18 |
|
| 19 |
$geo_info_complete = true; |
| 20 |
$global_geo_params = null; |
| 21 |
$rooms_geo_params = array(); |
| 22 |
$rooms_features = array(); |
| 23 |
$rooms_galleries = array(); |
| 24 |
$rooms_units_booked = array(); |
| 25 |
$rooms_units_pos = new stdClass; |
| 26 |
$markers_parties = new stdClass; |
| 27 |
|
| 28 |
// lang vars for JS |
| 29 |
JText::script('VBSEARCHROOMNUM'); |
| 30 |
JText::script('VBSEARCHRESADULT'); |
| 31 |
JText::script('VBSEARCHRESADULTS'); |
| 32 |
JText::script('VBSEARCHRESCHILD'); |
| 33 |
JText::script('VBSEARCHRESCHILDREN'); |
| 34 |
JText::script('VBSELECTR'); |
| 35 |
JText::script('VBO_CANCEL_SELECTION'); |
| 36 |
|
| 37 |
// we build a fake booking array to count the units booked for the various rooms |
| 38 |
$booking_data = array( |
| 39 |
'id' => 0, |
| 40 |
'checkin' => $this->checkin, |
| 41 |
'checkout' => $this->checkout, |
| 42 |
); |
| 43 |
|
| 44 |
foreach ($this->res as $party_num => $party_rooms) { |
| 45 |
foreach ($party_rooms as $party_room) { |
| 46 |
foreach ($party_room as $room_rplan) { |
| 47 |
if (empty($room_rplan['idroom']) || empty($room_rplan['params'])) { |
| 48 |
// unable to proceed |
| 49 |
$geo_info_complete = false; |
| 50 |
break 3; |
| 51 |
} |
| 52 |
if (isset($rooms_geo_params[$room_rplan['idroom']])) { |
| 53 |
// room already parsed |
| 54 |
continue; |
| 55 |
} |
| 56 |
$rparams = json_decode($room_rplan['params']); |
| 57 |
$geo_params = $geo->getRoomGeoParams($rparams); |
| 58 |
if (is_object($geo_params) && isset($geo_params->enabled) && $geo_params->enabled) { |
| 59 |
if (!isset($global_geo_params)) { |
| 60 |
// we use the global geo params of the first room returned |
| 61 |
$global_geo_params = $geo_params; |
| 62 |
} |
| 63 |
// push room geo params |
| 64 |
$rooms_geo_params[$room_rplan['idroom']] = $geo_params; |
| 65 |
// check if distinctive features are available |
| 66 |
$rooms_features[$room_rplan['idroom']] = array(); |
| 67 |
$room_features = VikBooking::getRoomParam('features', $room_rplan['params']); |
| 68 |
$room_features = !is_array($room_features) ? array() : $room_features; |
| 69 |
foreach ($room_features as $rindex => $rfeatures) { |
| 70 |
if (!is_array($rfeatures) || !count($rfeatures)) { |
| 71 |
continue; |
| 72 |
} |
| 73 |
foreach ($rfeatures as $featname => $featval) { |
| 74 |
if (empty($featval)) { |
| 75 |
continue; |
| 76 |
} |
| 77 |
// use the first distinctive feature |
| 78 |
$tn_featname = JText::translate($featname); |
| 79 |
if ($tn_featname == $featname) { |
| 80 |
// no translation was applied |
| 81 |
if (VBOPlatformDetection::isWordPress()) { |
| 82 |
// try to apply a translation through Gettext even if we have to pass a variable |
| 83 |
$tn_featname = __($featname); |
| 84 |
} else { |
| 85 |
// convert the string to a hypothetical INI constant |
| 86 |
$ini_constant = str_replace(' ', '_', strtoupper($featname)); |
| 87 |
$tn_featname = JText::translate($ini_constant); |
| 88 |
$tn_featname = $tn_featname == $ini_constant ? $featname : $tn_featname; |
| 89 |
} |
| 90 |
} |
| 91 |
$rooms_features[$room_rplan['idroom']][$rindex] = $tn_featname . ' ' . $featval; |
| 92 |
break; |
| 93 |
} |
| 94 |
} |
| 95 |
// build rooms gallery |
| 96 |
$rooms_galleries[$room_rplan['idroom']] = array(); |
| 97 |
if (!empty($room_rplan['moreimgs'])) { |
| 98 |
$moreimages = explode(';;', $room_rplan['moreimgs']); |
| 99 |
foreach ($moreimages as $mimg) { |
| 100 |
if (empty($mimg)) { |
| 101 |
continue; |
| 102 |
} |
| 103 |
// push thumb URL |
| 104 |
array_push($rooms_galleries[$room_rplan['idroom']], VBO_SITE_URI . 'resources/uploads/thumb_' . $mimg); |
| 105 |
} |
| 106 |
} elseif (!empty($room_rplan['img'])) { |
| 107 |
// push main image URL |
| 108 |
array_push($rooms_galleries[$room_rplan['idroom']], VBO_SITE_URI . 'resources/uploads/' . $room_rplan['img']); |
| 109 |
} |
| 110 |
// count room units booked |
| 111 |
$rooms_units_booked[$room_rplan['idroom']] = VikBooking::getRoomUnitNumsUnavailable($booking_data, $room_rplan['idroom']); |
| 112 |
} else { |
| 113 |
// unable to proceed |
| 114 |
$geo_info_complete = false; |
| 115 |
break 3; |
| 116 |
} |
| 117 |
// we parse just the first rate plan |
| 118 |
break; |
| 119 |
} |
| 120 |
} |
| 121 |
} |
| 122 |
|
| 123 |
// compose markers positions |
| 124 |
foreach ($rooms_geo_params as $idroom => $geo_params) { |
| 125 |
if (isset($geo_params->units_pos) && is_object($geo_params->units_pos) && count(get_object_vars($geo_params->units_pos))) { |
| 126 |
$rooms_units_pos->{$idroom} = $geo_params->units_pos; |
| 127 |
} |
| 128 |
} |
| 129 |
|
| 130 |
if ($geo->isSupported() && $geo_info_complete === true && count($rooms_geo_params) && count(get_object_vars($rooms_units_pos))) { |
| 131 |
// load assets |
| 132 |
$geo->loadAssets(); |
| 133 |
|
| 134 |
// check if ground overlay is implemented by the first room that returns the global geo params |
| 135 |
$current_goverlay = null; |
| 136 |
if ((int)$global_geo_params->goverlay > 0 && !empty($global_geo_params->overlay_img) && !empty($global_geo_params->overlay_south)) { |
| 137 |
// ground overlay is available |
| 138 |
$current_goverlay = new stdClass; |
| 139 |
$current_goverlay->url = $global_geo_params->overlay_img; |
| 140 |
$current_goverlay->south = (float)$global_geo_params->overlay_south; |
| 141 |
$current_goverlay->west = (float)$global_geo_params->overlay_west; |
| 142 |
$current_goverlay->north = (float)$global_geo_params->overlay_north; |
| 143 |
$current_goverlay->east = (float)$global_geo_params->overlay_east; |
| 144 |
} |
| 145 |
|
| 146 |
// compose markers parties |
| 147 |
foreach ($this->res as $party_num => $party_rooms) { |
| 148 |
$markers_parties->{$party_num} = array(); |
| 149 |
foreach ($party_rooms as $party_room) { |
| 150 |
foreach ($party_room as $room_rplan) { |
| 151 |
if (empty($room_rplan['idroom']) || !isset($rooms_geo_params[$room_rplan['idroom']])) { |
| 152 |
continue; |
| 153 |
} |
| 154 |
if (!in_array($room_rplan['idroom'], $markers_parties->{$party_num})) { |
| 155 |
$raw_roomcost = $tax_summary ? $room_rplan['cost'] : VikBooking::sayCostPlusIva($room_rplan['cost'], $room_rplan['idprice']); |
| 156 |
// build room info object |
| 157 |
$room_info = new stdClass; |
| 158 |
$room_info->id = $room_rplan['idroom']; |
| 159 |
$room_info->name = $room_rplan['name']; |
| 160 |
$room_info->cost = VikBooking::numberFormat($raw_roomcost); |
| 161 |
$room_info->units = isset($room_rplan['unitsavail']) ? (int)$room_rplan['unitsavail'] : (int)$room_rplan['units']; |
| 162 |
$room_info->tot_markers = 1; |
| 163 |
if ($rooms_geo_params[$room_rplan['idroom']]->markers_multi > 0 && $room_rplan['units'] > 1) { |
| 164 |
$room_info->tot_markers = (int)$room_rplan['units']; |
| 165 |
} |
| 166 |
// check if a promo was applied |
| 167 |
if (isset($room_rplan['promotion']) && isset($room_rplan['promotion']['discount'])) { |
| 168 |
if ($room_rplan['promotion']['discount']['pcent']) { |
| 169 |
$prev_amount = $raw_roomcost * 100 / (100 - $room_rplan['promotion']['discount']['amount']); |
| 170 |
} else { |
| 171 |
$prev_amount = $raw_roomcost + $room_rplan['promotion']['discount']['amount']; |
| 172 |
} |
| 173 |
if ($prev_amount > 0) { |
| 174 |
$room_info->prev_cost = VikBooking::numberFormat($prev_amount); |
| 175 |
} |
| 176 |
} |
| 177 |
// push room info |
| 178 |
array_push($markers_parties->{$party_num}, $room_info); |
| 179 |
} |
| 180 |
// we parse just the first rate plan |
| 181 |
break; |
| 182 |
} |
| 183 |
} |
| 184 |
} |
| 185 |
?> |
| 186 |
<div class="vbo-searchresults-geo-wrapper"> |
| 187 |
<div class="vbo-geo-wrapper"> |
| 188 |
<?php |
| 189 |
if ($this->roomsnum > 1) { |
| 190 |
?> |
| 191 |
<div class="vbo-geomap-uicontrol"> |
| 192 |
<div class="vbo-geomap-uicontrol-inner"> |
| 193 |
<span class="vbo-geomap-uicontrol-partynum"><?php echo JText::translate('VBSEARCHROOMNUM'); ?> 1</span> |
| 194 |
<span class="vbo-geomap-uicontrol-partyguests"> |
| 195 |
<?php VikBookingIcons::e('users', 'vbo-pref-color-text'); ?> |
| 196 |
<?php echo $this->arrpeople[1]['adults']; ?> |
| 197 |
<?php echo ($this->arrpeople[1]['adults'] == 1 ? JText::translate('VBSEARCHRESADULT') : JText::translate('VBSEARCHRESADULTS')); ?> |
| 198 |
<?php echo ($this->showchildren && $this->arrpeople[1]['children'] > 0 ? ", ".$this->arrpeople[1]['children']." ".($this->arrpeople[1]['children'] == 1 ? JText::translate('VBSEARCHRESCHILD') : JText::translate('VBSEARCHRESCHILDREN')) : ""); ?> |
| 199 |
</span> |
| 200 |
</div> |
| 201 |
</div> |
| 202 |
<?php |
| 203 |
} |
| 204 |
?> |
| 205 |
<div class="vbo-results-geo-map-container"> |
| 206 |
<?php |
| 207 |
if ($this->roomsnum > 1) { |
| 208 |
?> |
| 209 |
<div class="vbo-geomap-minicart" style="display: none;"> |
| 210 |
<div class="vbo-geomap-minicart-inner"> |
| 211 |
<div class="vbo-geomap-minicart-head"><?php VikBookingIcons::e('shopping-cart'); ?></div> |
| 212 |
<div class="vbo-geomap-minicart-body"></div> |
| 213 |
</div> |
| 214 |
</div> |
| 215 |
<?php |
| 216 |
} |
| 217 |
?> |
| 218 |
<div id="vbo-results-geo-map" style="width: 100%; height: <?php echo $geo->getRoomGeoParams($global_geo_params, 'height', 300); ?>px;"></div> |
| 219 |
</div> |
| 220 |
</div> |
| 221 |
</div> |
| 222 |
|
| 223 |
<script type="text/javascript"> |
| 224 |
/** |
| 225 |
* Define global scope vars |
| 226 |
*/ |
| 227 |
var vbo_geomap = null, |
| 228 |
vbo_geo_currency = '<?php echo $currencysymb; ?>'; |
| 229 |
vbo_geo_showchildren = <?php echo (int)$this->showchildren; ?>, |
| 230 |
vbo_geo_rooms_galleries = <?php echo json_encode($rooms_galleries); ?>, |
| 231 |
vbo_geo_guestparties = <?php echo json_encode($this->arrpeople); ?>, |
| 232 |
vbo_geomarker_parties = <?php echo json_encode($markers_parties); ?>, |
| 233 |
vbo_rooms_units_booked = <?php echo json_encode($rooms_units_booked); ?>, |
| 234 |
vbo_rooms_units_selected = {}, |
| 235 |
vbo_geomarker_units = {}, |
| 236 |
vbo_geomarker_units_pos = <?php echo json_encode($rooms_units_pos); ?>, |
| 237 |
vbo_info_markers = {}, |
| 238 |
vbo_info_markers_helper = <?php echo json_encode($rooms_features); ?>, |
| 239 |
vbo_ground_overlay = null, |
| 240 |
vbo_dbground_overlay = <?php echo is_object($current_goverlay) ? json_encode($current_goverlay) : 'null'; ?>, |
| 241 |
vbo_geomap_booking_step = 1 |
| 242 |
vbo_geomap_total_steps = <?php echo $this->roomsnum; ?>; |
| 243 |
|
| 244 |
// turn off the use of the modal/dialog window in case of multi rooms booking |
| 245 |
var vbo_multirooms_dialog = false; |
| 246 |
|
| 247 |
/** |
| 248 |
* Returns the room information. |
| 249 |
*/ |
| 250 |
function vboGetGeoRoomPartyInformation(idroom) { |
| 251 |
if (!vbo_geomarker_parties.hasOwnProperty(vbo_geomap_booking_step)) { |
| 252 |
return null; |
| 253 |
} |
| 254 |
for (var room in vbo_geomarker_parties[vbo_geomap_booking_step]) { |
| 255 |
if (!vbo_geomarker_parties[vbo_geomap_booking_step].hasOwnProperty(room)) { |
| 256 |
continue; |
| 257 |
} |
| 258 |
if (vbo_geomarker_parties[vbo_geomap_booking_step][room]['id'] == idroom) { |
| 259 |
return vbo_geomarker_parties[vbo_geomap_booking_step][room]; |
| 260 |
} |
| 261 |
} |
| 262 |
return null; |
| 263 |
} |
| 264 |
|
| 265 |
/** |
| 266 |
* Generates the HTML content for the units marker infowindow. |
| 267 |
*/ |
| 268 |
function vboGeoInfoMarkerContent(idroom, index, marker_title, rcost, rprevcost) { |
| 269 |
var rdomselector = '#vbcontainer' + vbo_geomap_booking_step + '_' + idroom; |
| 270 |
var infowin_cont = ''; |
| 271 |
infowin_cont += '<div class="vbo-geomarker-infowin-wrap">'; |
| 272 |
// check if gallery is available |
| 273 |
if (vbo_geo_rooms_galleries.hasOwnProperty(idroom) && vbo_geo_rooms_galleries[idroom].length) { |
| 274 |
infowin_cont += ' <div class="vbo-geomarker-infowin-room-gallery" data-idroom="' + idroom + '"></div>'; |
| 275 |
} |
| 276 |
infowin_cont += ' <div class="vbo-geomarker-room-title">'; |
| 277 |
if (jQuery(rdomselector).find('.vbmodalframe').length) { |
| 278 |
infowin_cont += ' <span class="vbo-geomarker-rstay-info" onclick="jQuery(\'' + rdomselector + '\').find(\'.vbmodalframe\').first().trigger(\'click\');"><?php VikBookingIcons::e('info-circle'); ?></span>'; |
| 279 |
} |
| 280 |
infowin_cont += ' <span class="vbo-geomarker-room-title-cont">' + marker_title + '</span>'; |
| 281 |
infowin_cont += ' </div>'; |
| 282 |
infowin_cont += ' <div class="vbo-geomarker-priceinfo">'; |
| 283 |
if (rprevcost != null) { |
| 284 |
infowin_cont += ' <span class="vbo-geomarker-priceinfo-cost-beforedisc"><span class="vbo_currency">' + vbo_geo_currency + '</span> <span class="vbo_price">' + rprevcost + '</span></span>'; |
| 285 |
} |
| 286 |
infowin_cont += ' <span class="vbo-geomarker-priceinfo-cost"><span class="vbo_currency">' + vbo_geo_currency + '</span> <span class="vbo_price">' + rcost + '</span></span>'; |
| 287 |
infowin_cont += ' </div>'; |
| 288 |
infowin_cont += ' <div class="vbo-geomarker-bookroom">'; |
| 289 |
infowin_cont += ' <button type="button" class="btn vbo-pref-color-btn" onclick="vboInteractiveGeoMapSelectRoom(' + idroom + ', ' + index + ');">' + Joomla.JText._('VBSELECTR') + '</button>'; |
| 290 |
infowin_cont += ' </div>'; |
| 291 |
infowin_cont += '</div>'; |
| 292 |
|
| 293 |
return infowin_cont; |
| 294 |
} |
| 295 |
|
| 296 |
/** |
| 297 |
* Selects one room and index for booking the current party. |
| 298 |
*/ |
| 299 |
function vboInteractiveGeoMapSelectRoom(idroom, index) { |
| 300 |
var current_step = vbo_geomap_booking_step; |
| 301 |
var room_info = vboGetGeoRoomPartyInformation(idroom); |
| 302 |
var tot_markers = room_info !== null ? room_info['tot_markers'] : 1; |
| 303 |
// register room index hidden field |
| 304 |
if (jQuery('#vbo-geo-roomindex-' + current_step).length) { |
| 305 |
jQuery('#vbo-geo-roomindex-' + current_step).remove(); |
| 306 |
} |
| 307 |
// if room does not support sub-units or has markers for sub-units, index value is 0 so that we can skip it later on in the booking process |
| 308 |
var room_index_val = tot_markers === 1 ? 0 : index; |
| 309 |
jQuery('#vbselectroomform').append('<input type="hidden" id="vbo-geo-roomindex-' + current_step + '" name="roomindex[]" value="' + room_index_val + '" />'); |
| 310 |
// trigger the main function to select the room |
| 311 |
var res = vbSelectRoom(current_step, idroom); |
| 312 |
if (res === false) { |
| 313 |
jQuery('#vbo-geo-roomindex-' + current_step).remove(); |
| 314 |
return; |
| 315 |
} |
| 316 |
// check if the next step should be displayed |
| 317 |
if (vbo_geomap_total_steps > 1 && vbo_geomap_total_steps > current_step) { |
| 318 |
// register the room index selected |
| 319 |
vbo_rooms_units_selected[current_step] = { |
| 320 |
idroom: idroom, |
| 321 |
index: index |
| 322 |
}; |
| 323 |
// populate mini-cart |
| 324 |
if (jQuery('.vbo-geomap-minicart').length) { |
| 325 |
var rcost = room_info !== null ? room_info['cost'] : ''; |
| 326 |
var rname = room_info !== null ? room_info['name'] : ''; |
| 327 |
var room_title = rname + ' #' + (index + ''); |
| 328 |
if (tot_markers === 1) { |
| 329 |
room_title = rname; |
| 330 |
} else if (vbo_info_markers_helper.hasOwnProperty(idroom) && vbo_info_markers_helper[idroom].hasOwnProperty(index)) { |
| 331 |
room_title = rname + ' - ' + vbo_info_markers_helper[idroom][index]; |
| 332 |
} |
| 333 |
// get party info |
| 334 |
var vbo_uicontrol_guests = ''; |
| 335 |
vbo_uicontrol_guests += '<?php VikBookingIcons::e('users', 'vbo-pref-color-text'); ?> '; |
| 336 |
vbo_uicontrol_guests += vbo_geo_guestparties[current_step]['adults'] + ' '; |
| 337 |
vbo_uicontrol_guests += (vbo_geo_guestparties[current_step]['adults'] == 1 ? Joomla.JText._('VBSEARCHRESADULT') : Joomla.JText._('VBSEARCHRESADULTS')) + ' '; |
| 338 |
vbo_uicontrol_guests += (vbo_geo_showchildren > 0 && vbo_geo_guestparties[current_step]['children'] > 1 ? (', ' + vbo_geo_guestparties[current_step]['children'] + ' ' + (vbo_geo_guestparties[current_step]['children'] == 1 ? Joomla.JText._('VBSEARCHRESCHILD') : Joomla.JText._('VBSEARCHRESCHILDREN'))) : ''); |
| 339 |
var minicart_row = ''; |
| 340 |
minicart_row += '<div class="vbo-geomap-minicart-row" data-minicartrow="' + current_step + '">'; |
| 341 |
minicart_row += ' <div class="vbo-geomap-minicart-party">'; |
| 342 |
minicart_row += ' <span class="vbo-geomap-minicart-party-num">' + Joomla.JText._('VBSEARCHROOMNUM') + ' ' + current_step + '</span>'; |
| 343 |
minicart_row += ' <span class="vbo-geomap-minicart-party-guests">' + vbo_uicontrol_guests + '</span>'; |
| 344 |
minicart_row += ' </div>'; |
| 345 |
minicart_row += ' <div class="vbo-geomap-minicart-room">'; |
| 346 |
minicart_row += ' <span class="vbo-geomap-minicart-room-name">' + room_title + '</span>'; |
| 347 |
minicart_row += ' <span class="vbo-geomap-minicart-room-price"><span class="vbo_currency">' + vbo_geo_currency + '</span> <span class="vbo_price">' + rcost + '</span></span>'; |
| 348 |
minicart_row += ' <span class="vbo-geomap-minicart-room-trash" onclick="vboInteractiveGeoMapDeselectRoom(' + current_step + ', ' + idroom + ');"><?php VikBookingIcons::e('trash'); ?></span>'; |
| 349 |
minicart_row += ' </div>'; |
| 350 |
minicart_row += '</div>'; |
| 351 |
jQuery('.vbo-geomap-minicart-body').append(minicart_row).removeClass('vbo-geomap-minicart-body-hid').addClass('vbo-geomap-minicart-body-enter'); |
| 352 |
jQuery('.vbo-geomap-minicart').show(); |
| 353 |
// register closing event for the minicart body |
| 354 |
setTimeout(function() { |
| 355 |
jQuery('.vbo-geomap-minicart-body').removeClass('vbo-geomap-minicart-body-enter').addClass('vbo-geomap-minicart-body-hid'); |
| 356 |
}, 1500); |
| 357 |
} |
| 358 |
// increase step for next selection |
| 359 |
vbo_geomap_booking_step++; |
| 360 |
// reload map for the next booking party |
| 361 |
vboInitInteractiveGeoMap(); |
| 362 |
return; |
| 363 |
} |
| 364 |
if (res === true) { |
| 365 |
// form is being submitted |
| 366 |
return; |
| 367 |
} |
| 368 |
if (vbo_geomap_booking_step == vbo_geomap_total_steps) { |
| 369 |
// we can submit the form |
| 370 |
document.getElementById('vbselectroomform').submit(); |
| 371 |
return true; |
| 372 |
} |
| 373 |
} |
| 374 |
|
| 375 |
/** |
| 376 |
* Deselects the room from the given party step, as well as for any step after. |
| 377 |
*/ |
| 378 |
function vboInteractiveGeoMapDeselectRoom(step, idroom) { |
| 379 |
if (confirm(Joomla.JText._('VBO_CANCEL_SELECTION'))) { |
| 380 |
if (step > vbo_geomap_total_steps) { |
| 381 |
console.error('invalid step given', step, vbo_geomap_total_steps); |
| 382 |
return false; |
| 383 |
} |
| 384 |
// loop through all room parties starting from the last one until reaching the selected one |
| 385 |
for (var now_step = vbo_geomap_total_steps; now_step >= step; now_step--) { |
| 386 |
// remove cart row |
| 387 |
if (jQuery('.vbo-geomap-minicart-row[data-minicartrow="' + now_step + '"]').length) { |
| 388 |
jQuery('.vbo-geomap-minicart-row[data-minicartrow="' + now_step + '"]').remove(); |
| 389 |
} |
| 390 |
// hide cart if no more rows |
| 391 |
if (!jQuery('.vbo-geomap-minicart-row').length) { |
| 392 |
jQuery('.vbo-geomap-minicart').hide(); |
| 393 |
} |
| 394 |
// remove hidden field for room index |
| 395 |
if (jQuery('#vbo-geo-roomindex-' + now_step).length) { |
| 396 |
jQuery('#vbo-geo-roomindex-' + now_step).remove(); |
| 397 |
} |
| 398 |
// delete the room index previously selected |
| 399 |
if (vbo_rooms_units_selected.hasOwnProperty(now_step)) { |
| 400 |
delete vbo_rooms_units_selected[now_step]; |
| 401 |
} |
| 402 |
// deselect room from classic template |
| 403 |
// remove selected class |
| 404 |
if (jQuery('#vbcontainer' + now_step + '_' + idroom).length) { |
| 405 |
jQuery('#vbcontainer' + now_step + '_' + idroom).removeClass('room_selected'); |
| 406 |
} |
| 407 |
// change selector label |
| 408 |
if (jQuery('#vbselector' + now_step + '_' + idroom).length) { |
| 409 |
jQuery('#vbselector' + now_step + '_' + idroom).text(Joomla.JText._('VBSELECTR')); |
| 410 |
} |
| 411 |
// empty hidden input field |
| 412 |
if (jQuery('#roomopt' + now_step).length) { |
| 413 |
jQuery('#roomopt' + now_step).val(''); |
| 414 |
} |
| 415 |
// update global r_counter object from classic template |
| 416 |
if (typeof r_counter !== 'undefined' && r_counter.hasOwnProperty(idroom)) { |
| 417 |
// decrease units used for this room |
| 418 |
if (r_counter[idroom].hasOwnProperty('used') && r_counter[idroom]['used'] > 0) { |
| 419 |
r_counter[idroom]['used']--; |
| 420 |
} |
| 421 |
} |
| 422 |
} |
| 423 |
// update global booking step |
| 424 |
vbo_geomap_booking_step = step; |
| 425 |
// reload map for the current booking party |
| 426 |
vboInitInteractiveGeoMap(); |
| 427 |
} |
| 428 |
} |
| 429 |
|
| 430 |
/** |
| 431 |
* Given the markers of the rooms for the current booking party, calculates and sets the map bounds |
| 432 |
*/ |
| 433 |
function vboInteractiveGeoMapCenterBounds() { |
| 434 |
if (vbo_geomap === null || !vbo_geomarker_parties.hasOwnProperty(vbo_geomap_booking_step)) { |
| 435 |
console.error('map is null or booking step not found'); |
| 436 |
return false; |
| 437 |
} |
| 438 |
// set map center and zoom automatically |
| 439 |
var latlngbounds = new google.maps.LatLngBounds(); |
| 440 |
|
| 441 |
// get the position of all markers for the current room party |
| 442 |
var party_rooms = vbo_geomarker_parties[vbo_geomap_booking_step]; |
| 443 |
var tot_coords = 0; |
| 444 |
for (var room in party_rooms) { |
| 445 |
if (!party_rooms.hasOwnProperty(room)) { |
| 446 |
continue; |
| 447 |
} |
| 448 |
var idroom = party_rooms[room]['id']; |
| 449 |
if (!vbo_geomarker_units_pos.hasOwnProperty(idroom)) { |
| 450 |
continue; |
| 451 |
} |
| 452 |
for (var m in vbo_geomarker_units_pos[idroom]) { |
| 453 |
if (!vbo_geomarker_units_pos[idroom].hasOwnProperty(m)) { |
| 454 |
continue; |
| 455 |
} |
| 456 |
latlngbounds.extend({ |
| 457 |
lat: parseFloat(vbo_geomarker_units_pos[idroom][m]['lat']), |
| 458 |
lng: parseFloat(vbo_geomarker_units_pos[idroom][m]['lng']) |
| 459 |
}); |
| 460 |
tot_coords++; |
| 461 |
} |
| 462 |
} |
| 463 |
|
| 464 |
// apply calculated center and bounds |
| 465 |
if (tot_coords > 0) { |
| 466 |
vbo_geomap.setCenter(latlngbounds.getCenter()); |
| 467 |
vbo_geomap.fitBounds(latlngbounds); |
| 468 |
} |
| 469 |
} |
| 470 |
|
| 471 |
/** |
| 472 |
* Given the the current booking party, adds the markers to the map |
| 473 |
*/ |
| 474 |
function vboInteractiveGeoMapSetPartyMarkers() { |
| 475 |
if (vbo_geomap === null || !vbo_geomarker_parties.hasOwnProperty(vbo_geomap_booking_step)) { |
| 476 |
console.error('map is null or booking step not found'); |
| 477 |
return false; |
| 478 |
} |
| 479 |
|
| 480 |
// update UI control for this room party |
| 481 |
if (jQuery('.vbo-geomap-uicontrol').length) { |
| 482 |
jQuery('.vbo-geomap-uicontrol-partynum').text(Joomla.JText._('VBSEARCHROOMNUM') + ' ' + vbo_geomap_booking_step); |
| 483 |
var vbo_uicontrol_guests = ''; |
| 484 |
vbo_uicontrol_guests += '<?php VikBookingIcons::e('users', 'vbo-pref-color-text'); ?> '; |
| 485 |
vbo_uicontrol_guests += vbo_geo_guestparties[vbo_geomap_booking_step]['adults'] + ' '; |
| 486 |
vbo_uicontrol_guests += (vbo_geo_guestparties[vbo_geomap_booking_step]['adults'] == 1 ? Joomla.JText._('VBSEARCHRESADULT') : Joomla.JText._('VBSEARCHRESADULTS')) + ' '; |
| 487 |
vbo_uicontrol_guests += (vbo_geo_showchildren > 0 && vbo_geo_guestparties[vbo_geomap_booking_step]['children'] > 1 ? (', ' + vbo_geo_guestparties[vbo_geomap_booking_step]['children'] + ' ' + (vbo_geo_guestparties[vbo_geomap_booking_step]['children'] == 1 ? Joomla.JText._('VBSEARCHRESCHILD') : Joomla.JText._('VBSEARCHRESCHILDREN'))) : ''); |
| 488 |
jQuery('.vbo-geomap-uicontrol-partyguests').html(vbo_uicontrol_guests); |
| 489 |
} |
| 490 |
|
| 491 |
// unset any previously defined marker, if any |
| 492 |
for (var i in vbo_geomarker_units) { |
| 493 |
if (vbo_geomarker_units.hasOwnProperty(i)) { |
| 494 |
vbo_geomarker_units[i].setMap(null); |
| 495 |
} |
| 496 |
} |
| 497 |
vbo_geomarker_units = {}; |
| 498 |
|
| 499 |
// iterate through rooms of current party |
| 500 |
var party_rooms = vbo_geomarker_parties[vbo_geomap_booking_step]; |
| 501 |
for (var room in party_rooms) { |
| 502 |
if (!party_rooms.hasOwnProperty(room)) { |
| 503 |
continue; |
| 504 |
} |
| 505 |
var idroom = party_rooms[room]['id']; |
| 506 |
var rname = party_rooms[room]['name']; |
| 507 |
var runits = party_rooms[room]['units']; |
| 508 |
var rcost = party_rooms[room]['cost']; |
| 509 |
var rprevcost = party_rooms[room].hasOwnProperty('prev_cost') ? party_rooms[room]['prev_cost'] : null; |
| 510 |
var tot_markers = party_rooms[room]['tot_markers']; |
| 511 |
if (!vbo_geomarker_units_pos.hasOwnProperty(idroom)) { |
| 512 |
continue; |
| 513 |
} |
| 514 |
// iterate through all markers for this room |
| 515 |
for (var m = 1; m <= tot_markers; m++) { |
| 516 |
if (!vbo_geomarker_units_pos[idroom].hasOwnProperty(m)) { |
| 517 |
continue; |
| 518 |
} |
| 519 |
// make sure this room index is available on these dates |
| 520 |
if (vbo_rooms_units_booked.hasOwnProperty(idroom)) { |
| 521 |
var room_index_booked = false; |
| 522 |
for (var res_id in vbo_rooms_units_booked[idroom]) { |
| 523 |
if (!vbo_rooms_units_booked[idroom].hasOwnProperty(res_id)) { |
| 524 |
continue; |
| 525 |
} |
| 526 |
if (vbo_rooms_units_booked[idroom][res_id] == m) { |
| 527 |
room_index_booked = true; |
| 528 |
break; |
| 529 |
} |
| 530 |
} |
| 531 |
if (room_index_booked === true) { |
| 532 |
// this marker (room unit) index is booked |
| 533 |
continue; |
| 534 |
} |
| 535 |
} |
| 536 |
// make sure this room is still selectable |
| 537 |
var selected_units = 0; |
| 538 |
for (var step in vbo_rooms_units_selected) { |
| 539 |
if (!vbo_rooms_units_selected.hasOwnProperty(step)) { |
| 540 |
continue; |
| 541 |
} |
| 542 |
if (vbo_rooms_units_selected[step]['idroom'] == idroom) { |
| 543 |
// increase units selected for this room |
| 544 |
selected_units++; |
| 545 |
if (tot_markers > 1 && vbo_rooms_units_selected[step]['index'] == m) { |
| 546 |
// this exact index was selected, and the room has got multiple markers, so skip it |
| 547 |
selected_units = runits; |
| 548 |
break; |
| 549 |
} |
| 550 |
} |
| 551 |
} |
| 552 |
if (selected_units >= runits) { |
| 553 |
// this room has no more units available or this multi-marker was selected already, so skip the marker |
| 554 |
continue; |
| 555 |
} |
| 556 |
// prepare marker object for the current room unit |
| 557 |
var marker_title = rname + ' #' + (m + ''); |
| 558 |
if (tot_markers === 1) { |
| 559 |
marker_title = rname; |
| 560 |
} else if (vbo_info_markers_helper.hasOwnProperty(idroom) && vbo_info_markers_helper[idroom].hasOwnProperty(m)) { |
| 561 |
marker_title = rname + ' - ' + vbo_info_markers_helper[idroom][m]; |
| 562 |
} |
| 563 |
var marker_options = { |
| 564 |
draggable: false, |
| 565 |
map: vbo_geomap, |
| 566 |
position: { |
| 567 |
lat: parseFloat(vbo_geomarker_units_pos[idroom][m]['lat']), |
| 568 |
lng: parseFloat(vbo_geomarker_units_pos[idroom][m]['lng']) |
| 569 |
}, |
| 570 |
title: marker_title |
| 571 |
}; |
| 572 |
// check if we know a custom icon for this marker |
| 573 |
if (vbo_geomarker_units_pos[idroom][m].hasOwnProperty('icon')) { |
| 574 |
marker_options['icon'] = vbo_geomarker_units_pos[idroom][m]['icon']; |
| 575 |
} |
| 576 |
// set custom properties |
| 577 |
marker_options['room_id'] = idroom; |
| 578 |
marker_options['room_name'] = rname; |
| 579 |
marker_options['room_units'] = runits; |
| 580 |
marker_options['room_cost'] = rcost; |
| 581 |
marker_options['room_prev_cost'] = rprevcost; |
| 582 |
marker_options['room_index'] = m; |
| 583 |
marker_options['room_gallery'] = (vbo_geo_rooms_galleries.hasOwnProperty(idroom) && vbo_geo_rooms_galleries[idroom].length ? 1 : 0); |
| 584 |
// create marker infowindow |
| 585 |
var vbo_info_marker_cont = vboGeoInfoMarkerContent(idroom, m, marker_title, rcost, rprevcost); |
| 586 |
var vbo_info_marker = new google.maps.InfoWindow({ |
| 587 |
content: vbo_info_marker_cont, |
| 588 |
}); |
| 589 |
// add unit marker to map |
| 590 |
var vbo_geomarker_runit = new google.maps.Marker(marker_options); |
| 591 |
// add listener to marker's click event |
| 592 |
vbo_geomarker_runit.addListener('click', function() { |
| 593 |
// close any other open infowindow first |
| 594 |
for (var infom in vbo_info_markers) { |
| 595 |
if (!vbo_info_markers.hasOwnProperty(infom)) { |
| 596 |
continue; |
| 597 |
} |
| 598 |
vbo_info_markers[infom].close(); |
| 599 |
} |
| 600 |
// display its infowindow only |
| 601 |
if (this['room_id'] && this['room_index']) { |
| 602 |
var identifier = this['room_id'] + '_' + this['room_index']; |
| 603 |
if (vbo_info_markers.hasOwnProperty(identifier)) { |
| 604 |
vbo_info_markers[identifier].open(vbo_geomap, this); |
| 605 |
if (this['room_gallery'] > 0) { |
| 606 |
var gallery_params = { |
| 607 |
images: vbo_geo_rooms_galleries[this['room_id']], |
| 608 |
navButPrevContent: '<?php VikBookingIcons::e('chevron-left'); ?>', |
| 609 |
navButNextContent: '<?php VikBookingIcons::e('chevron-right'); ?>', |
| 610 |
containerHeight: '195px', |
| 611 |
}; |
| 612 |
var gallery_selector = '.vbo-geomarker-infowin-room-gallery[data-idroom="' + this['room_id'] + '"]'; |
| 613 |
if (jQuery(gallery_selector).length) { |
| 614 |
// render gallery immediately |
| 615 |
vboGeoMapRenderInfowinGallery(gallery_selector, gallery_params); |
| 616 |
} else { |
| 617 |
// infowindows may take some seconds to be displayed, so we delay the rendering |
| 618 |
window.setTimeout(vboGeoMapRenderInfowinGallery.bind(null, gallery_selector, gallery_params), 500); |
| 619 |
} |
| 620 |
} |
| 621 |
} else { |
| 622 |
console.error('info marker identifier not found', this, identifier); |
| 623 |
} |
| 624 |
} else { |
| 625 |
console.error('info marker properties not found', this); |
| 626 |
} |
| 627 |
}); |
| 628 |
// register marker to pool |
| 629 |
var identifier = idroom + '_' + m; |
| 630 |
vbo_geomarker_units[identifier] = vbo_geomarker_runit; |
| 631 |
// register info window |
| 632 |
vbo_info_markers[identifier] = vbo_info_marker; |
| 633 |
} |
| 634 |
} |
| 635 |
} |
| 636 |
|
| 637 |
/** |
| 638 |
* Renders the vikDotsSlider gallery for an infowindow. |
| 639 |
* We wrap the use of this plugin inside a function so that we can delay the execution. |
| 640 |
*/ |
| 641 |
function vboGeoMapRenderInfowinGallery(selector, params) { |
| 642 |
jQuery(selector).vikDotsSlider(params); |
| 643 |
} |
| 644 |
|
| 645 |
/** |
| 646 |
* Initializes the interactive geo map through Google Maps for the current booking step. |
| 647 |
*/ |
| 648 |
function vboInitInteractiveGeoMap() { |
| 649 |
// default map options |
| 650 |
var def_map_options = { |
| 651 |
center: new google.maps.LatLng(<?php echo $global_geo_params->latitude; ?>, <?php echo $global_geo_params->longitude; ?>), |
| 652 |
zoom: <?php echo (int)$global_geo_params->zoom; ?>, |
| 653 |
mapTypeId: '<?php echo $global_geo_params->mtype; ?>', |
| 654 |
mapTypeControl: false |
| 655 |
}; |
| 656 |
// initialize Map |
| 657 |
vbo_geomap = new google.maps.Map(document.getElementById('vbo-results-geo-map'), def_map_options); |
| 658 |
// add listeners to map |
| 659 |
vbo_geomap.addListener('click', function(e) { |
| 660 |
// close all infowindows |
| 661 |
for (var infom in vbo_info_markers) { |
| 662 |
if (!vbo_info_markers.hasOwnProperty(infom)) { |
| 663 |
continue; |
| 664 |
} |
| 665 |
vbo_info_markers[infom].close(); |
| 666 |
} |
| 667 |
}); |
| 668 |
// add markers and set UI control for the current rooms party |
| 669 |
vboInteractiveGeoMapSetPartyMarkers(); |
| 670 |
// center bounds |
| 671 |
vboInteractiveGeoMapCenterBounds(); |
| 672 |
// populate ground overlay image, if set |
| 673 |
if (vbo_dbground_overlay !== null) { |
| 674 |
// compose LatLngBounds object |
| 675 |
var overlay_bounds = new google.maps.LatLngBounds( |
| 676 |
new google.maps.LatLng(parseFloat(vbo_dbground_overlay.south), parseFloat(vbo_dbground_overlay.west)), |
| 677 |
new google.maps.LatLng(parseFloat(vbo_dbground_overlay.north), parseFloat(vbo_dbground_overlay.east)) |
| 678 |
); |
| 679 |
// update ground overlay object |
| 680 |
vbo_ground_overlay = new google.maps.GroundOverlay(vbo_dbground_overlay.url, overlay_bounds); |
| 681 |
// set the overlay to the map |
| 682 |
vbo_ground_overlay.setMap(vbo_geomap); |
| 683 |
} |
| 684 |
} |
| 685 |
|
| 686 |
jQuery(document).ready(function() { |
| 687 |
|
| 688 |
// init interactive geo map with markers |
| 689 |
vboInitInteractiveGeoMap(); |
| 690 |
|
| 691 |
// register hovering events for minicart body |
| 692 |
if (jQuery('.vbo-geomap-minicart').length) { |
| 693 |
jQuery('.vbo-geomap-minicart').hover(function() { |
| 694 |
jQuery('.vbo-geomap-minicart-body').removeClass('vbo-geomap-minicart-body-hid').addClass('vbo-geomap-minicart-body-enter'); |
| 695 |
}, function() { |
| 696 |
jQuery('.vbo-geomap-minicart-body').removeClass('vbo-geomap-minicart-body-enter').addClass('vbo-geomap-minicart-body-hid'); |
| 697 |
}); |
| 698 |
} |
| 699 |
|
| 700 |
// preload image gallery |
| 701 |
jQuery(vbo_geo_rooms_galleries).vikDotsSlider('preloadImages'); |
| 702 |
}); |
| 703 |
|
| 704 |
</script> |
| 705 |
<?php |
| 706 |
} |
| 707 |
|