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

default_interactive_map.php in VikBooking Hotel Booking Engine & PMS 1.6.6, at site/views/search/tmpl/default_interactive_map.php

707 lines 28.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 $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