PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.7.2
VikBooking Hotel Booking Engine & PMS v1.7.2
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 / precheckin / tmpl / default.php

default.php in VikBooking Hotel Booking Engine & PMS 1.7.2, at site/views/precheckin/tmpl/default.php

746 lines 27.8 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 $document = JFactory::getDocument();
14 // load jQuery lib e jQuery UI
15 if (VikBooking::loadJquery()) {
16 JHtml::fetch('jquery.framework', true, true);
17 }
18 $document->addStyleSheet(VBO_SITE_URI.'resources/jquery-ui.min.css');
19 JHtml::fetch('script', VBO_SITE_URI.'resources/jquery-ui.min.js');
20
21 $currencysymb = VikBooking::getCurrencySymb();
22 $datesep = VikBooking::getDateSeparator();
23 $nowdf = VikBooking::getDateFormat();
24 if ($nowdf == "%d/%m/%Y") {
25 $df = 'd/m/Y';
26 $juidf = 'dd/mm/yy';
27 } elseif ($nowdf == "%m/%d/%Y") {
28 $df = 'm/d/Y';
29 $juidf = 'mm/dd/yy';
30 } else {
31 $df = 'Y/m/d';
32 $juidf = 'yy/mm/dd';
33 }
34 $wdays_map = array(
35 JText::translate('VBWEEKDAYZERO'),
36 JText::translate('VBWEEKDAYONE'),
37 JText::translate('VBWEEKDAYTWO'),
38 JText::translate('VBWEEKDAYTHREE'),
39 JText::translate('VBWEEKDAYFOUR'),
40 JText::translate('VBWEEKDAYFIVE'),
41 JText::translate('VBWEEKDAYSIX')
42 );
43 $ts_info = getdate($this->order['ts']);
44 $checkin_info = getdate($this->order['checkin']);
45 $checkout_info = getdate($this->order['checkout']);
46 $pitemid = VikRequest::getInt('Itemid', 0, 'request');
47
48 // compose the calculation for pax_data
49 list($pax_fields, $pax_fields_attributes) = VikBooking::getPaxFields(true);
50 $pax_data = array();
51 $count_pax_data = 1;
52 if (!empty($this->customer['pax_data'])) {
53 $pax_data = json_decode($this->customer['pax_data'], true);
54 }
55
56 $arrpeople = array();
57 foreach ($this->orderrooms as $ind => $or) {
58 $num = $ind + 1;
59 $arrpeople[$num]['adults'] = $or['adults'];
60 $arrpeople[$num]['children'] = $or['children'];
61 $arrpeople[$num]['children_age'] = $or['childrenage'];
62 $arrpeople[$num]['t_first_name'] = $or['t_first_name'];
63 $arrpeople[$num]['t_last_name'] = $or['t_last_name'];
64 }
65
66 // countries list
67 $all_countries = VikBooking::getCountriesArray();
68
69 // access the active back-end driver instance also for pre-checkin
70 $pax_fields_obj = VBOCheckinPax::getInstance();
71
72 // load langs for JS
73 JText::script('VBO_UPLOAD_FAILED');
74 JText::script('VBO_REMOVEF_CONFIRM');
75 JText::script('VBO_PRECHECKIN_TOAST_HELP');
76 ?>
77
78 <h3 class="vbo-booking-details-intro"><?php echo JText::sprintf('VBOYOURBOOKCONFAT', VikBooking::getFrontTitle()); ?></h3>
79
80 <div class="vbo-booking-details-topcontainer vbo-booking-details-precheckin">
81
82 <div class="vbo-booking-details-head vbo-booking-details-head-confirmed">
83 <h4><?php echo JText::translate('VBOPRECHECKIN'); ?></h4>
84 </div>
85
86 <div class="vbo-booking-details-midcontainer">
87 <div class="vbo-booking-details-bookinfos">
88 <span class="vbvordudatatitle"><?php echo JText::translate('VBORDERDETAILS'); ?></span>
89 <div class="vbo-booking-details-bookinfo">
90 <span class="vbo-booking-details-bookinfo-lbl"><?php echo JText::translate('VBORDEREDON'); ?></span>
91 <span class="vbo-booking-details-bookinfo-val"><?php echo $wdays_map[$ts_info['wday']].', '.date(str_replace("/", $datesep, $df).' H:i', $this->order['ts']); ?></span>
92 </div>
93 <div class="vbo-booking-details-bookinfo">
94 <span class="vbo-booking-details-bookinfo-lbl"><?php echo JText::translate('VBCONFIRMNUMB'); ?></span>
95 <span class="vbo-booking-details-bookinfo-val"><?php echo $this->order['confirmnumber']; ?></span>
96 </div>
97 <div class="vbo-booking-details-bookinfo">
98 <span class="vbo-booking-details-bookinfo-lbl"><?php echo JText::translate('VBDAL'); ?></span>
99 <span class="vbo-booking-details-bookinfo-val"><?php echo $wdays_map[$checkin_info['wday']].', '.date(str_replace("/", $datesep, $df).' H:i', $this->order['checkin']); ?></span>
100 </div>
101 <div class="vbo-booking-details-bookinfo">
102 <span class="vbo-booking-details-bookinfo-lbl"><?php echo JText::translate('VBAL'); ?></span>
103 <span class="vbo-booking-details-bookinfo-val"><?php echo $wdays_map[$checkout_info['wday']].', '.date(str_replace("/", $datesep, $df).' H:i', $this->order['checkout']); ?></span>
104 </div>
105 <div class="vbo-booking-details-bookinfo">
106 <span class="vbo-booking-details-bookinfo-lbl"><?php echo JText::translate('VBDAYS'); ?></span>
107 <span class="vbo-booking-details-bookinfo-val"><?php echo $this->order['days']; ?></span>
108 </div>
109 </div>
110 </div>
111
112 <div class="vbo-precheckin-container">
113 <div class="info vbo-precheckin-disclaimer"><?php echo JText::translate('VBO_PRECHECKIN_DISCLAIMER'); ?></div>
114 <form action="<?php echo JRoute::rewrite('index.php?option=com_vikbooking'.(!empty($pitemid) ? '&Itemid='.$pitemid : '')); ?>" method="post">
115 <input type="hidden" name="option" value="com_vikbooking" />
116 <input type="hidden" name="task" value="storeprecheckin" />
117 <input type="hidden" name="sid" value="<?php echo empty($this->order['sid']) && !empty($this->order['idorderota']) ? $this->order['idorderota'] : $this->order['sid']; ?>" />
118 <input type="hidden" name="ts" value="<?php echo $this->order['ts']; ?>" />
119 <input type="hidden" name="Itemid" value="<?php echo $pitemid; ?>" />
120 <?php
121 foreach ($this->orderrooms as $ind => $or) {
122 $num = $ind + 1;
123 // total guests details available
124 $count_pax_data = $num < 2 ? $count_pax_data : 0;
125 if (isset($pax_data[$ind])) {
126 $count_pax_data = count($pax_data[$ind]);
127 }
128
129 // calculate the number of guests to register depending on current driver settings for pre-checkin (plugin only)
130 $guests_to_register = $pax_fields_obj->registerChildren($precheckin = true) ? ($arrpeople[$num]['adults'] + $arrpeople[$num]['children']) : $arrpeople[$num]['adults'];
131 ?>
132 <div class="vbo-precheckin-room-wrapper">
133 <div class="vbo-precheckin-room-wrap <?php echo $count_pax_data >= $guests_to_register ? 'vbo-precheckin-guestscount-complete' : 'vbo-precheckin-guestscount-incomplete'; ?>">
134 <div class="vbo-precheckin-room-head">
135 <span><?php echo $or['name']; ?></span>
136 </div>
137 <div class="vbo-precheckin-adults-cont">
138 <?php
139 for ($g = 1; $g <= $guests_to_register; $g++) {
140 $current_guest = array();
141 if (count($pax_data) && isset($pax_data[$ind]) && isset($pax_data[$ind][$g])) {
142 $current_guest = $pax_data[$ind][$g];
143 } elseif ($ind < 1 && $g == 1) {
144 $current_guest = $this->customer;
145 }
146 ?>
147 <div class="vbo-precheckin-adult-wrap">
148 <div class="vbo-precheckin-adult-num">
149 <span><?php echo JText::sprintf('VBOGUESTNUM', $g); ?></span>
150 </div>
151 <?php
152 /**
153 * Overrides tip: to add and collect custom details from each guest it is possible to push more
154 * pairs of key-values to $pax_fields. For example, a custom value could be pushed like this:
155 *
156 * $pax_fields['custom_field_key'] = 'Custom Field Name';
157 * $pax_fields_attributes['custom_field_key'] = 'text';
158 *
159 * @see the best way to customize the guest fields is to use the apposite plugin hooks/events.
160 */
161 $pax_field_ind = 1;
162 foreach ($pax_fields as $paxk => $paxv) {
163 // determine the pax field rendering type
164
165 if (isset($pax_fields_attributes[$paxk]) && is_array($pax_fields_attributes[$paxk])) {
166 // select with choices
167 $field_rendering_type = 'select';
168 } elseif (isset($pax_fields_attributes[$paxk]) && $pax_fields_attributes[$paxk] == 'country') {
169 // field of type country
170 $field_rendering_type = 'country';
171 } elseif (isset($pax_fields_attributes[$paxk]) && $pax_fields_attributes[$paxk] == 'calendar') {
172 // datepicker calendar
173 $field_rendering_type = 'calendar';
174 } elseif (isset($pax_fields_attributes[$paxk]) && $pax_fields_attributes[$paxk] == 'file') {
175 // file upload (multiple files allowed)
176 $field_rendering_type = 'file';
177 } elseif (isset($pax_fields_attributes[$paxk]) && $pax_fields_attributes[$paxk] == 'text') {
178 // text
179 $field_rendering_type = 'text';
180 } else {
181 // custom pax-field type
182 $field_rendering_type = 'paxfield';
183 }
184
185 // the pax-field HTML string, if any
186 $pax_field_html = '';
187
188 // run pre-flight check to ensure the paxfield is compatible with the current guest
189 if ($field_rendering_type === 'paxfield') {
190 /**
191 * Attempt to render a custom field previously installed through a third party plugin.
192 * If no such field type is found, the object will default to the "text" type.
193 *
194 * @since 1.16.3 (J) - 1.6.3 (WP)
195 */
196
197 // get an instance of the VBOCheckinPaxfield object
198 $pax_field_obj = $pax_fields_obj->getField($paxk);
199
200 // detect the current type of guest
201 $guest_type = $g > $arrpeople[$num]['adults'] ? 'child' : 'adult';
202
203 // set object data
204 $pax_field_obj->setGuestType($guest_type)
205 ->setFieldNumber($pax_field_ind)
206 ->setGuestNumber($g)
207 ->setGuestData($current_guest)
208 ->setRoomIndex($ind)
209 ->setRoomGuests($arrpeople[$num]['adults'], $arrpeople[$num]['children'])
210 ->setTotalRooms(count($arrpeople));
211
212 // render input field
213 $pax_field_html = $pax_fields_obj->render($pax_field_obj);
214 if (empty($pax_field_html)) {
215 // nothing to display, increase the counter and continue
216 $pax_field_ind++;
217 continue;
218 }
219 }
220
221 // open field container
222 ?>
223 <div class="vbo-precheckin-guest-detail<?php echo isset($pax_fields_attributes[$paxk]) && $pax_fields_attributes[$paxk] == 'file' ? ' vbo-precheckin-guest-detail-files' : ''; ?>">
224 <label for="pax-field-<?php echo $paxv . '-' . $ind . '-' . $g . '-' . $paxk; ?>"><?php echo $paxv; ?></label>
225 <?php
226
227 if ($field_rendering_type === 'paxfield') {
228 // render the custom pax-field input element
229
230 // access the implementor object
231 $implementor = $pax_fields_obj->getFieldTypeImplementor($pax_field_obj);
232
233 // check if a particular CSS class has been defined
234 $field_container_class = $implementor->getContainerClassAttr();
235 $field_container_class = !empty($field_container_class) ? " $field_container_class" : '';
236
237 // display the custom field type
238 ?>
239 <div class="vbo-precheckin-custom-field<?php echo $field_container_class; ?>">
240 <?php echo $pax_field_html; ?>
241 </div>
242 <?php
243 } elseif ($field_rendering_type === 'select') {
244 // select with choices
245 ?>
246 <select name="guests[<?php echo $ind; ?>][<?php echo $g; ?>][<?php echo $paxk; ?>]">
247 <option></option>
248 <?php
249 $opt_ind = 1;
250 foreach ($pax_fields_attributes[$paxk] as $attrk => $attrv) {
251 $paxv_selected = isset($current_guest[$paxk]) && ($current_guest[$paxk] == $attrv || (!is_numeric($attrk) && $current_guest[$paxk] == $attrk));
252 if (!$paxv_selected && isset($current_guest[$paxk]) && is_numeric($current_guest[$paxk])) {
253 /**
254 * It is safe to compare such select tags, which usually refer to "gender",
255 * to even numeric values in order to attempt to pre-select the current value.
256 */
257 $paxv_selected = ($opt_ind == $current_guest[$paxk]);
258 }
259 ?>
260 <option value="<?php echo !is_numeric($attrk) ? $attrk : $attrv; ?>"<?php echo ($paxv_selected ? ' selected="selected"' : ''); ?>><?php echo $attrv; ?></option>
261 <?php
262 $opt_ind++;
263 }
264 ?>
265 </select>
266 <?php
267 } elseif ($field_rendering_type === 'country') {
268 // field of type country
269 echo VikBooking::getCountriesSelect('guests['.$ind.']['.$g.']['.$paxk.']', $all_countries, (isset($current_guest[$paxk]) ? $current_guest[$paxk] : ''), $paxv);
270 } elseif ($field_rendering_type === 'calendar') {
271 // datepicker calendar
272 ?>
273 <input type="text" autocomplete="off" data-gind="<?php echo $g; ?>" class="vbo-paxfield vbo-paxfield-datepicker" name="guests[<?php echo $ind; ?>][<?php echo $g; ?>][<?php echo $paxk; ?>]" value="<?php echo (isset($current_guest[$paxk]) ? $this->escape($current_guest[$paxk]) : ''); ?>" />
274 <?php
275 } elseif ($field_rendering_type === 'file') {
276 // file upload (multiple files allowed)
277 ?>
278 <input type="hidden" id="vbo-paxfield-curfiles-<?php echo $ind . '-' . $g . '-' . $paxk; ?>" name="guests[<?php echo $ind; ?>][<?php echo $g; ?>][<?php echo $paxk; ?>]" value="<?php echo (isset($current_guest[$paxk]) ? $this->escape($current_guest[$paxk]) : ''); ?>" />
279
280 <div class="vbo-paxfield-upload-container">
281 <button type="button" class="btn vbo-pref-color-btn-secondary vbo-precheckin-uploadfile" data-roomi="<?php echo $ind; ?>" data-guesti="<?php echo $g; ?>" data-paxk="<?php echo $paxk; ?>"><?php VikBookingIcons::e('camera'); ?> <?php echo JText::translate('VBOUPSELLADD'); ?></button>
282 <div class="vbo-paxfield-upload-progress-wrap" id="vbo-paxfield-upload-progress-<?php echo $ind . '-' . $g . '-' . $paxk; ?>" style="display: none;">
283 <div class="vbo-paxfield-upload-progress">&nbsp;</div>
284 </div>
285 </div>
286
287 <div class="vbo-paxfield vbo-paxfield-files" id="vbo-paxfield-files-<?php echo $ind . '-' . $g . '-' . $paxk; ?>" data-gselector="<?php echo $ind . '-' . $g . '-' . $paxk; ?>">
288 <?php
289 if (isset($current_guest[$paxk]) && !empty($current_guest[$paxk])) {
290 $guest_files = explode('|', $current_guest[$paxk]);
291 foreach ($guest_files as $gfk => $guest_file) {
292 if (empty($guest_file) || strpos($guest_file, 'http') !== 0) {
293 continue;
294 }
295 $furl_segments = explode('/', $guest_file);
296 $guest_fname = $furl_segments[(count($furl_segments) - 1)];
297 $read_fname = substr($guest_fname, (strpos($guest_fname, '_') + 1));
298 ?>
299 <div class="vbo-paxfield-file-uploaded">
300 <span class="vbo-paxfield-file-uploaded-rm"><?php VikBookingIcons::e('times-circle'); ?></span>
301 <a href="<?php echo $guest_file; ?>" target="_blank">
302 <?php VikBookingIcons::e('image'); ?>
303 <span><?php echo $read_fname; ?></span>
304 </a>
305 </div>
306 <?php
307 }
308 }
309 ?>
310 </div>
311 <?php
312 } else {
313 // text
314 ?>
315 <input type="text" autocomplete="off" data-gind="<?php echo $g; ?>" class="vbo-paxfield" name="guests[<?php echo $ind; ?>][<?php echo $g; ?>][<?php echo $paxk; ?>]" value="<?php echo (isset($current_guest[$paxk]) ? $this->escape($current_guest[$paxk]) : ''); ?>" />
316 <?php
317 }
318
319 // close field container
320 ?>
321 </div>
322 <?php
323
324 // increase field counter
325 $pax_field_ind++;
326 }
327 ?>
328 </div>
329 <?php
330 }
331 ?>
332 </div>
333 </div>
334 </div>
335 <?php
336 }
337 ?>
338 <div class="vbo-precheckin-submit">
339 <button type="submit" class="btn btn-large vbo-pref-color-btn"><?php echo JText::translate('VBOSUBMITPRECHECKIN'); ?></button>
340 </div>
341 </form>
342 </div>
343
344 </div>
345
346 <input type="file" id="vbo-precheckin-upload-field" accept="image/*,.pdf" multiple="multiple" style="display: none;" />
347
348 <script type="text/javascript">
349 /**
350 * Declare global score variables
351 */
352 var vbo_prechin_current_room = null,
353 vbo_prechin_current_guest = null,
354 vbo_prechin_current_paxk = null,
355 vbo_typingtoast_displayed = false,
356 vbo_typingtoast_changes = 0;
357
358 /**
359 * Displays a toast message
360 */
361 function vboPresentToast(content, duration, clickcallback) {
362 // remove any other previous toast from the document
363 jQuery('.vbo-toast-message').remove();
364 // build toast
365 var toast = jQuery('<div>').addClass('vbo-toast-message vbo-toast-message-presented');
366 // onclick function
367 var onclickfunc = function() {
368 // hide toast when clicked
369 jQuery(this).removeClass('vbo-toast-message-presented').addClass('vbo-toast-message-dimissed');
370 };
371 if (typeof clickcallback === 'function') {
372 onclickfunc = function() {
373 // launch callback
374 clickcallback.call(this);
375 // hide toast either way
376 jQuery(this).removeClass('vbo-toast-message-presented').addClass('vbo-toast-message-dimissed');
377 };
378 }
379 // register click event on toast
380 toast.on('click', onclickfunc);
381 // build toast content
382 var inner = jQuery('<div>').addClass('vbo-toast-message-content');
383 toast.append(inner.append(content));
384 // present toast
385 jQuery('body').append(toast);
386 // set timeout for auto-dismiss
387 if (typeof duration === 'undefined') {
388 duration = 4000;
389 }
390 if (!isNaN(duration) && duration > 0) {
391 // if duration NaN or <= 0, the toast won't be dismissed automatically
392 setTimeout(function() {
393 jQuery('.vbo-toast-message').removeClass('vbo-toast-message-presented').addClass('vbo-toast-message-dimissed');
394 }, duration);
395 }
396 }
397
398 /**
399 * Some older smartphones or tablets may not support files uploading
400 */
401 function vboIsUploadSupported() {
402 if (!navigator || !navigator.userAgent) {
403 return false;
404 }
405 if (navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/)) {
406 return false;
407 } else {
408 return true;
409 }
410 }
411
412 /**
413 * Checks wether a jQuery XHR response object was due to a connection error.
414 * Property readyState 0 = Network Error (UNSENT), 4 = HTTP error (DONE).
415 * Property responseText may not be set in some browsers.
416 * This is what to check to determine if a connection error occurred.
417 */
418 function vboIsConnectionLostError(err) {
419 if (!err || !err.hasOwnProperty('status')) {
420 return false;
421 }
422
423 return (
424 err.statusText == 'error'
425 && err.status == 0
426 && (err.readyState == 0 || err.readyState == 4)
427 && (!err.hasOwnProperty('responseText') || err.responseText == '')
428 );
429 }
430
431 /**
432 * Ensures AJAX requests that fail due to connection errors are retried automatically.
433 * This function is made specifically to work with AJAX uploads.
434 */
435 function vboDoAjaxUpload(url, data, success, failure, progress, attempt) {
436 var VBO_AJAX_MAX_ATTEMPTS = 3;
437
438 if (attempt === undefined) {
439 attempt = 1;
440 }
441
442 var settings = {
443 type: 'post',
444 contentType: false,
445 processData: false,
446 cache: false,
447 };
448
449 // register event for upload progress
450 settings.xhr = function() {
451 var xhrobj = jQuery.ajaxSettings.xhr();
452 if (xhrobj.upload) {
453 // attach progress event
454 xhrobj.upload.addEventListener('progress', function(event) {
455 // calculate percentage
456 var percent = 0;
457 var position = event.loaded || event.position;
458 var total = event.total;
459 if (event.lengthComputable) {
460 percent = Math.ceil(position / total * 100);
461 }
462 // trigger callback
463 progress(percent);
464 }, false);
465 }
466 return xhrobj;
467 };
468
469 if (typeof url === 'object') {
470 // configuration object passed
471 Object.assign(settings, url);
472 } else {
473 // use the default settings
474 settings.url = url;
475 }
476
477 // set request data
478 settings.data = data;
479
480 return jQuery.ajax(
481 settings
482 ).done(function(resp) {
483 if (success !== undefined) {
484 // launch success callback function
485 success(resp);
486 }
487 }).fail(function(err) {
488 /**
489 * If the error is caused by a site connection lost, and if the number
490 * of retries is lower than max attempts, retry the same AJAX request.
491 */
492 if (attempt < VBO_AJAX_MAX_ATTEMPTS && vboIsConnectionLostError(err)) {
493 // delay the retry by half second
494 setTimeout(function() {
495 // relaunch same request and increase number of attempts
496 console.log('Retrying previous AJAX request');
497 vboDoAjaxUpload(url, data, success, failure, progress, (attempt + 1));
498 }, 500);
499 } else {
500 // launch the failure callback otherwise
501 if (failure !== undefined) {
502 failure(err);
503 }
504 }
505
506 // always log the error in console
507 console.log('AJAX request failed' + (err.status == 500 ? ' (' + err.responseText + ')' : ''), err);
508 });
509 }
510
511 /**
512 * Updates the progress bar for the current uploading process
513 */
514 function vboUploadSetProgress(selector_suffix, progress) {
515 progress = Math.max(0, progress);
516 progress = Math.min(100, progress);
517
518 var progress_wrap = jQuery('#vbo-paxfield-upload-progress-' + selector_suffix);
519 if (!progress_wrap.length) {
520 return;
521 }
522 progress_wrap.find('.vbo-paxfield-upload-progress').width(progress + '%').html(progress + '%');
523 }
524
525 /**
526 * Uploads the selected document(s)
527 */
528 function vboUploadDocuments(files) {
529 // create form data object
530 var formData = new FormData();
531
532 // set booking and pre-checkin information
533 formData.append('sid', '<?php echo empty($this->order['sid']) && !empty($this->order['idorderota']) ? $this->order['idorderota'] : $this->order['sid']; ?>');
534 formData.append('ts', '<?php echo $this->order['ts']; ?>');
535 formData.append('room_index', vbo_prechin_current_room);
536 formData.append('guest_index', vbo_prechin_current_guest);
537 formData.append('pax_index', vbo_prechin_current_paxk);
538
539 // selector suffix is composed of room, guest and pax field indexes
540 var selector_suffix = vbo_prechin_current_room + '-' + vbo_prechin_current_guest + '-' + vbo_prechin_current_paxk;
541
542 // iterate files selected and append them to the form data
543 for (var i = 0; i < files.length; i++) {
544 formData.append('docs[]', files[i]);
545 }
546
547 // display progress wrap
548 jQuery('#vbo-paxfield-upload-progress-' + selector_suffix).show();
549
550 // AJAX request to upload the files selected
551 vboDoAjaxUpload(
552 // url
553 '<?php echo VikBooking::ajaxUrl(JRoute::rewrite('index.php?option=com_vikbooking&task=precheckin_upload_docs&tmpl=component'.(!empty($pitemid) ? '&Itemid='.$pitemid : ''), false)); ?>',
554 // form data
555 formData,
556 // success callback
557 function(response) {
558 // hide progress wrap
559 jQuery('#vbo-paxfield-upload-progress-' + selector_suffix).hide();
560 // unset progress
561 vboUploadSetProgress(selector_suffix, 0);
562
563 // parse response
564 try {
565 var obj_res = JSON.parse(response),
566 uploaded_urls = [];
567
568 for (var i in obj_res) {
569 if (!obj_res.hasOwnProperty(i) || !obj_res[i].hasOwnProperty('url')) {
570 continue;
571 }
572 uploaded_urls.push(obj_res[i]['url']);
573 }
574 if (!uploaded_urls.length) {
575 console.log('no valid URLs returned', response);
576 return false;
577 }
578 // update hidden field
579 var hidden_inp = jQuery('#vbo-paxfield-curfiles-' + selector_suffix);
580 var current_guest_files = hidden_inp.val().split('|');
581 if (!current_guest_files.length || !current_guest_files[0].length) {
582 current_guest_files = [];
583 }
584 // merge current files with new ones uploaded
585 var new_guest_files = current_guest_files.concat(uploaded_urls);
586 // update hidden input field to contain all files
587 hidden_inp.val(new_guest_files.join('|'));
588 // display links for the newly uploaded files
589 var uploaded_content = '';
590 for (var i = 0; i < uploaded_urls.length; i++) {
591 var furl_segments = uploaded_urls[i].split('/');
592 var guest_fname = furl_segments[(furl_segments.length - 1)];
593 var read_fname = guest_fname.substr((guest_fname.indexOf('_') + 1));
594
595 uploaded_content += '<div class="vbo-paxfield-file-uploaded">';
596 uploaded_content += ' <span class="vbo-paxfield-file-uploaded-rm"><?php VikBookingIcons::e('times-circle'); ?></span>';
597 uploaded_content += ' <a href="' + uploaded_urls[i] + '" target="_blank">';
598 uploaded_content += ' <?php VikBookingIcons::e('image'); ?>';
599 uploaded_content += ' <span>' + read_fname + '</span>';
600 uploaded_content += ' </a>';
601 uploaded_content += '</div>';
602 }
603 // append the new content
604 jQuery('#vbo-paxfield-files-' + selector_suffix).append(uploaded_content);
605
606 // display toast message
607 vboPresentToast(Joomla.JText._('VBO_PRECHECKIN_TOAST_HELP'), 4000, function() {
608 jQuery('html,body').animate({scrollTop: jQuery('.vbo-precheckin-submit').offset().top - 100}, {duration: 400});
609 });
610 } catch(err) {
611 console.error('could not parse JSON response for uploading documents', err, response);
612 }
613 },
614 // failure callback
615 function(error) {
616 alert(Joomla.JText._('VBO_UPLOAD_FAILED'));
617 // hide progress wrap
618 jQuery('#vbo-paxfield-upload-progress-' + selector_suffix).hide();
619 // unset progress
620 vboUploadSetProgress(selector_suffix, 0);
621
622 console.error(error);
623 },
624 // progress callback
625 function(progress) {
626 // update progress bar
627 vboUploadSetProgress(selector_suffix, progress);
628 }
629 );
630 }
631
632 /**
633 * Declare functions for DOM ready
634 */
635 jQuery(function() {
636
637 /**
638 * Datepicker for birth date
639 */
640 jQuery('.vbo-paxfield-datepicker').datepicker({
641 dateFormat: "<?php echo $juidf; ?>",
642 changeMonth: true,
643 changeYear: true,
644 yearRange: "<?php echo (date('Y') - 100) . ':' . date('Y'); ?>"
645 });
646
647 /**
648 * Click event on file-upload button
649 */
650 jQuery('.vbo-precheckin-uploadfile').click(function() {
651 var elem = jQuery(this);
652
653 var room_index = elem.data('roomi'),
654 guest_index = elem.data('guesti'),
655 pax_index = elem.data('paxk');
656
657 // check if device supports file upload
658 if (!vboIsUploadSupported()) {
659 alert('Your device may not support files uploading');
660 return false;
661 }
662
663 // update global vars
664 vbo_prechin_current_room = room_index;
665 vbo_prechin_current_guest = guest_index;
666 vbo_prechin_current_paxk = pax_index;
667
668 // trigger the click event on the hidden input field for the files upload
669 jQuery('#vbo-precheckin-upload-field').trigger('click');
670 });
671
672 /**
673 * Change event on global file-upload hidden field
674 */
675 jQuery('#vbo-precheckin-upload-field').on('change', function(e) {
676 // get files selected
677 var files = jQuery(this)[0].files;
678
679 if (!files || !files.length) {
680 console.error('no files selected for upload');
681 return false;
682 }
683
684 // upload selected files
685 vboUploadDocuments(files);
686
687 // make the input value empty
688 jQuery(this).val(null);
689 });
690
691 /**
692 * Click event on the button to remove an uploaded file
693 */
694 jQuery(document.body).on('click', '.vbo-paxfield-file-uploaded-rm', function() {
695 var file_container = jQuery(this).closest('.vbo-paxfield-file-uploaded');
696 if (!file_container.length) {
697 return false;
698 }
699 var file_url = file_container.find('a').attr('href');
700 var files_selector = file_container.closest('.vbo-paxfield-files').attr('data-gselector');
701 if (confirm(Joomla.JText._('VBO_REMOVEF_CONFIRM'))) {
702 var pax_elem = jQuery('#vbo-paxfield-curfiles-' + files_selector);
703 var pax_urls = pax_elem.val();
704 if (pax_urls.indexOf(file_url + '|') >= 0) {
705 pax_urls = pax_urls.replace(file_url + '|', '');
706 } else if (pax_urls.indexOf('|' + file_url) >= 0) {
707 pax_urls = pax_urls.replace('|' + file_url, '');
708 } else {
709 pax_urls = pax_urls.replace(file_url, '');
710 }
711 // update hidden input value
712 pax_elem.val(pax_urls);
713 // remove the file container
714 file_container.remove();
715 // display toast message
716 vboPresentToast(Joomla.JText._('VBO_PRECHECKIN_TOAST_HELP'), 4000, function() {
717 jQuery('html,body').animate({scrollTop: jQuery('.vbo-precheckin-submit').offset().top - 100}, {duration: 400});
718 });
719 }
720 });
721
722 /**
723 * Change event on input fields to trigger the toast message
724 */
725 jQuery('.vbo-precheckin-room-wrapper').find('input[type="text"], select').on('change', function() {
726 // if toast displayed and clicked, unset listener
727 if (vbo_typingtoast_displayed === true) {
728 jQuery('.vbo-precheckin-room-wrapper').find('input[type="text"], select').off('change');
729 }
730 // increase counter
731 vbo_typingtoast_changes++;
732 if (vbo_typingtoast_changes > 2) {
733 // reset counter
734 vbo_typingtoast_changes = 0;
735 // display toast message
736 vboPresentToast(Joomla.JText._('VBO_PRECHECKIN_TOAST_HELP'), 4000, function() {
737 jQuery('html,body').animate({scrollTop: jQuery('.vbo-precheckin-submit').offset().top - 100}, {duration: 400});
738 // if toast is clicked, we never display it again
739 vbo_typingtoast_displayed = true;
740 });
741 }
742 });
743
744 });
745 </script>
746