1 2/****************************************************************************** 3 * 4 * PROJECT: Flynax Classifieds Software 5 * VERSION: 4.8.2 6 * LISENSE: FL5S1Z14Y14Q - https://www.flynax.com/flynax-software-eula.html 7 * PRODUCT: Classified Ads Script 8 * DOMAIN : paginehoreca.it 9 * FILE : LIB.JS 10 * 11 * This script is a commercial software and any kind of using it must be 12 * coordinate with Flynax Owners Team and be agree to Flynax License Agreement 13 * 14 * This block may not be removed from this file or any other files with out 15 * permission of Flynax respective owners. 16 * 17 * Copyrights Flynax Classifieds Software | 2022 18 * https://www.flynax.com 19 * 20 ******************************************************************************/ 21 22var bookingClass = function(){ 23 var self = this; 24 25 /** 26 * Showing errors 27 * @param {string} error - Message of error 28 */ 29 this.errorShow = function(error) { 30 printMessage('error', error); 31 self.book_color(true); 32 }; 33 34 /** 35 * Selection days on calendar 36 * @param {string} o_id - Mktime of date 37 */ 38 this.xSelect = function(o_id) { 39 if (bookingConfigs['deny'] === 0) { 40 flUtil.loadStyle(rlConfig.tpl_base + 'components/popup/popup.css'); 41 flUtil.loadScript(rlConfig.tpl_base + 'components/popup/_popup.js', function() { 42 let $loginForm = $('#login_modal_source > *').clone(); 43 $loginForm.find('.caption_padding').hide(); 44 45 $('body').popup({ 46 click : false, 47 content: $loginForm, 48 caption: lang.booking_login_popup_title, 49 width : 300, 50 onShow : function ($popup) { 51 // Prevent closing the popup by click on label with checkbox 52 if ($popup.find('.remember-me')) { 53 $popup.find('input#css_INPUT_1').attr('id', 'css_INPUT_99999'); 54 $popup.find('label[for="css_INPUT_1"]').attr('for', 'css_INPUT_99999'); 55 } 56 } 57 }); 58 }); 59 60 return false; 61 } 62 63 var result, start_book, end_book, mass_bind_checkin; 64 65 if (bookingConfigs.Booking_type === 'time_range') { 66 // first selection 67 if (!bookingConfigs['s_id']) { 68 if ($(bookingConfigs['day_prefix'] + o_id).hasClass('booked')) { 69 self.errorShow(lang['booked_day_text']); 70 } else if ($(bookingConfigs['day_prefix'] + o_id).hasClass('closed')) { 71 self.errorShow(lang['closed_day_text']); 72 } else { 73 mass_bind_checkin = bookingConfigs.bind_checkin !== '' 74 ? bookingConfigs['bind_checkin'].split(',') 75 : false; 76 77 if (mass_bind_checkin && !in_array(self.getDateByTimeZone(o_id, 'ddd'), mass_bind_checkin)) { 78 self.errorShow(lang.check_in_only_text.replace('{days}', bookingConfigs.bindCheckinLocale)); 79 } else { 80 bookingConfigs.s_id = o_id; 81 start_book = self.getDateByTimeZone(o_id); 82 bookingConfigs.db_start = Number(o_id); 83 self.bUpdate(o_id); 84 85 if (rlPageInfo.controller === 'booking_requests' && bookingConfigs.request_id) { 86 bookingConfigs.start_date_value = start_book; 87 self.stepsHandler('update_period', 'update'); 88 } else { 89 self.stepsHandler( 90 'details', 91 'show', 92 { 93 start_book: start_book, 94 total_days: 1, 95 } 96 ); 97 } 98 99 self.updateEscortAvailabilityData(); 100 101 // Reset fields in booking details 102 var $type_obj = $('[name="escort_rates"]'); 103 $type_obj.find('option:selected').removeAttr('selected'); 104 $type_obj.find('option[value="-1"]').attr('selected', 'selected'); 105 $type_obj.trigger('change'); 106 107 var $time_obj = $('[name="f[booking_check_out]"]'); 108 self.selectFirstActiveOption($time_obj); 109 $time_obj.addClass('disabled').attr('disabled', 'disabled'); 110 111 var $duration_obj = $('[name="escort_duration"]'); 112 self.selectFirstActiveOption($duration_obj); 113 $duration_obj.addClass('disabled').attr('disabled', 'disabled'); 114 // Reset escort fields in booking details end 115 116 // Update date in booking details 117 var new_date = self.getDateByTimeZone(bookingConfigs['s_id']); 118 119 var html = '<a id="change_date_button" href="javascript:void(0)">'; 120 html += lang['booking_button_select_date'] + '</a>'; 121 122 $('div.field.start_date').html('<b>' + new_date + '</b>' + html); 123 124 $('#change_date_button').click(function(){ 125 self.escortChangeDate(); 126 }); 127 128 $('#modal_block div.inner > div.close').trigger('click'); 129 } 130 } 131 } else { 132 bookingConfigs['s_id'] = 0; 133 134 if (rlPageInfo['controller'] !== 'booking_order') { 135 $('#booking_message_obj').fadeOut('fast'); 136 } 137 138 self.book_color(true); 139 } 140 } else { 141 // period selected 142 if (bookingConfigs['first'] === 1) { 143 if (o_id === bookingConfigs['s_id']) { 144 self.book_color(true); 145 bookingConfigs['first'] = 0; 146 return; 147 } 148 149 var mass_bind_checkout = bookingConfigs['bind_checkout'] !== '' 150 ? bookingConfigs['bind_checkout'].split(',') 151 : false;
152 153 if (mass_bind_checkout 154 && ((!in_array(self.getDateByTimeZone(o_id, 'ddd'), mass_bind_checkout) && o_id > bookingConfigs['s_id']) 155 || (!in_array(self.getDateByTimeZone(bookingConfigs['s_id'], 'ddd'), mass_bind_checkout) && o_id < bookingConfigs['s_id'])) 156 ) { 157 self.errorShow(lang.check_out_only_text.replace('{days}', bookingConfigs.bindCheckoutLocale)); 158 } else { 159 let daysInPeriod = self.getCountDaysBetween2Timestamps(o_id, bookingConfigs.s_id); 160 161 if (daysInPeriod < bookingConfigs.min_bl && bookingConfigs.min_bl > 0) { 162 self.errorShow( 163 lang.min_bl_text.replace( 164 '{nights}', 165 '<span class="daySize">' + parseInt(bookingConfigs.min_bl) + '</span>' 166 ) 167 ) 168 } else if (daysInPeriod > bookingConfigs['max_bl'] && bookingConfigs['max_bl'] > 0) { 169 self.errorShow( 170 lang.max_bl_text.replace( 171 '{nights}', 172 '<span class="daySize">' + parseInt(bookingConfigs.max_bl) + '</span>' 173 ) 174 ) 175 } else { 176 if (bookingConfigs['s_id'] > o_id) { 177 result = self.bUpdate(o_id, bookingConfigs['s_id'], '-'); 178 start_book = self.getDateByTimeZone(o_id); 179 end_book = self.getDateByTimeZone(bookingConfigs['s_id']); 180 181 bookingConfigs['db_start'] = o_id; 182 bookingConfigs['db_end'] = bookingConfigs['s_id']; 183 } else { 184 result = self.bUpdate(o_id, bookingConfigs['s_id'], '+'); 185 start_book = self.getDateByTimeZone(bookingConfigs['s_id']); 186 end_book = self.getDateByTimeZone(o_id); 187 188 bookingConfigs['db_start'] = bookingConfigs['s_id']; 189 bookingConfigs['db_end'] = o_id; 190 } 191 192 if (result === true) { 193 if (rlPageInfo.controller === 'booking_requests' && bookingConfigs['request_id']) { 194 bookingConfigs['start_date_value'] = start_book; 195 bookingConfigs['end_date_value'] = end_book; 196 197 self.stepsHandler('update_period', 'update'); 198 } else { 199 self.stepsHandler( 200 'details', 201 'show', 202 { 203 start_book : start_book, 204 end_book : end_book, 205 total_days : daysInPeriod, 206 } 207 ); 208 } 209 } else { 210 self.errorShow(lang['already_booked_text']); 211 } 212 } 213 } 214 215 bookingConfigs['first'] = 0; 216 } else { 217 if ($(bookingConfigs['day_prefix'] + o_id).hasClass('booked')) { 218 self.errorShow(lang['booked_day_text']); 219 } else if ($(bookingConfigs['day_prefix'] + o_id).hasClass('closed')) { 220 self.errorShow(lang['closed_day_text']); 221 } else { 222 mass_bind_checkin = bookingConfigs['bind_checkin'] !== '' 223 ? bookingConfigs['bind_checkin'].split(',') 224 : false; 225 226 if (mass_bind_checkin && !in_array(self.getDateByTimeZone(o_id, 'ddd'), mass_bind_checkin)) { 227 self.errorShow(lang.check_in_only_text.replace('{days}
227', bookingConfigs.bindCheckinLocale)); 228 } else { 229 if (bookingConfigs['s_id'] > 0) { 230 bookingConfigs['s_id'] = bookingConfigs['cur_id']; 231 } 232 233 self.book_color(true); 234 self.bUpdate(o_id); 235 $('#booking_message_obj').fadeOut('fast'); 236 237 if (rlPageInfo.controller === 'booking_order') { 238 $('.booking_message_clone').hide(); 239 } 240 241 bookingConfigs['first'] = 1; 242 bookingConfigs['s_id'] = o_id; 243 bookingConfigs['cur_id'] = o_id; 244 } 245 } 246 } 247 } 248 }; 249 250 /** 251 * Update colors of days on calendar 252 * @param {int} o_id 253 * @param {int} s_id 254 * @param {string} mod - Maybe "+" or "-" 255 * @param {boolean} disable_recount - Paint calendar without recount of amount 256 */ 257 this.bUpdate = function(o_id, s_id, mod, disable_recount) { 258 if (bookingConfigs.first === 1) { 259 let daysInPeriod = bookingConfigs.Booking_type === 'time_range' 260 ? 1 261 : self.getCountDaysBetween2Timestamps(o_id, s_id); 262 263 let currentDate = s_id; 264 for (let i = 0; i < daysInPeriod; i++) { 265 currentDate = mod === '+' 266 ? self.addDaysToTimestamp(currentDate) 267 : self.subtractDaysFromTimestamp(currentDate); 268 269 let $day = $(bookingConfigs.day_prefix + currentDate); 270 if ($day.hasClass('booked') || $day.hasClass('closed') || $day.hasClass('unavailable')) { 271 return false; 272 } 273 274 bookingConfigs.selected[bookingConfigs.index] = currentDate; 275 bookingConfigs.index++; 276 } 277 278 self.book_color(false, false, mod, disable_recount); 279 } else { 280 if (!disable_recount && !bookingConfigs.in_popup) { 281 $('#booking_message').html(''); 282 self.stepsHandler('fields', 'hide'); 283 } 284 285 $(bookingConfigs.day_prefix + o_id).addClass( 286 bookingConfigs.Booking_type !== 'time_range' ? 'daySelect start' : 'daySelect' 287 ); 288 bookingConfigs.selected[bookingConfigs.index] = o_id; 289 bookingConfigs.index++; 290 } 291 292 return true; 293 }; 294 295 /** 296 * Change color of selected day in calendar and count total price of selected range 297 * @param {boolean} erase - Reset of selection 298 * @param {boolean} st 299 * @param {string} mod 300 * @param {boolean} disable_recount - Paint calendar without recount of amount 301 */ 302 this.book_color = function(erase, st, mod, disable_recount) { 303 var iteration = 1; 304 var calc = 0; 305 var bDebug = ''; 306 var count_selected_days = bookingConfigs['selected'].length; 307 var count_selected_days_without_last = count_selected_days - 1; 308 var price = 0; 309 310 if (bookingConfigs['selected']) { 311 for (var id = 0; id < count_selected_days; id++) { 312 var $dayContainer = $(bookingConfigs['day_prefix'] + bookingConfigs['selected'][id]); 313 $dayContainer[erase === true ? 'removeClass' : 'addClass']('daySelect'); 314 315 // add special classes for first and last days of selection 316 if (erase) { 317 $dayContainer.removeClass('start end'); 318 } else { 319 if (id === 0) { 320 $dayContainer.addClass( 321 bookingConfigs['selected'][id + 1] > bookingConfigs['selected'][id] ? 'start' : 'end' 322 ); 323 } else if (id === count_selected_days - 1) { 324 if (bookingConfigs['selected'][id + 1]) { 325 $dayContainer.addClass( 326 bookingConfigs['selected'][id + 1] > bookingConfigs['selected'][id] ? 'end' : 'start' 327 ); 328 } else { 329 $dayContainer.addClass( 330 bookingConfigs['selected'][id - 1] < bookingConfigs['selected'][id] ? 'end' : 'start' 331 ); 332 } 333 } 334 } 335 336 if (bookingConfigs['first'] === 1 && !disable_recount) { 337 // listing rate range 338 for (var idR in bookingConfigs['usRange']) { 339 price = parseFloat(bookingConfigs['usRange'][idR][2].split('|')[0]); 340 341 if (bookingConfigs['fixed_range'] === 1) { 342 if (mod === '+') { 343 if (iteration !== count_selected_days) { 344 if (bookingConfigs['selected'][0] >= bookingConfigs['usRange'][idR][0] 345 && bookingConfigs['selected'][0] <= bookingConfigs['usRange'][idR][1] 346 ) { 347 bDebug += parseFloat(bookingConfigs['usRange'][idR][2].split('|')[0] ) + ' + '; 348 bookingConfigs['total_cost'] += price; 349 } 350 } 351 } else { 352 if (iteration !== 1) { 353 if (bookingConfigs['selected'][count_selected_days_without_last] >= bookingConfigs['usRange'][idR][0] 354 && bookingConfigs['selected'][count_selected_days_without_last] <= bookingConfigs['usRange'][idR][1] 355 ) { 356 bDebug += price + ' + '; 357 bookingConfigs['total_cost'] += price; 358 } 359 } 360 } 361 } else { 362 if (bookingConfigs['selected'][id] >= bookingConfigs['usRange'][idR][0] 363 && bookingConfigs['selected'][id] <= bookingConfigs['usRange'][idR][1] 364 ) { 365 if (mod === '+') { 366 if (iteration !== count_selected_days) { 367 bDebug += price + ' + '; 368 bookingConfigs['total_cost'] += price; 369 calc++; 370 } 371 } else { 372 if (iteration !== 1) { 373 bDebug += price + ' + '; 374 bookingConfigs['total_cost'] += price; 375 calc++; 376 } 377 } 378 } 379 } 380 } 381 } 382 iteration++; 383 } 384 385 if (bookingConfigs['first'] === 1 && !disable_recount) { 386 if (bookingConfigs['fixed_range'] === 0) { 387 bDebug += bookingConfigs['booking_debug'] 388 ? '( ' + count_selected_days_without_last + ' - ' + calc + ' ) * ' + bookingConfigs['defPrice'] 389 : ''; 390 bookingConfigs['total_cost'] += (count_selected_days_without_last - calc) * bookingConfigs['defPrice']; 391 } else { 392 if (bookingConfigs['total_cost'] === 0) { 393 bDebug += bookingConfigs['booking_debug'] 394 ? count_selected_days_without_last + ' * ' + bookingConfigs['defPrice'] 395 : ''; 396 bookingConfigs['total_cost'] += count_selected_days_without_last * bookingConfigs['defPrice']; 397 } 398 } 399 400 if (bookingConfigs['booking_debug']) { 401 console.log(bDebug); 402 } 403 bookingConfigs['total_cost'] = self.str2money(bookingConfigs['total_cost']); 404 } 405 406 if (erase === true) { 407 bookingConfigs['selected'] = []; 408 bookingConfigs['index'] = 0; 409 bookingConfigs['total_cost'] = 0; 410 } 411 412 if (st === true) { 413 if (bookingConfigs['selected'][0] !== '') { 414 $(bookingConfigs['day_prefix'] + bookingConfigs['selected'][0]).addClass('daySelect'); 415 } 416 } 417 } 418 }; 419 420 /** 421 * Change price by money format 422 * @param {string} price - Price 423 * @return {string} - Formatted price 424 */ 425 this.str2money = function(price) { 426 price = parseFloat(price); 427 428 if (!price) { 429 return false;
430 } 431 432 var price_split = price.toFixed(2).split('.'); 433 var price_int = self.strrev(price_split[0]); 434 var price_cents = (price_split[1] ? price_split[1] : '') === '00' ? '' : '.' + price_split[1]; 435 var len = price_int.length; 436 var val = ''; 437 438 for (var i = 0; i <= len; i++) { 439 val += price_int.charAt(i); 440 if (((i + 1) % 3 === 0) && (i + 1 < len)) { 441 val += bookingConfigs['price_delimiter']; 442 } 443 } 444 445 val = self.strrev(val) + price_cents; 446 447 return val; 448 }; 449 450 this.strrev = function(string) { 451 string = string + ''; 452 453 var grapheme_extend = /(.)([\uDC00-\uDFFF\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065E\u0670\u06D6-\u06DC\u06DE-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0901-\u0903\u093C\u093E-\u094D\u0951-\u0954\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C82\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D02\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F90-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B6-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAA\u1C24-\u1C37\u1DC0-\u1DE6\u1DFE\u1DFF\u20D0-\u20F0\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA67C\uA67D\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA926-\uA92D\uA947-\uA953\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uFB1E\uFE00-\uFE0F\uFE20-\uFE26])/g; 454 string = string.replace(grapheme_extend, '$2$1'); // Temporarily reverse 455 456 return string.split('').reverse().join(''); 457 }; 458 459 /** 460 * Paint booked and closed days on the calendar 461 */ 462 this.paintUserBook = function() { 463 for (id in bookingConfigs.usBook) { 464 var pr = ''; 465 var status_b = bookingConfigs.usBook[id][0]; 466 var st_b = bookingConfigs.usBook[id][1]; 467 var en_b = bookingConfigs.usBook[id][2]; 468 let daysInPeriod = bookingConfigs.Booking_type === 'time_range' 469 ? 1 470 : self.getCountDaysBetween2Timestamps(en_b, st_b); 471 472 var currentDate = st_b; 473 var req_id = Number(bookingConfigs.usBook[id]['3']); 474 var current_req_id = Number(bookingConfigs.request_id); 475 var $dayContainer = null; 476 477 // don't draw days of current request 478 if (!current_req_id || (current_req_id !== req_id)) { 479 for (let i = 0; i <= daysInPeriod; i++) { 480 if (i !== 0) { 481 currentDate = self.addDaysToTimestamp(currentDate); 482 } 483 484 pr = status_b === 'process' ? 'pr_' : ''; 485 $dayContainer = $(bookingConfigs.day_prefix + currentDate); 486 487 if (i === 0) { 488 if (bookingConfigs.Booking_type === 'time_range') { 489 if ($dayContainer.hasClass('fully-booked')) { 490 $dayContainer.addClass('booked').removeAttr('title'); 491 } else if (!$dayContainer.hasClass('partially-booked')) { 492 $dayContainer.addClass('partially-booked'); 493 $dayContainer.append( 494 $('<img>').attr({ 495 src: rlConfig.plugins_url + 'booking/static/hour.png', 496 alt: '' 497 }) 498 ); 499 } 500 501 if (bookingConfigs['usBook'][id]['4'] && rlPageInfo.controller !== 'booking_requests') { 502 $dayContainer.addClass('own-request'); 503 } 504 } else { 505 $dayContainer.addClass(pr + 'checkin'); 506 507 if (bookingConfigs['usBook'][id]['4'] && rlPageInfo.controller !== 'booking_requests') { 508 $dayContainer.addClass(pr + 'checkin_own'); 509 } 510 511 if ($dayContainer.hasClass('pr_checkout')) { 512 $dayContainer.addClass('booked').removeAttr('title'); 513 } 514 515 if ($dayContainer.hasClass(pr + 'checkout') || $dayContainer.hasClass('checkout')) { 516 $dayContainer.addClass('booked').removeAttr('title'); 517 } 518 } 519 } else if (i === daysInPeriod) { 520 if (bookingConfigs.Booking_type !== 'time_range') { 521 $dayContainer.addClass(pr + 'checkout'); 522 523 if (bookingConfigs['usBook'][id]['4'] && rlPageInfo.controller !== 'booking_requests') { 524 $dayContainer.addClass(pr + 'checkout_own'); 525 } 526 527 if ($dayContainer.hasClass(pr + 'checkin') || $dayContainer.hasClass('checkin')) { 528 $dayContainer.addClass('booked').removeAttr('title'); 529 } 530 } 531 } else { 532 $dayContainer.addClass('booked').removeAttr('title'); 533 } 534 535 if (bookingConfigs['usBook'][id]['4'] 536 && rlPageInfo.controller !== 'booking_requests' 537 && bookingConfigs.Booking_type !== 'time_range' 538 ) { 539 $dayContainer.addClass('own-request'); 540 } 541 } 542 } else { 543 // highlight start date of current request 544 var $startDay = $(bookingConfigs['day_prefix'] + st_b); 545 if (st_b && rlPageInfo.controller === 'booking_requests' && $startDay.hasClass('current-request')) { 546 $startDay.addClass('start'); 547 } 548 549 // highlight end date of current request 550 var $endDay = $(bookingConfigs['day_prefix'] + en_b); 551 if (en_b && rlPageInfo.controller === 'booking_requests' && $endDay.hasClass('current-request')) { 552 $(bookingConfigs['day_prefix'] + en_b).addClass('end'); 553 } 554 } 555 } 556 557 // Fill closed days 558 for (let cd in bookingConfigs.closeRange) { 559 let st_close = bookingConfigs.closeRange[cd][0]; 560 let end_close = bookingConfigs.closeRange[cd][1]; 561 let daysInPeriod = self.getCountDaysBetween2Timestamps(end_close, st_close); 562 let currentDate = st_close; 563 564 for (let j = 0; j <= daysInPeriod; j++) { 565 if (j !== 0) { 566 currentDate = self.addDaysToTimestamp(currentDate); 567 } 568 569 $(bookingConfigs.day_prefix + currentDate).removeClass().addClass('closed').removeAttr('title'); 570 } 571 } 572 }; 573 574 /** 575 * Change dates in calendar | First step 576 * @param {string} mode - Next or previous month 577 */ 578 this.changeDates = function(mode) { 579 self.booking_mask('set'); 580 self.getDates(bookingConfigs['listing_id'], mode); 581 }; 582 583 /** 584 * Adding/Removing mask with "loading" to calendar 585 * @param {string} mode - Detect adding or removing 586 */ 587 this.booking_mask = function(mode) { 588 if (mode === 'set') {
589 $('#booking_calendar').addClass('loading'); 590 } else if (mode === 'reset') { 591 $('#booking_calendar').removeClass('loading'); 592 } 593 }; 594 595 /** 596 * Accepting or Rejecting booking request by owner of listing 597 * @param {string} action - Some of action 598 * @param {int} require_id - ID of request 599 */ 600 this.bookingRequestHandler = function(action, require_id) { 601 if (action === 'accept') { 602 $('#accept_btn').val(lang['loading']); 603 } else if (action === 'refuse') { 604 $('#refuse_btn').val(lang['loading']); 605 } 606 607 var message = CKEDITOR.instances.textarea_answer.getData(); 608 609 $('#accept_btn,#refuse_btn').addClass('disabled').attr('disabled', true); 610 $('.cancel').fadeOut('fast'); 611 $('#refuse_btn').after('<span>' + lang['booking_refuse'] + '</span>'); 612 613 // get updated checkIn/checkOut time values if owner changed it 614 var checkin_time = bookingConfigs.Booking_type === 'time_range' 615 ? bookingConfigs.escort_type_service 616 : bookingConfigs.check_in; 617 618 var checkout_time = bookingConfigs.Booking_type === 'time_range' 619 ? bookingConfigs.escort_time_service 620 : bookingConfigs.check_out; 621 622 var request = { 623 mode: 'bookingRequestHandler', 624 item: { 625 ID : require_id, 626 action : action, 627 message : message ? message : '', 628 data : { 629 db_start : bookingConfigs.db_start, 630 db_end : bookingConfigs.Booking_type === 'time_range' 631 ? bookingConfigs.escort_duration 632 : bookingConfigs.db_end, 633 total_cost : bookingConfigs.total_cost, 634 checkin_time : checkin_time, 635 checkout_time : checkout_time, 636 period_updated : bookingConfigs.period_updated 637 } 638 }, 639 lang: rlLang 640 }; 641 642 $.post( 643 rlConfig.ajax_url, 644 request, 645 function(response){ 646 if (response.status === 'OK') { 647 $('#owner_actions').fadeOut('fast'); 648 $('#change_period').fadeOut('slow', function(){ $(this).remove() }); 649 $('.current_dates').removeClass('current_dates'); 650 651 if (action === 'accept') { 652 $('#owRes').html(lang.booking_accepted); 653 } else if (action === 'refuse') { 654 $('#owRes').html(lang.booking_refused); 655 } 656 657 if (bookingConfigs.Booking_type === 'time_range') { 658 $('#change_date_button').addClass('hide'); 659 660 if (bookingConfigs['period_updated']) { 661 $('div.field.type').html($('[name="escort_rates"] option:selected').text()); 662 $('div.field.time').html($('[name="f[booking_check_out]"] option:selected').text()); 663 664 var duration = ''; 665 var $duraionObj = $('[name="escort_duration"] option:selected'); 666 667 if (parseInt($duraionObj.val()) > 0) { 668 duration = $duraionObj.text(); 669 $('div.field.duration').html(duration); 670 } else { 671 $('div.field.duration').closest('div.table-cell').addClass('hide'); 672 } 673 } 674 } 675 676 // update calendar 677 bookingConfigs['request_id'] = null; 678 self.getDates(bookingConfigs.listing_id); 679 680 printMessage('notice', response.data); 681 } else { 682 printMessage('error', response.message); 683 } 684 }, 685 'json' 686 ); 687 }; 688 689 /** 690 * Remove request from page 691 * @param {int} id - ID of request 692 * @param {string} redirect - Custom redirect to prev page if page have pagination 693 */ 694 this.removeRequest = function(id, redirect) { 695 if (!id) { 696 return false;
697 } 698 699 $(this).val(lang['loading']); 700 701 var request = {mode: 'bookingRemoveRequest', item: id, lang: rlLang}; 702 703 $.post(rlConfig.ajax_url, request, function(response){ 704 $('#modal_block div.close').trigger('click'); 705 if (response.status === 'OK') { 706 $('#item_request_' + id).fadeOut('fast', function() { 707 $('#item_request_' + id).remove(); 708 709 // hide table if table is empty 710 var parent = false; 711 if ($('#area_requests').length || $('#area_booking').length) { 712 if ($('#area_requests').length && $('#area_requests .list-table > .row').length <= 0) { 713 parent = $('#area_requests'); 714 } 715 if ($('#area_booking').length && $('#area_booking .list-table > .row').length <= 0) { 716 parent = $('#area_booking'); 717 } 718 } 719 720 if ($('#listings').length) { 721 if ($('#listings article.item').length <= 0) { 722 parent = $('#listings'); 723 } 724 } 725 726 if (parent) { 727 if ($(parent).find('.list-table').length > 0) { 728 $(parent).find('.list-table').fadeOut('fast'); 729 } 730 731 // reservation page 732 if ($('#listings').length > 0) { 733 $(parent).parent().html('<div class="text-notice">' + lang['booking_no_reservations'] + '</div>'); 734 735 // redirect to previos page 736 if (redirect) { 737 window.location.href = prev_page; 738 } 739 } 740 // other pages 741 else { 742 $(parent).html('<div class="text-notice">' + lang['booking_no_requests'] + '</div>'); 743 } 744 } 745 }); 746 747 setTimeout(function(){ printMessage('notice', response.data) }, 500); 748 } else { 749 setTimeout(function(){ printMessage('error', response.message) }, 500); 750 } 751 }, 'json'); 752 }; 753 754 /** 755 * Window with confirmation of removing request 756 * @param {string} redirect - Custom redirect if page have pagination 757 */ 758 this.requestRemoveHandler = function(redirect) { 759 $('.remove_request').each(function(){ 760 $(this).flModal({ 761 caption: lang['warning'], 762 content: lang['booking_remove_notice'], 763 prompt : "booking.removeRequest(" + $(this).attr('id') + ", '" + redirect + "')", 764 width : 'auto', 765 height : 'auto' 766 }); 767 }); 768 }; 769 770 /** 771 * Adding new rate range to list 772 */ 773 this.addRateRange = function() { 774 var lCurrency = $('select[name="f[price][currency]"] option:selected').text(); 775 var field = '<div class="row tmp" id="add_rate_' + bookingConfigs['current_field'] + '">'; 776 field += '<div data-caption="' + lang['from'] + '">'; 777 field += '<input class="w120" type="text" name="b[' + bookingConfigs['current_field'] + '][from]" '; 778 field += 'id="brr_from_' + bookingConfigs['current_field'] + '" value="" autocomplete="off" /></div>'; 779 field += '<div data-caption="' + lang['to'] + '">'; 780 field += '<input class="w120" type="text" name="b[' + bookingConfigs['current_field'] + '][to]" '; 781 field += 'id="brr_to_' + bookingConfigs['current_field'] + '" value="" autocomplete="off" /></div>'; 782 field += '<div data-caption="' + lang['price'] + '">'; 783 field += bookingConfigs.system_currency_position === 'before' ? lCurrency + ' ' : ''; 784 field += '<input type="text" class="numeric w120 price" name="b[' + bookingConfigs['current_field'] + '][price]" '; 785 field += 'id="price_' + bookingConfigs['current_field'] + '" value="" />'; 786 field += bookingConfigs.system_currency_position === 'after' ? ' ' + lCurrency : ''; 787 field += '<img class="qtip booking_qtip" alt="" title="' + lang['booking_close_rate_range_notice']; 788 field += '" id="rate_desc_' + bookingConfigs['current_field'] + '" src="'; 789 field += bookingConfigs['src_delete_img'] + '" />' + '</div>'; 790 791 /* description */ 792 field += '<div data-caption="' + lang.description + '" class="rate-ranges-description">'; 793 field += '<a href="javascript:void(0)" onclick="booking.addDesc(' + bookingConfigs['current_field'] + ')">'; 794 field += lang.description + '</a>'; 795 field += '<textarea class="hide" id="save_desc_' + bookingConfigs['current_field'] + '" '; 796 field += 'name="b[' + bookingConfigs['current_field'] +'][desc]" cols="30" rows="2"></textarea>'; 797 field += '</div>'; 798 /* description end */ 799 800 field += '<div data-caption="' + lang['actions'] + '" class="rate-ranges-actions">'; 801 field += '<img class="remove" onclick="booking.removeRate(' + bookingConfigs['current_field'] + ')" '; 802 field += 'title="' + lang['delete'] + '" alt="' + lang['delete'] + '" src="'; 803 field += bookingConfigs['src_delete_img'] + '" /></div>'; 804 field += '</div>'; 805 806 $('#booking_rate_ranges_list > div.list-table #rrange_regular').before(field); 807 808 self.rateRangeFieldsHandler(bookingConfigs['current_field']); 809 setTimeout(function(){ bookingConfigs['current_field']++ }, 200); 810 }; 811 812 /** 813 * Apply handlers to new rate range fields 814 * @param {int} id 815 */ 816 this.rateRangeFieldsHandler = function(id) { 817 $('.numeric').numeric(); 818 819 self.qtipInit(true); 820 821 var rate_ranges_selector = ''; 822 823 if (id) { 824 rate_ranges_selector = '#brr_from_' + id + ',#brr_to_' + id; 825 } else { 826 for (var i = 1; i < parseInt(bookingConfigs['current_field']); i++) { 827 rate_ranges_selector = rate_ranges_selector 828 ? rate_ranges_selector + ', #brr_from_' + i + ', #brr_to_' + i 829 : '#brr_from_' + i + ', #brr_to_' + i; 830 } 831 } 832 833 if (rate_ranges_selector) { 834 setTimeout(function(){ 835 var dp_regional = bookingConfigs['rlLang'] === 'en' ? 'en-GB' : bookingConfigs['rlLang']; 836 var dates = $(rate_ranges_selector) 837 .datepicker('destroy') 838 .datepicker({ 839 showOn: 'focus', 840 dateFormat: 'dd-mm-yy', 841 minDate: self.getMinRateDate(), 842 onSelect: function(selectedDate) { 843 if (this.id.indexOf('from') !== -1) { 844 var instance = $(this).data("datepicker"), 845 date = $.datepicker.parseDate(instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings); 846 var to_date = date.getDate() + parseInt(bookingConfigs['booking_min_book_day']); 847 date.setDate(to_date); 848 dates.not(this).datepicker("option", "minDate", date); 849 850 var mMonth = date.getMonth() + 1; 851 var mDay = date.getDate(); 852 mMonth = mMonth < 10 ? '0'+ mMonth : mMonth; 853 mDay = mDay < 10 ? '0'+ mDay : mDay; 854 855 dates.not(this).val(mDay + '-' + mMonth + '-' + date.getFullYear()); 856 } 857 } 858 }) 859 .datepicker($.datepicker.regional[dp_regional]); 860 }, 100); 861 } 862 }; 863 864 /** 865 * Get minimum date for new rate range (by exist ranges) 866 */ 867 this.getMinRateDate = function() { 868 var default_date = new Date();
869 var targetTimeOffset = bookingConfigs['bookingTimeOffset'] * 60; // desired time zone 870 default_date.setMinutes(default_date.getMinutes() + default_date.getTimezoneOffset() + targetTimeOffset); 871 872 var exist_min_date = ''; 873 var previous_field = bookingConfigs['current_field'] - 1; 874 var min_date = bookingConfigs['current_field'] > 1 && !bookingConfigs['post_rate_ranges'] 875 ? ($('[name="b[' + previous_field + '][to]"]').length 876 ? $('[name="b[' + previous_field + '][to]"]').val() 877 : $('#rrange_' + previous_field + ' div[data-caption="to"]').text()) 878 : default_date; 879 880 /* find value from exist rate ranges (if new created rate is empty) */ 881 if (!min_date) { 882 for (var i = previous_field; i > 0; i--) { 883 if ($('#rrange_' + i + ' div[data-caption="to"]').length 884 && $('#rrange_' + i + ' div[data-caption="to"]').text() 885 ) { 886 exist_min_date = $('#rrange_' + i + ' div[data-caption="to"]').text(); 887 break; 888 } 889 } 890 891 /* find last filled value in tmp rate ranges */ 892 if (!min_date) { 893 for (var i = previous_field; i > 0; i--) { 894 if ($('[name="b[' + i + '][to]"]').length && $('[name="b[' + i + '][to]"]').val()) { 895 min_date = $('[name="b[' + i + '][to]"]').val(); 896 break; 897 } 898 } 899 } 900 } 901 902 if (exist_min_date || min_date) { 903 min_date = bookingConfigs['current_field'] > 1 && !bookingConfigs['post_rate_ranges'] 904 ? new Date(exist_min_date 905 ? exist_min_date.replace(/(\d{2})\-(\d{2})\-(\d{4})/,'$3-$2-$1') 906 : min_date.replace(/(\d{2})\-(\d{2})\-(\d{4})/,'$3-$2-$1')) 907 : min_date; 908 909 /* allow to create new rate from next day only */ 910 if (bookingConfigs['current_field'] > 1 ) { 911 min_date.setDate(min_date.getDate() + 1); 912 } 913 } 914 915 return min_date ? min_date : default_date; 916 }; 917 918 /** 919 * Deleting rate range row from list 920 * @param {int} id - ID of row with rate 921 * @param {bool} rate_details - Detect exist rate or temp 922 */ 923 this.removeRate = function(id, rate_details) { 924 if (!id) { 925 return false; 926 } 927 928 if (rate_details) { 929 $(this).val(lang['loading']); 930 931 var request = { 932 mode: 'bookingRemoveRateRange', 933 item: { 934 rate_id: id, 935 listing_id: bookingConfigs['listing_id'] 936 }, 937 lang: typeof rlLang !== 'undefined' ? rlLang : bookingConfigs.rlLang 938 }; 939 940 $.post(rlConfig.ajax_url, request, function(response){ 941 if (bookingConfigs['isAdmin']) { 942 self.closeApModal(); 943 } else { 944 $('#modal_block div.close').trigger('click'); 945 } 946 947 if (response.status === 'OK') { 948 $('#rrange_' + id).fadeOut('fast', function(){ $(this).remove() }); 949 bookingConfigs['current_field']--; 950 951 if (!bookingConfigs['isAdmin']) { 952 setTimeout(function(){ printMessage('notice', response.data) }, 500); 953 } 954 } else { 955 setTimeout(function(){ printMessage('error', response.message) }, 500); 956 } 957 }, 'json'); 958 } else { 959 $('#add_rate_' + id).fadeOut('fast', function(){ $(this).remove() }); 960 bookingConfigs['current_field']--; 961 } 962 }; 963 964 /** 965 * Window with confirmation of removing rate 966 */ 967 this.confirmRemoveRateHandler = function() { 968 var caption = lang['warning']; 969 var confirmation_phrase = lang['booking_remove_confirm']; 970 971 $('.remove_rate').each(function(){ 972 if (bookingConfigs['isAdmin']) { 973 $(this).flModal({ 974 width: 450, 975 height: 'auto', 976 caption: caption, 977 content: confirmation_phrase + '<div class="prompt admin"><input name="remove_confirmation" onclick="booking.removeRate(' + $(this).attr('id') + ', true)" type="button" value="' + lang['booking_ok'] + '"><a class="close" href="javascript:void(0)" onclick="self.closeApModal()">' + lang['cancel'] + '</a></div>' 978 }); 979 } else { 980 $(this).flModal({ 981 caption: caption, 982 content: confirmation_phrase, 983 prompt : "booking.removeRate(" + $(this).attr('id') + ", true)", 984 width : 'auto', 985 height : 'auto' 986 }); 987 } 988 }); 989 }; 990 991 /** 992 * Close modal window 993 */ 994 this.closeApModal = function() { 995 $('.modal-window > div:first > span:last').trigger('click'); 996 }; 997 998 /** 999 * Show/Hide section field group 1000 */ 1001 this.bookingSectionHandler = function() { 1002 if (bookingConfigs.booking_available) { 1003 if (self.$bookingRadioButton.length > 0) { 1004 /* show for all booking type except Escort (time_ranges) */ 1005 if (bookingConfigs.booking_type && bookingConfigs.booking_type !== 'time_range') { 1006 /* check in field */ 1007 var checkin = '<' + self.rateParentTag + ' id="booking_checkin" class="submit-cell clearfix hide">'; 1008 checkin += '<' + self.rateChildTag + ' class="name">' + lang['booking_checkin'] + '</' + self.rateChildTag + '>'; 1009 checkin += '<'+ self.rateChildTag + ' class="field" id="booking_checkin_obj"></' + self.rateChildTag + '>'; 1010 checkin += '</' + self.rateParentTag + '>'; 1011 1012 self.$bookingSection.after(checkin); 1013 self.$checkInSection.clone().appendTo('#booking_checkin_obj').fadeIn('slow'); 1014 1015 /* check out field */ 1016 var checkout = '<' + self.rateParentTag + ' id="booking_checkout" class="submit-cell clearfix hide">'; 1017 checkout += '<' + self.rateChildTag + ' class="name">' + lang['booking_checkout'] + '</' + self.rateChildTag + '>'; 1018 checkout += '<' + self.rateChildTag + ' class="field" id="booking_checkout_obj"></' + self.rateChildTag + '>'; 1019 checkout += '</' + self.rateParentTag + '>'; 1020 1021 $('#booking_checkin').after(checkout); 1022 self.$checkOutSection.clone().appendTo('#booking_checkout_obj').fadeIn('slow'); 1023 1024 /* rate ranges fields */ 1025 var rateRanges = '<' + self.rateParentTag + ' id="booking_rate_ranges" class="submit-cell clearfix hide">'; 1026 rateRanges += '<' + self.rateChildTag + ' class="name">' + lang['booking_rate_range'] + '</' + self.rateChildTag + '>'; 1027 rateRanges += '<' + self.rateChildTag + ' class="field" id="booking_rate_ranges_obj"></' + self.rateChildTag + '>'; 1028 rateRanges += '</' + self.rateParentTag + '>'; 1029 1030 if (bookingConfigs.booking_type && bookingConfigs.booking_type !== 'time_range') { 1031 $('#booking_checkout').after(rateRanges); 1032 } else { 1033 self.$bookingSection.after(rateRanges); 1034 } 1035 1036 $('#booking_rate_ranges_list').appendTo('#booking_rate_ranges_obj').fadeIn('slow'); 1037 1038 if ($('[name="f[booking_module]"][value="1"]').is(':checked')) { 1039 $('#booking_rate_ranges, #booking_checkin, #booking_checkout').fadeIn('normal'); 1040 } 1041 } else if (bookingConfigs.booking_type === 'time_range' && !bookingConfigs.is_escort) { 1042 var $availability = $('#availability'), $rates = $('#rates'); 1043 1044 $availability.appendTo(self.$bookingSection.parent()); 1045 $rates.appendTo(self.$bookingSection.parent()); 1046 1047 if (self.$bookingRadioButton.filter(':checked').val() === '1') { 1048 $availability.removeClass('hide'); 1049 $rates.removeClass('hide'); 1050 } 1051 } 1052 1053 self.$bookingRadioButton.off('click').click(function() { 1054 if ($(this).is('[value="1"]:checked')) { 1055 $('#booking_checkin').fadeIn('fast'); 1056 $('#booking_checkout').fadeIn('fast'); 1057 $('#booking_rate_ranges').fadeIn('normal', self.loadingRangesHandler); 1058 1059 if (bookingConfigs.booking_type === 'time_range' && !bookingConfigs.is_escort) { 1060 $availability.removeClass('hide'); 1061 $rates.removeClass('hide'); 1062 } 1063 } else { 1064 $('#booking_checkin').fadeOut('normal'); 1065 $('#booking_checkout').fadeOut('normal'); 1066 $('#booking_rate_ranges').fadeOut('normal', 1067 function(){ 1068 $('#booking_rate_ranges_list > div.list-table div.row').remove(); 1069 } 1070 ); 1071 1072 if (bookingConfigs.booking_type === 'time_range' && !bookingConfigs.is_escort) { 1073 $availability.addClass('hide'); 1074 $rates.addClass('hide'); 1075 } 1076 } 1077 }); 1078 1079 self.$bookingRadioButton.closest('form').on('submit', function(event) { 1080 if (!self.$bookingRadioButton.is('[value="1"]:checked')) { 1081 return true; 1082 } 1083 1084 var submit = true, 1085 emptyFields = [], 1086 errorMessage = lang.booking_addEditListingErrorEmptyRanges; 1087 1088 if (bookingConfigs.booking_type === 'time_range' && !bookingConfigs.is_escort) { 1089 var emptyAvailabilityFields = 0, emptyAvailabilityIDs = []; 1090 $availability.find('select').each(function () { 1091 if ($(this).val() === '0') { 1092 emptyAvailabilityFields++; 1093 emptyAvailabilityIDs.push('#' + $(this).attr('id')) 1094 } 1095 }); 1096 1097 if (emptyAvailabilityFields === 14) { 1098 submit = false;
1099 emptyFields = emptyAvailabilityIDs; 1100 errorMessage = lang.booking_emptyHourlyRanges; 1101 } else if (emptyAvailabilityFields > 0) { 1102 let fromAvailability, toAvailability, i; 1103 emptyAvailabilityIDs = []; 1104 1105 for (i = 1; i <= 7; i++) { 1106 fromAvailability = $('#hourly-availability-from-' + i).val(); 1107 toAvailability = $('#hourly-availability-to-' + i).val(); 1108 1109 if (fromAvailability !== '0' && toAvailability === '0') { 1110 emptyAvailabilityIDs.push('#hourly-availability-to-' + i); 1111 } else if (fromAvailability === '0' && toAvailability !== '0') { 1112 emptyAvailabilityIDs.push('#hourly-availability-from-' + i); 1113 } 1114 } 1115 1116 if (emptyAvailabilityIDs.length > 0) { 1117 submit = false; 1118 emptyFields = emptyAvailabilityIDs; 1119 errorMessage = lang.booking_emptyHourlyRanges; 1120 } 1121 } 1122 1123 let emptyRatesIDs = []; 1124 $('.rates-field-container .rates').each(function () { 1125 $(this).find('input').each(function () { 1126 if ($(this).val() === '') { 1127 emptyRatesIDs.push('#' + $(this).attr('id')); 1128 } 1129 }); 1130 1131 if (!$(this).find('select.hourly-rates-duration').val()) { 1132 emptyRatesIDs.push('#' + $(this).find('select.hourly-rates-duration').attr('id')); 1133 } 1134 }); 1135 1136 if (emptyRatesIDs.length > 0) { 1137 submit = false; 1138 emptyFields = emptyFields.concat(emptyRatesIDs); 1139 errorMessage = lang.booking_emptyHourlyRanges; 1140 } 1141 } else { 1142 $('[id^=add_rate_] input').each(function() { 1143 if ($(this).val() === '') { 1144 emptyFields.push('#' + $(this).attr('id')); 1145 submit = false; 1146 } 1147 }); 1148 } 1149 1150 if (!submit) { 1151 event.preventDefault(); 1152 let $submitButton = self.$bookingRadioButton.closest('form').find('[type="submit"]'); 1153 if ($submitButton.prop('disabled')) { 1154 $submitButton.val(lang.add_listing).prop('disabled', false).removeClass('disabled'); 1155 } 1156 1157 printMessage('error', errorMessage, emptyFields); 1158 flynax.slideTo(bookingConfigs.isAdmin ? '#system_message' : '#fs_booking_rates'); 1159 self.rateRangeFieldsHandler(); 1160 1161 // Restore phrase in button and removing "disabled" class 1162 if (typeof manageListing === 'object' && typeof manageListing.enableButton === 'function') { 1163 manageListing.enableButton(); 1164 } 1165 } 1166 1167 return submit; 1168 }); 1169 } 1170 1171 self.recountRegularPrice(true); 1172 self.confirmRemoveRateHandler(); 1173 self.qtipInit(); 1174 1175 $('.add_rate_range').click(function(){ 1176 self.addRateRange(); 1177 }); 1178 1179 if (bookingConfigs['post_rate_ranges']) { 1180 self.rateRangeFieldsHandler(); 1181 } 1182 } else { 1183 $('div#fs_booking_rates').remove(); 1184 } 1185 }; 1186 1187 /** 1188 * Add new row with data of hourly rate 1189 * @since 3.2.0 1190 */ 1191 this.addNewHourlyRate = function () { 1192 var $timeSelector = $('<select>', { 1193 name : 'f[booking_rates][' + self.rateIndex + '][time]', 1194 id : 'hourly-rates-duration-' + self.rateIndex, 1195 class: 'hourly-rates-duration', 1196 }), 1197 timeValue = '', 1198 hoursValue = ''; 1199 1200 $timeSelector.append($('<option>').val('').text(lang.booking_rate_selector)); 1201 1202 for (i = 1; i <= 24; i++) { 1203 if (i > 1) { 1204 hoursValue = i % 2 ? i / 2 : i / 2; 1205 timeValue = i % 2 ? parseInt(hoursValue) + ':30' : hoursValue + ':00'; 1206 1207 if (hoursValue <= 9.5) { 1208 timeValue = '0' + timeValue; 1209 } 1210 } else { 1211 hoursValue = 0.5; 1212 timeValue = '00:30'; 1213 } 1214 1215 $timeSelector.append( 1216 $('<option>').val(hoursValue).text(timeValue) 1217 ) 1218 } 1219 1220 var $currency = $('<select>').attr({ 1221 name: 'f[booking_rates][' + self.rateIndex + '][currency]', 1222 id : 'hourly-rate-currency-' + self.rateIndex, 1223 }); 1224
1225 bookingConfigs.currencies.forEach(function (currency) { 1226 $currency.append( 1227 $('<option>').val(currency.key).text(currency.value) 1228 ) 1229 }); 1230 1231 $('.rates-field-container .rates:last').after( 1232 $('<div>', {class: 'rates'}).append( 1233 $('<input>').attr({ 1234 type : 'text', 1235 name : 'f[booking_rates][' + self.rateIndex + '][title]', 1236 id : 'hourly-rates-name-' + self.rateIndex, 1237 placeholder: lang.booking_rate_title 1238 }), 1239 $timeSelector, 1240 $('<input>').attr({ 1241 type : 'text', 1242 name : 'f[booking_rates][' + self.rateIndex + '][price]', 1243 id : 'hourly-rates-price-' + self.rateIndex, 1244 placeholder: lang.price, 1245 class : 'numeric w120', 1246 }), 1247 $currency, 1248 (!bookingConfigs.bookingRepeatedly 1249 ? $('<select>').attr({ 1250 name: 'f[booking_rates][' + self.rateIndex + '][type]', 1251 id : 'hourly-rate-type-' + self.rateIndex, 1252 }).append( 1253 $('<option>').attr({value: 'single'}).text(lang.booking_single_rate), 1254 $('<option>').attr({value: 'multi', selected: true}).text(lang.booking_multi_rate), 1255 ) 1256 : null 1257 ), 1258 $('<img>').addClass('remove remove-hourly-rate').attr({ 1259 'title': lang.delete, 1260 'alt' : lang.delete, 1261 'src' : bookingConfigs.src_delete_img, 1262 'id' : 'hourly-rate-' + self.rateIndex 1263 }).click(function () { 1264 $(this).closest('.rates').fadeOut('fast', function(){ 1265 $(this).remove(); 1266 self.rateIndex--; 1267 }); 1268 }) 1269 ) 1270 ); 1271 1272 self.rateIndex++; 1273 }; 1274 1275 /** 1276 * Load list with rate ranges to page (for ex. after desc editing) 1277 */ 1278 this.loadingRangesHandler = function() { 1279 $('#booking_rate_ranges_list > div.list-table div.row').remove(); 1280 $('#booking_rate_ranges_list > div.list-table').append('<div id="loading_ranges">' + lang['loading'] + '</div>'); 1281 1282 if (bookingConfigs.rlController === 'edit_listing') { 1283 var request = {mode: 'bookingGetRateRanges', item: bookingConfigs['listing_id'], lang: rlLang}; 1284 1285 $.post(rlConfig.ajax_url, request, function(response){ 1286 if (response.status === 'OK') { 1287 $('#loading_ranges').remove(); 1288 1289 var rate_ranges = response.data.rate_ranges; 1290 var regular_price = response.data.regular_price; 1291 1292 if (rate_ranges.length > 0) { 1293 for (var i = 0; i < rate_ranges.length; i++) { 1294 var item = rate_ranges[i]; 1295 var rate_id = item.ID ? parseInt(item.ID) : 0; 1296 1297 bookingConfigs['current_field'] = rate_id > parseInt(bookingConfigs['current_field']) 1298 ? rate_id 1299 : bookingConfigs['current_field']; 1300 1301 $('#booking_rate_ranges_list > div.list-table').append( 1302 self.buildRateFieldHtml(rate_id, item.From, item.To, item.Price, item.Desc) 1303 ); 1304 } 1305 1306 self.confirmRemoveRateHandler(); 1307 } 1308 1309 if (regular_price) { 1310 var regular_price_desc_html = self.buildRateFieldHtml( 1311 'regular', 1312 lang['booking_rate_price_per_day'], 1313 '', 1314 regular_price.value, 1315 regular_price.desc 1316 ); 1317 1318 $('#booking_rate_ranges_list > div.list-table').append(regular_price_desc_html); 1319 } 1320 1321 self.qtipInit(); 1322 self.recountRegularPrice(); 1323 $('#loading_ranges').remove(); 1324 $('#add_ranges_table').fadeIn('slow'); 1325 } else { 1326 printMessage('error', response.message); 1327 } 1328 }, 'json'); 1329 } else { 1330 var regular_price_desc_html = self.buildRateFieldHtml( 1331 'regular', 1332 lang['booking_rate_price_per_day'], 1333 '', 1334 '', 1335 '', 1336 true 1337 ); 1338 $('#booking_rate_ranges_list > div.list-table').append(regular_price_desc_html); 1339 1340 self.qtipInit(); 1341 self.recountRegularPrice(); 1342 1343 $('#loading_ranges').remove(); 1344 $('#add_ranges_table').fadeIn('normal'); 1345 } 1346 }; 1347 1348 /** 1349 * Generate html code for row with data of rate range 1350 * @param {int} id - ID of rate range 1351 * @param {string} from - From date 1352 * @param {string} to - To date 1353 * @param {int} price - Price of rate range 1354 * @param {string} desc - Description of rate range 1355 * @param {bool} add_listing - Detect add listing page 1356 * @return {string} - Html code of rate range 1357 */ 1358 this.buildRateFieldHtml = function(id, from, to, price, desc, add_listing) { 1359 if (!id) { 1360 return false;
1361 } 1362 1363 var lCurrency = $('select[name="f[price][currency]"] option:selected').text(); 1364 1365 var result = '<div class="row" id="rrange_' + id + '">'; 1366 result += '<div data-caption="' + lang.from + '">' + from +'</div>'; 1367 result += '<div data-caption="' + lang.to + '">' + to + '</div>'; 1368 result += '<div data-caption="' + lang.price + '">'; 1369 1370 /* price */ 1371 result += price && parseFloat(price) !== 0 && price !== lang.not_available 1372 ? (bookingConfigs.system_currency_position === 'before' 1373 ? lCurrency + ' ' + price 1374 : price + ' ' + lCurrency) 1375 : (parseFloat(price) === 0 ? lang['booking_close_days'] : lang['not_available']); 1376 /* price end */ 1377 1378 // add qtip with description of missing standard rate 1379 if (id === 'regular' && price === lang.not_available) { 1380 result += ' <img class="qtip booking_qtip" alt="" title="' + lang['booking_empty_regular'] + '" '; 1381 result += 'src="' + bookingConfigs['src_delete_img'] + '" />'; 1382 } 1383 1384 result += '</div>'; 1385 1386 /* description */ 1387 desc = desc ? desc : ''; 1388 result += '<div data-caption="' + lang.description + '">'; 1389 1390 if (add_listing) { 1391 result += '<a href="javascript:void(0)" onclick="booking.addDesc()">' + lang.description + '</a>'; 1392 } else { 1393 var qtip_e = '<br><hr><a class=\'booking_edit_desc\' href=\'javascript:void(0)\' '; 1394 qtip_e += 'onclick=\'booking.editDesc(' + (id !== 'regular' ? id : '') + ')\'>' + lang.edit + '</a>'; 1395 1396 result += '<img class="qtip booking_qtip" alt="" title="' + (desc ? desc : lang['not_available']); 1397 result += ' ' + qtip_e + '" id="desc_ico_' + id + '" src="'; 1398 result += bookingConfigs['src_delete_img'] + '" />'; 1399 } 1400 1401 result += '<textarea class="hide" id="save_desc_' + id + '" name="b[' + id +'][desc] cols="30" rows="2">'; 1402 result += desc + '</textarea>'; 1403 result += '</div>'; 1404 /* description end */ 1405 1406 result += '<div data-caption="' + lang['actions'] + '">'; 1407 1408 if (id === 'regular') { 1409 result += lang['not_available']; 1410 } else { 1411 result += '<img class="remove remove_rate" id=' + id; 1412 result += ' title="' + lang['delete'] + '" alt="' + lang['delete'] + '"'; 1413 result += ' src="' + bookingConfigs['src_delete_img'] + '" />'; 1414 } 1415 1416 result += '</div>'; 1417 result += '</div>'; 1418 1419 return result; 1420 }; 1421 1422 /** 1423 * Custom qTip initialization with delay 1424 * @param {bool} second_call - Add qtip's for new fields only 1425 */ 1426 this.qtipInit = function(second_call) { 1427 var qtip_style_admin = { 1428 width: 'auto', 1429 background: '#858585', 1430 color: 'white', 1431 border: { 1432 width: 7, 1433 radius: 5, 1434 color: '#858585' 1435 }, 1436 tip: 'bottomLeft' 1437 }; 1438 1439 // first call in document ready 1440 if (!second_call) { 1441 setTimeout( 1442 function(){ 1443 $('.booking_qtip').addClass('qtip'); 1444 $('.qtip.booking_qtip').each(function(){ 1445 if ($(this).attr('title')) { 1446 $(this).qtip({ 1447 content: $(this).attr('title'), 1448 show: 'mouseover', 1449 hide: { 1450 fixed: true, 1451 delay: 500 1452 }, 1453 position: { 1454 corner: { 1455 target: 'topRight', 1456 tooltip: 'bottomLeft' 1457 } 1458 }, 1459 style: bookingConfigs['isAdmin'] ? qtip_style_admin : qtip_style 1460 }).attr('title', ''); 1461 } 1462 }); 1463 }, 1464 100 1465 ); 1466 } else { 1467 if (bookingConfigs['isAdmin']) { 1468 // second call for new images with qtip (in admin) 1469 $('.qtip.booking_qtip').each(function(){ 1470 if ($(this).attr('title')) { 1471 $(this).qtip({ 1472 width: 'auto', 1473 content: $(this).attr('title'), 1474 show: 'mouseover', 1475 hide: 'mouseout', 1476 position: { 1477 corner: { 1478 target: 'topRight', 1479 tooltip: 'bottomLeft' 1480 } 1481 }, 1482 style: { 1483 width: 'auto', 1484 background: '#858585', 1485 color: 'white', 1486 border: { 1487 width: 7, 1488 radius: 5, 1489 color: '#858585' 1490 }, 1491 tip: 'bottomLeft' 1492 } 1493 }).attr('title', ''); 1494 } 1495 }); 1496 } else { 1497 // second call for new images with qtip (in frontend) 1498 $('.qtip.booking_qtip').each(function(){ 1499 var target = 'topRight'; 1500 var tooltip = 'bottomLeft'; 1501 1502 if ($(this).hasClass('middle-bottom')) { 1503 target = 'topMiddle'; 1504 tooltip = 'bottomMiddle'; 1505 1506 var tmp_style = jQuery.extend({}, qtip_style); 1507 tmp_style.tip = 'bottomMiddle'; 1508 } 1509 1510 if ($(this).attr('title')) { 1511 $(this).qtip({ 1512 content: $(this).attr('title'), 1513 show: 'mouseover', 1514 hide: 'mouseout', 1515 position: { 1516 corner: { 1517 target: target, 1518 tooltip: tooltip 1519 } 1520 }, 1521 style: $(this).hasClass('middle-bottom') ? tmp_style : qtip_style 1522 }).attr('title', ''); 1523 } 1524 }); 1525 } 1526 } 1527 }; 1528 1529 /** 1530 * Adding description for new rate range 1531 * @param {int} id - ID of rate range 1532 */ 1533 this.addDesc = function(id) { 1534 if (!id) { 1535 id = 'regular'; 1536 } 1537 1538 var caption = lang['manage']; 1539 var html_content = $('#manage_item_dom').html(); 1540 1541 if (bookingConfigs['isAdmin']) { 1542 $(document).flModal({ 1543 width: 450, 1544 height: 'auto', 1545 caption: caption, 1546 onReady: function(){ 1547 $('#manage_item_dom').html(''); 1548 self.copyDescToTable(id) 1549 }, 1550 content: html_content, 1551 onClose: function(){ 1552 $('#manage_item_dom').html(html_content) 1553 } 1554 }); 1555 } else { 1556 $(document).flModal({ 1557 click: false, 1558 source: '#manage_item_dom', 1559 caption: lang['manage'], 1560 width: 450, 1561 height: 'auto', 1562 ready: function(){ 1563 self.copyDescToTable(id) 1564 } 1565 }); 1566 } 1567 }; 1568 1569 /** 1570 * Copy description from temp container to ranges table 1571 * @param {int} id - ID of rate range 1572 */ 1573 this.copyDescToTable = function(id) { 1574 if (!id) { 1575 return false;
1576 } 1577 1578 var value = $('#save_desc_' + id).val(); 1579 1580 if (value != lang['not_available']) { 1581 $('input[name=item-desc]').val(value); 1582 } 1583 1584 $('input[name=item-desc-save]').click(function(){ 1585 $('#save_desc_' + id).val($('input[name=item-desc]').val()); 1586 1587 if (bookingConfigs['isAdmin']) { 1588 self.closeApModal(); 1589 } else { 1590 $('#modal_block div.close').trigger('click'); 1591 } 1592 }); 1593 }; 1594 1595 /** 1596 * Edit description of Rate Range 1597 * @param {string} id - ID of rate range or Regular 1598 */ 1599 this.editDesc = function(id) { 1600 var caption = lang['manage']; 1601 var html_content = $('#manage_item_dom').html(); 1602 1603 if (bookingConfigs['isAdmin']) { 1604 $(document).flModal({ 1605 width: 450, 1606 height: 'auto', 1607 caption: caption, 1608 onReady: function(){ 1609 $('#manage_item_dom').html(''); 1610 self.sendDescContentFromModal(id) 1611 }, 1612 content: html_content, 1613 onClose: function(){ 1614 $('#manage_item_dom').html(html_content) 1615 } 1616 }); 1617 } else { 1618 $(document).flModal({ 1619 click: false, 1620 source: '#manage_item_dom', 1621 caption: caption, 1622 width: 450, 1623 height: 'auto', 1624 ready: function(){ 1625 self.sendDescContentFromModal(id) 1626 } 1627 }); 1628 } 1629 }; 1630 1631 /** 1632 * Send description of rate via ajax request 1633 * @param {string} id - ID of rate range or Regular 1634 */ 1635 this.sendDescContentFromModal = function(id) { 1636 if (!id) { 1637 id = 'regular'; 1638 } 1639 1640 var old_desc = $('#save_desc_' + id).val(); 1641 1642 $('[name="item-desc"]').val(old_desc !== lang.not_available ? old_desc : ''); 1643 $('[name="item-desc-save"]').click(function(){ 1644 var new_desc = $('[name=item-desc]').val(); 1645 1646 if (new_desc !== lang.not_available && old_desc !== new_desc) { 1647 if (bookingConfigs.rlController === 'edit_listing') { 1648 $(this).val(lang['loading']).addClass('disabled').attr('disabled', true); 1649 1650 var request = { 1651 mode: 'bookingUpdateRateDesc', 1652 item: {rate_id: id, listing_id: bookingConfigs['listing_id']}, 1653 desc: JSON.stringify(new_desc), 1654 lang: rlLang 1655 }; 1656 1657 $.post(rlConfig.ajax_url, request, function(response){ 1658 if (bookingConfigs['isAdmin']) { 1659 self.closeApModal(); 1660 } else { 1661 $('#modal_block div.close').trigger('click'); 1662 } 1663 1664 if (response.status === 'OK') { 1665 $('#save_desc_' + id).val(new_desc); 1666 1667 // update rows with rate ranges 1668 self.loadingRangesHandler(); 1669 1670 if (!bookingConfigs['isAdmin']) { 1671 setTimeout(function(){ printMessage('notice', response.data) }, 500); 1672 } 1673 } else { 1674 setTimeout(function(){ printMessage('error', response.message) }, 500); 1675 } 1676 }, 'json'); 1677 } else { 1678 if (bookingConfigs['isAdmin']) { 1679 self.closeApModal(); 1680 } else { 1681 $('#modal_block div.close').trigger('click'); 1682 } 1683 } 1684 } else { 1685 if (bookingConfigs['isAdmin']) { 1686 self.closeApModal(); 1687 } else { 1688 $('#modal_block div.close').trigger('click'); 1689 } 1690 } 1691 }); 1692 }; 1693 1694 /** 1695 * Get dates for calendar 1696 * 1697 * @param {int} listing_id - ID of listing 1698 * @param {string} param_mode - Button for next/previous month 1699 * @param {bool} update - Update calendar without current request 1700 */ 1701 this.getDates = function(listing_id, param_mode, update) { 1702 if (!listing_id) { 1703 return false;
1704 } 1705 1706 self.loadExternalScripts(function() { 1707 flUtil.ajax({ 1708 mode: 'bookingGetDates', 1709 item: { 1710 listing_id: listing_id, 1711 mode : param_mode, 1712 request_id: bookingConfigs.request_id ? bookingConfigs.request_id : null 1713 } 1714 }, 1715 function(response) { 1716 bookingConfigs.usBook = []; 1717 bookingConfigs.usRange = []; 1718 bookingConfigs.closeRange = []; 1719 1720 if (response.status === 'OK') { 1721 let weekDays = { 1722 1: lang.booking_monday, 1723 2: lang.booking_tuesday, 1724 3: lang.booking_wednesday, 1725 4: lang.booking_thursday, 1726 5: lang.booking_friday, 1727 6: lang.booking_saturday, 1728 7: lang.booking_sunday, 1729 }; 1730 1731 // assign already booked days 1732 if (response.data.userBook) { 1733 for (var i = response.data.userBook.length - 1; i >= 0; i--) { 1734 bookingConfigs.usBook[i] = []; 1735 bookingConfigs.usBook[i][0] = response.data.userBook[i].Status; 1736 bookingConfigs.usBook[i][1] = response.data.userBook[i].From; 1737 bookingConfigs.usBook[i][2] = response.data.userBook[i].To; 1738 bookingConfigs.usBook[i][3] = response.data.userBook[i].ID; 1739 bookingConfigs.usBook[i][4] = response.data.userBook[i].Own_request; 1740 bookingConfigs.usBook[i][5] = response.data.userBook[i].Checkout; 1741 1742 if (bookingConfigs.Booking_type === 'time_range') { 1743 bookingConfigs.usBook[i][6] = response.data.userBook[i].Duration; 1744 bookingConfigs.usBook[i][7] = response.data.userBook[i].Type; 1745 bookingConfigs.usBook[i][8] = response.data.userBook[i].RateIndex; 1746 } 1747 } 1748 } 1749 1750 // assign rate ranges 1751 if (response.data.usRange) { 1752 for (var i = response.data.usRange.length - 1; i >= 0; i--) { 1753 bookingConfigs.usRange[i] = []; 1754 bookingConfigs.usRange[i][0] = response.data.usRange[i]['From']; 1755 bookingConfigs.usRange[i][1] = response.data.usRange[i]['To']; 1756 bookingConfigs.usRange[i][2] = response.data.usRange[i]['Price']; 1757 } 1758 } 1759 1760 // assign closed days 1761 if (response.data.closeRange) { 1762 for (var i = response.data.closeRange.length - 1; i >= 0; i--) { 1763 bookingConfigs.closeRange[i] = []; 1764 bookingConfigs.closeRange[i][0] = response.data.closeRange[i]['From']; 1765 bookingConfigs.closeRange[i][1] = response.data.closeRange[i]['To']; 1766 } 1767 } 1768 1769 // assign binding days 1770 if (response.data.bindingDays 1771 && (response.data.bindingDays.checkin || response.data.bindingDays.checkout) 1772 ) { 1773 bookingConfigs['bind_checkin'] = response.data.bindingDays.checkin 1774 ? response.data.bindingDays.checkin 1775 : ''; 1776 bookingConfigs['bind_checkout'] = response.data.bindingDays.checkout 1777 ? response.data.bindingDays.checkout 1778 : ''; 1779 1780 let additionalNotices = ''; 1781 if (bookingConfigs.Booking_type !== 'time_range' 1782 && (bookingConfigs.bind_checkin || bookingConfigs.bind_checkout) 1783 ) { 1784 if (bookingConfigs.bind_checkin && bookingConfigs.bind_checkin.split(',').length < 7) { 1785 let checkinLocale = self.getBindDaysByLocale(bookingConfigs.bind_checkin, weekDays);
1786 bookingConfigs.bindCheckinLocale = checkinLocale; 1787 1788 additionalNotices += '<li class="active">'; 1789 additionalNotices += lang.check_in_only_text.replace('{days}', checkinLocale); 1790 additionalNotices += '</li>'; 1791 } 1792 1793 if (bookingConfigs.bind_checkout && bookingConfigs.bind_checkout.split(',').length < 7) { 1794 let checkoutLocale = self.getBindDaysByLocale(bookingConfigs.bind_checkout, weekDays); 1795 bookingConfigs.bindCheckoutLocale = checkoutLocale; 1796 1797 additionalNotices += '<li class="active">'; 1798 additionalNotices += lang.check_out_only_text.replace('{days}', checkoutLocale); 1799 additionalNotices += '</li>'; 1800 } 1801 1802 let $notices = $('.booking_notices ul'); 1803 $notices.find('li:not(.static)').remove(); 1804 $notices.append(additionalNotices); 1805 } 1806 } 1807 1808 // draw calendar 1809 if (response.data.bookingDays) { 1810 var month = []; 1811 var first = false; 1812 var mass_bind_checkin = bookingConfigs.bind_checkin 1813 ? bookingConfigs.bind_checkin.split(',') 1814 : false; 1815 var mass_bind_checkout = bookingConfigs.bind_checkout 1816 ? bookingConfigs.bind_checkout.split(',') 1817 : false; 1818 1819 var calendar_html = '<div id="calendar_map" class="clearfix row'; 1820 calendar_html += bookingConfigs['is_escort'] ? ' escort' : ''; 1821 calendar_html += '">'; 1822 1823 var narrow_templates = { 1824 'escort_flatty': 'col-sm-12', 1825 'escort_velvet_flatty': 'col-sm-12', 1826 'general_modern': 'col-sm-12', 1827 'auto_modern': 'col-sm-12', 1828 'general_simple': 'col-sm-12', 1829 'escort_sun_cocktail': 'col-sm-12 col-md-12 col-lg-6', 1830 }; 1831 1832 var col_class = ( 1833 typeof narrow_templates[bookingConfigs['site_template']] == 'undefined' 1834 || rlPageInfo['controller'] !== 'listing_details' 1835 ) 1836 ? 'col-sm-6' 1837 : narrow_templates[bookingConfigs['site_template']]; 1838 1839 for (var item in response.data.bookingDays) { 1840 month = response.data.bookingDays[item]; 1841 first = !first; 1842 1843 calendar_html += '<div class="' + col_class + '"><div>'; 1844 calendar_html += '<div class="month-name"><b>' + month.Name + ' ' + month.Year + '</b></div>'; 1845 calendar_html += '<table class="month-table" '; 1846 calendar_html += '>'; 1847 calendar_html += '<tr class="dayName">'; 1848 1849 let dayTitle; 1850 for (let i = 1; i <= 7; i++) { 1851 if (bookingConfigs.first_day === 'sunday') { 1852 dayTitle = i === 1 ? weekDays[7] : weekDays[i - 1]; 1853 } else { 1854 dayTitle = weekDays[i]; 1855 } 1856 1857 calendar_html += '<td><div>' + dayTitle + '</div></td>'; 1858 } 1859 1860 calendar_html += '</tr>'; 1861 calendar_html += '<tr>'; 1862 1863 var index = 0; 1864 1865 // show other days 1866 for (var item_day in month.Days) { 1867 var day = month.Days[item_day]; 1868 var book_color = ''; 1869 index++; 1870 1871 calendar_html += '<td class="calendar_td">'; 1872 1873 if (!day.Miss) { 1874 // disable binding days 1875 if (day.Color !== 'U' && (mass_bind_checkin || mass_bind_checkout)) { 1876 if (bookingConfigs.Booking_type === 'time_range') { 1877 if (bookingConfigs.bind_checkin 1878 && !in_array( 1879 self.getDateByTimeZone(parseInt(day.mktime), 'ddd'), 1880 mass_bind_checkin 1881 ) 1882 ) { 1883 day.Color = 'U'; 1884 } 1885 } 1886 } 1887 1888 if (day.Color === 'U') { 1889 book_color = 'unavailable'; 1890 } else if (day.Color === 'R') { 1891 book_color = 'restriction'; 1892 } else if (day.Color === 'T') { 1893 book_color = 'today'; 1894 } else if (day.Color === 'A') { 1895 var current = false;
1896 1897 if (!update 1898 && !param_mode 1899 && bookingConfigs['usBook'] 1900 && bookingConfigs['request_id'] 1901 ) { 1902 for (let id in bookingConfigs['usBook']) { 1903 let st_b = bookingConfigs['usBook'][id][1]; 1904 let en_b = bookingConfigs['usBook'][id][2]; 1905 let daysInPeriod = self.getCountDaysBetween2Timestamps(en_b, st_b); 1906 let currentDate = st_b; 1907 let req_id = Number(bookingConfigs['usBook'][id]['3']); 1908 let current_req_id = Number(bookingConfigs['request_id']); 1909 1910 // Highlight current request in calendar 1911 if (current_req_id && current_req_id === req_id) { 1912 for (i = 0; i <= daysInPeriod; i++) { 1913 if (i !== 0) { 1914 currentDate = self.addDaysToTimestamp(currentDate); 1915 } 1916 1917 current = day.mktime >= st_b && day.mktime <= en_b; 1918 } 1919 } 1920 } 1921 } 1922 1923 book_color = current ? 'current-request' : 'available'; 1924 } 1925 1926 if (bookingConfigs.Booking_type === 'time_range' && day.fullyBooked) { 1927 book_color += ' fully-booked'; 1928 } 1929 1930 calendar_html += '<div class="date ' + book_color + '"'; 1931 1932 if (day.mktime) { 1933 calendar_html += 'id="day_' + day.mktime + '" '; 1934 } 1935 1936 if (day.Color !== 'U' && day.Color !== 'R') { 1937 calendar_html += ' title="' + lang.booking_start_booking_title + '" '; 1938 calendar_html += 'onclick="booking.xSelect(\'' + day.mktime + '\')"'; 1939 } 1940 1941 calendar_html += '>'; 1942 calendar_html += '<span>'; 1943 calendar_html += parseInt(day.Day); 1944 calendar_html += '</span>'; 1945 1946 // add price of day 1947 if (book_color !== 'unavailable' && book_color !== 'restriction') { 1948 var price = 0; 1949 1950 if (bookingConfigs['usRange']) { 1951 for (var idR in bookingConfigs['usRange']) { 1952 price = 0; 1953 1954 if (parseInt(bookingConfigs['usRange'][idR][0]) <= day.mktime 1955 && day.mktime <= parseInt(bookingConfigs['usRange'][idR][1]) 1956 ) { 1957 price = parseFloat(bookingConfigs['usRange'][idR][2].split('|')[0]); 1958 break; 1959 } 1960 } 1961 } 1962 1963 price = price ? price : bookingConfigs['defPrice']; 1964 1965 if (price) { 1966 price = self.adaptNumbersInPrice(price); 1967 price = bookingConfigs['system_currency_position'] === 'before' 1968 ? bookingConfigs['defCurrency'] + ' ' + price 1969 : price + ' ' + bookingConfigs['defCurrency']; 1970 1971 calendar_html += '<span class="day-price">' + price + '</span>'; 1972 } 1973 } 1974 1975 calendar_html += '</div>'; 1976 calendar_html += '</td>'; 1977 } 1978 1979 if (index % 7 === 0 && index !== month.Days.length) { 1980 calendar_html += '</tr><tr>'; 1981 } 1982 } 1983 1984 calendar_html += '</tr>'; 1985 calendar_html += '</table>'; 1986 calendar_html += '</div></div>'; 1987 } 1988 1989 /* Prev/next month navigation */ 1990 calendar_html += '<div class="horizontal">'; 1991 calendar_html += '<div '; 1992 calendar_html += 'onclick="booking.changeDates(\'-M\')" id="prevRange" '; 1993 calendar_html += 'class="prev hide" title="' + lang['booking_prev'] + ' '; 1994 calendar_html += lang['booking_month'] + '"'; 1995 calendar_html += '></div>'; 1996 calendar_html += '<div '; 1997 calendar_html += 'onclick="booking.changeDates(\'+M\')" class="next" '; 1998 calendar_html += 'title="' + lang['booking_next'] + ' ' + lang['booking_month'] + '"'; 1999 calendar_html += '></div>'; 2000 calendar_html += '</div>'; 2001 /* Prev/next month navigation end */ 2002 2003 calendar_html += '</div>'; 2004
2005 $('#booking_calendar').html(calendar_html).fadeIn('slow'); 2006 2007 self.booking_mask("set"); 2008 self.paintUserBook(); 2009 self.booking_mask('reset'); 2010 } 2011 2012 // show/hide arrow for previous month 2013 response.data.showPrev ? $('#prevRange').fadeIn('slow') : $('#prevRange').fadeOut('fast'); 2014 2015 // set prebooked days in calendar to continue order (in booking order page only) 2016 // simulate selection 2017 if (bookingConfigs['db_start'] 2018 && (bookingConfigs['db_end'] || bookingConfigs.Booking_type === 'time_range') 2019 && bookingConfigs['start_date_value'] 2020 && (bookingConfigs['end_date_value'] || bookingConfigs.Booking_type === 'time_range') 2021 && bookingConfigs['total_days'] 2022 ) { 2023 // update calendar and count total amount 2024 self.bUpdate( 2025 bookingConfigs['db_start'], 2026 false, 2027 false, 2028 param_mode || bookingConfigs.in_popup ? true : false 2029 ); 2030 2031 if (!bookingConfigs['edit_action']) { 2032 bookingConfigs['cur_id'] = bookingConfigs['s_id'] = bookingConfigs['db_start']; 2033 } 2034 2035 bookingConfigs['total_cost'] = 0; 2036 bookingConfigs['first'] = 1; 2037 2038 if (bookingConfigs.in_popup) { 2039 // remove selected day from calendar 2040 bookingConfigs['s_id'] = 0; 2041 self.book_color(true); 2042 bookingConfigs['first'] = 0; 2043 } else { 2044 var result = self.bUpdate( 2045 bookingConfigs['db_end'], 2046 bookingConfigs['db_start'], 2047 '+', 2048 !!param_mode 2049 ); 2050 2051 if (!param_mode) { 2052 self.stepsHandler( 2053 'details', 2054 'show', 2055 { 2056 start_book : bookingConfigs.start_date_value, 2057 end_book : bookingConfigs.end_date_value, 2058 total_days : bookingConfigs.total_days, 2059 total_cost : bookingConfigs.total_cost, 2060 mode : !!param_mode, 2061 } 2062 ); 2063 2064 // set default condition for second selection 2065 bookingConfigs['first'] = 0; 2066 } 2067 } 2068 } 2069 2070 if (param_mode) { 2071 self.book_color(false, true, param_mode, true); 2072 } 2073 2074 if (typeof $.convertPrice == 'function') { 2075 $('#area_booking .day-price').convertPrice({showCents: false, shortView: true}); 2076 } 2077 2078 // disable calendar in request details page in first loading 2079 if (rlPageInfo.controller === 'booking_requests') { 2080 if (update) { 2081 $('#booking_calendar').removeClass('disabled'); 2082 self.booking_mask('reset'); 2083 $('#area_booking .table-cell.current_dates').removeClass('current_dates'); 2084 2085 if (bookingConfigs.Booking_type === 'date_time_range' 2086 && bookingConfigs.listing_check_in 2087 && bookingConfigs.listing_check_out 2088 ) { 2089 /* build html for check in field */ 2090 checkin_html = '<div class="name"><div><span>' + lang['booking_checkin']; 2091 checkin_html += '</span></div></div>'; 2092 checkin_html += '<div class="field start_date">'; 2093 2094 // block unavailable time 2095 $('[name="f[booking_check_in]"] option').each(function(){ 2096 $(this).attr('disabled', 'disabled'); 2097 2098 if ($(this).attr('value') === bookingConfigs.listing_check_in) { 2099 $(this).removeAttr('disabled').attr('selected', 'selected'); 2100 2101 return false;
2102 } 2103 }); 2104 2105 checkin_html += '<b>' + bookingConfigs['start_date_value'] + '</b> - '; 2106 checkin_html += $('#booking_checkin_field').html(); 2107 checkin_html += '</div>'; 2108 2109 $('.table-cell.check-in').html(checkin_html); 2110 /* end html for check-in field */ 2111 2112 /* build html for check-out field */ 2113 checkout_html = '<div class="name"><div><span>' + lang['booking_checkout']; 2114 checkout_html += '</span></div></div>'; 2115 checkout_html += '<div class="field end_date">'; 2116 2117 $('[name="f[booking_check_out]"] option[value="0"]').attr('disabled', 'disabled'); 2118 2119 // block unavailable time 2120 $($('[name="f[booking_check_out]"] option').get().reverse()).each(function(){ 2121 $(this).attr('disabled', 'disabled'); 2122 2123 if ($(this).attr('value') === bookingConfigs.listing_check_out) { 2124 $(this).removeAttr('disabled').attr('selected', 'selected'); 2125 2126 return false; 2127 } 2128 }); 2129 2130 checkout_html += '<b>' + bookingConfigs['end_date_value'] + '</b> - '; 2131 checkout_html += $('#booking_checkout_field').html(); 2132 checkout_html += '</div>'; 2133 2134 $('.table-cell.check-out').html(checkout_html); 2135 /* end html for check-out field */ 2136 2137 self.dateTimeRangeHandler(); 2138 } 2139 } else if (!update && !param_mode && bookingConfigs.Booking_type !== 'time_range') { 2140 $('#booking_calendar').addClass('disabled'); 2141 self.booking_mask('set'); 2142 } 2143 } 2144 } else { 2145 printMessage('error', response.message); 2146 } 2147 }) 2148 }); 2149 }; 2150 2151 /** 2152 * Saving selected binding days 2153 */ 2154 this.saveBindingDaysHandler = function() { 2155 if (!bookingConfigs['listing_id']) { 2156 return false; 2157 } 2158 2159 $('.save_binding_days').click(function(){ 2160 $(this).val(lang['loading']).addClass('disabled').attr('disabled', 'disabled'); 2161 2162 var formData = $('#binding_days_form').serializeArray(); 2163 var request = { 2164 mode: 'bookingSaveBindingDays', 2165 item: { 2166 listing_id: bookingConfigs['listing_id'], 2167 formData: formData 2168 }, 2169 lang: rlLang 2170 }; 2171 2172 $.post(rlConfig.ajax_url, request, function(response){ 2173 $('.save_binding_days').val(lang['save']).removeClass('disabled').removeAttr('disabled'); 2174 2175 if (response.status == 'OK') { 2176 printMessage('notice', response.data) 2177 } else { 2178 printMessage('error', response.message); 2179 } 2180 }, 'json'); 2181 }); 2182 }; 2183 2184 /** 2185 * Saving selected configs 2186 */ 2187 this.saveConfigsHandler = function() { 2188 if (!bookingConfigs['listing_id']) { 2189 return false; 2190 } 2191 2192 $('.save_configs').click(function(){ 2193 $(this).val(lang['loading']).addClass('disabled').attr('disabled', 'disabled'); 2194 var min_day_value = $('[name="min_book_day"]').val(); 2195 var max_day_value = $('[name="max_book_day"]').val(); 2196 2197 if ((min_day_value == '' || parseInt(min_day_value) <= 0) && bookingConfigs['Booking_type'] != 'time_range') { 2198 $('.save_configs').val(lang['save']).removeClass('disabled').removeAttr('disabled'); 2199 printMessage('error', lang['booking_min_config_desc'], 'min_book_day'); 2200 } else if (max_day_value == '' 2201 || parseInt(max_day_value) < 0 2202 || (parseInt(max_day_value) > 0 && parseInt(max_day_value) <= parseInt(min_day_value)) 2203 ) { 2204 $('.save_configs').val(lang['save']).removeClass('disabled').removeAttr('disabled'); 2205 printMessage('error', lang['booking_max_config_error'], 'max_book_day'); 2206 } else { 2207 var formData = $('#configs_form').serializeArray(); 2208 var request = { 2209 mode: 'bookingSaveConfigs', 2210 item: { 2211 listing_id: bookingConfigs['listing_id'], 2212 formData: formData 2213 }, 2214 lang: rlLang 2215 }; 2216 2217 $.post(rlConfig.ajax_url, request, function(response){ 2218 $('.save_configs').val(lang['save']).removeClass('disabled').removeAttr('disabled'); 2219 2220 if (response.status == 'OK') { 2221 printMessage('notice', response.data) 2222 } else { 2223 printMessage('error', response.message); 2224 } 2225 }, 'json'); 2226 } 2227 }); 2228 }; 2229 2230 /** 2231 * Recount of regular price by changed value of "Rent field" 2232 */ 2233 this.rentFieldHandler = function() { 2234 if (!bookingConfigs.booking_rent_field || !bookingConfigs.booking_rent_value) { 2235 return false;
2236 } 2237 2238 var $rent = $('[name="f[' + bookingConfigs.booking_rent_field +']"]'); 2239 2240 if ($rent.length) { 2241 $rent.change(function() { 2242 if ($('[name="f[' + bookingConfigs['booking_rent_field'] +']"]:checked').val() !== bookingConfigs.booking_rent_value) { 2243 if (bookingConfigs['booking_time_frame_field']) { 2244 $('[name="f[' + bookingConfigs['booking_time_frame_field'] + ']"]').removeAttr('checked'); 2245 } 2246 2247 self.recountRegularPrice(); 2248 } 2249 }); 2250 } 2251 }; 2252 2253 /** 2254 * Recount of regular price by changed price 2255 */ 2256 this.priceHandler = function() { 2257 if (!bookingConfigs.booking_price_field) { 2258 return false; 2259 } 2260 2261 var $price = $('[name="f[' + bookingConfigs['booking_price_field'] + '][value]"]'); 2262 2263 if ($price.length > 0) { 2264 $price.change(function(){ 2265 self.recountRegularPrice(); 2266 }); 2267 } 2268 }; 2269 2270 /** 2271 * Recount of regular price by changed time frame 2272 */ 2273 this.rentTimeFrameHandler = function() { 2274 if (!bookingConfigs.booking_time_frame_field) { 2275 return false; 2276 } 2277 2278 var $timeFrame = $('[name="f[' + bookingConfigs['booking_time_frame_field'] + ']"]'); 2279 2280 if ($timeFrame.length) { 2281 $timeFrame.change(function(){ 2282 self.recountRegularPrice(); 2283 }); 2284 } 2285 }; 2286 2287 /** 2288 * Recount of regular price by changed currency 2289 */ 2290 this.currencyHandler = function() { 2291 if (!bookingConfigs.booking_price_field) { 2292 return false; 2293 } 2294 2295 var $currency = $('[name="f[' + bookingConfigs.booking_price_field + '][currency]"]'); 2296 2297 if ($currency.length) { 2298 $currency.change(function(){ 2299 self.recountRegularPrice(); 2300 }); 2301 } 2302 }; 2303 2304 /** 2305 * Recount and put the regular price to rate ranges table 2306 * @param {bool} enable_handlers - Enable handlers for recount 2307 */ 2308 this.recountRegularPrice = function(enable_handlers) { 2309 if (enable_handlers) { 2310 self.priceHandler(); 2311 self.rentTimeFrameHandler(); 2312 self.currencyHandler(); 2313 self.rentFieldHandler(); 2314 2315 return; 2316 } 2317 2318 var $time_frame_field_val = $('[name="f[' + bookingConfigs.booking_time_frame_field + ']"]').is('select') 2319 ? $('[name="f[' + bookingConfigs.booking_time_frame_field + ']"] option:selected').val() 2320 : $('[name="f[' + bookingConfigs.booking_time_frame_field + ']"]:checked').val(); 2321 2322 if (!bookingConfigs['booking_price_field'] 2323 || !bookingConfigs['booking_time_frame'] 2324 || $('[name="f[booking_module]"][value="1"]').is(':checked') === false 2325 || ((!bookingConfigs['booking_time_frame_field'] 2326 || !$time_frame_field_val) 2327 && (bookingConfigs['booking_rent_field'] 2328 && bookingConfigs['booking_rent_value'] 2329 && $('[name="f[' + bookingConfigs['booking_rent_field'] + ']"]:checked').val() == bookingConfigs['booking_rent_value']) 2330 ) 2331 ) { 2332 return; 2333 } 2334 2335 let price, currency, time_frame, price_cel, price_field = bookingConfigs.booking_price_field; 2336 2337 price = parseFloat($('[name="f[' + price_field + '][value]"]').val()) 2338 ? parseFloat($('[name="f[' + price_field + '][value]"]').val()) 2339 : lang['not_available']; 2340 currency = $('[name="f[' + price_field + '][currency]"] option:selected').text(); 2341 time_frame = $time_frame_field_val; 2342 2343 /* count regular price */ 2344 if (price > 0 && time_frame) { 2345 for (var time_frame_key in bookingConfigs.booking_time_frame) { 2346 if (!bookingConfigs.booking_time_frame.hasOwnProperty(time_frame_key)) { 2347 continue; 2348 } 2349 2350 var time_frame_value = bookingConfigs.booking_time_frame[time_frame_key]; 2351 2352 if (time_frame === time_frame_value) { 2353 if (time_frame_key === 'day') { 2354 price_cel = price; 2355 } else if (time_frame_key === 'week') { 2356 price_cel = Math.round((price / 7) * 100) / 100; 2357 } else if (time_frame_key === 'month') { 2358 // get count days of current month 2359 Date.prototype.daysInMonth = function(mth, yr){ 2360 yr = yr || this.getFullYear(); 2361 mth = mth || this.getMonth(); 2362 2363 return new Date(yr, mth + 1, 0).getDate(); 2364 }; 2365 2366 price_cel = Math.round((price / new Date().daysInMonth()) * 100) / 100; 2367 } else if (time_frame_key === 'year') {
2368 price_cel = Math.round((price / 365) * 100) / 100; 2369 } else if (time_frame_key === 'hour' && bookingConfigs.booking_type === 'date_time_range') { 2370 price_cel = Math.round((price * 24) * 100) / 100; 2371 } else { 2372 price_cel = lang.not_available; 2373 } 2374 2375 break; 2376 } else { 2377 price_cel = lang.not_available; 2378 } 2379 } 2380 2381 /* build regular price */ 2382 if (price_cel !== lang.not_available) { 2383 price = bookingConfigs.system_currency_position === 'before' 2384 ? currency + ' ' + price_cel 2385 : price_cel + ' ' + currency; 2386 } else { 2387 price = lang.not_available; 2388 } 2389 } else { 2390 price = lang.not_available; 2391 } 2392 2393 /* add value to table with rate ranges */ 2394 if ($('#rrange_regular').length > 0) { 2395 var price_val = price; 2396 2397 // add qtip with description of missing standard rate 2398 if (price_val === lang.not_available) { 2399 price += ' <img class="qtip booking_qtip" alt="" title="' + lang['booking_empty_regular'] + '" '; 2400 price += 'src="' + bookingConfigs['src_delete_img'] + '" />'; 2401 } 2402 2403 $('#rrange_regular').find('div[data-caption="' + lang['price'] + '"]').html(price); 2404 2405 if (price_val === lang.not_available) { 2406 self.qtipInit(true); 2407 } 2408 } 2409 2410 return price; 2411 }; 2412 2413 /** 2414 * Handler for booking steps 2415 * 2416 * @param {string} steps - Key of step or "all" 2417 * @param {string} action - Show/hide 2418 * @param {object} parameters - Additional parameters (optional) 2419 */ 2420 this.stepsHandler = function(steps, action, parameters) { 2421 if (!steps || !action) { 2422 return; 2423 } 2424 2425 // show/hide booking details section 2426 if (steps === 'details') { 2427 if (action === 'show' && !parameters.mode) { 2428 var html = ''; 2429 2430 if (!bookingConfigs.in_popup) { 2431 if (rlPageInfo.controller === 'booking_order') { 2432 html = '<div class="table-cell escort-date">'; 2433 html += '<div class="name"><div><span>'; 2434 2435 html += bookingConfigs.Booking_type === 'time_range' 2436 ? lang.booking_escort_date 2437 : lang.booking_checkin; 2438 2439 html += '</span></div></div>'; 2440 html += '<div class="value">'; 2441 2442 // adding check-in (date & time) 2443 if (parameters && parameters.start_book) { 2444 if (bookingConfigs.Booking_type === 'date_time_range') { 2445 if (bookingConfigs.listing_check_in) { 2446 $('[name="f[booking_check_in]"] option').each(function(){ 2447 $(this).attr('disabled', 'disabled'); 2448 2449 if ($(this).attr('value') === bookingConfigs.listing_check_in) { 2450 $(this).removeAttr('disabled').attr('selected', 'selected'); 2451 2452 return false; 2453 } 2454 }); 2455 } 2456 2457 html += '<div class="date-value"><b>' + parameters.start_book + '</b> - </div>' + $('#booking_checkin_field').html(); 2458 } else { 2459 html += bookingConfigs.check_in && bookingConfigs.Booking_type !== 'time_range' 2460 ? parameters.start_book + ' - ' + bookingConfigs.check_in 2461 : parameters.start_book; 2462 2463 if (bookingConfigs.Booking_type === 'time_range') { 2464 html += '<span style="margin: 0 5px;">/</span><a href="javascript:void(0)" '; 2465 html += 'onclick="booking.escortChangeDate()">'; 2466 html += lang.booking_button_select_date + '</a>'; 2467 } 2468 } 2469 } 2470 2471 html += '</div></div>'; 2472 2473 if (bookingConfigs.Booking_type === 'time_range') { 2474 html += '<div class="table-cell">'; 2475 html += '<div class="name"><div><span>' + lang.booking_escort_type + '</span></div></div>'; 2476 html += '<div class="value">' + $('#escort_rates_obj').html() + '</div>'; 2477 2478 $('#escort_rates_obj').remove(); 2479 2480 html += '</div>'; 2481 } 2482 2483 html += '<div class="table-cell">'; 2484 html += '<div class="name"><div><span>'; 2485 2486 if (bookingConfigs.Booking_type === 'time_range') { 2487 let $timeContainer = $('#booking_checkout_field'), 2488 $durationContainer = $('#escort_duration_obj'); 2489 2490 if (bookingConfigs.Booking_repeatedly) { 2491 html += lang.booking_escort_time; 2492 html += '</span></div></div>'; 2493 html += '<div class="value checkout_value_field">'; 2494 2495 self.updateEscortAvailabilityData(); 2496
2497 html += $timeContainer.html(); 2498 html += '</div></div>'; 2499 html += '<div class="table-cell">'; 2500 html += '<div class="name"><div><span>' + lang.booking_escort_duration; 2501 html += '</span></div></div>'; 2502 html += '<div class="value">' + $durationContainer.html(); 2503 } else { 2504 html += lang.booking_escort_duration; 2505 html += '</span></div></div>'; 2506 html += '<div class="value hourly-time"><div class="view">' + lang.not_available + '</div>'; 2507 html += '<div class="origin hide">' + $durationContainer.html() + '</div>'; 2508 html += '</div></div>'; 2509 html += '<div class="table-cell">'; 2510 html += '<div class="name"><div><span>'; 2511 html += lang.booking_escort_time; 2512 html += '</span></div></div>'; 2513 html += '<div class="value checkout_value_field">'; 2514 2515 self.updateEscortAvailabilityData(); 2516 2517 html += $timeContainer.html(); 2518 html += '</div></div>'; 2519 } 2520 2521 $timeContainer.remove(); 2522 $durationContainer.remove(); 2523 } else { 2524 html += lang.booking_checkout; 2525 html += '</span></div></div>'; 2526 html += '<div class="value checkout_value_field">'; 2527 2528 // adding check-out (date & time) 2529 if (parameters && parameters.end_book) { 2530 if (bookingConfigs.Booking_type === 'date_time_range') { 2531 if (bookingConfigs.listing_check_out) { 2532 $('[name="f[booking_check_out]"] option[value="0"]').attr('disabled', 'disabled'); 2533 2534 $($('[name="f[booking_check_out]"] option').get().reverse()).each(function(){ 2535 $(this).attr('disabled', 'disabled'); 2536 2537 if ($(this).attr('value') === bookingConfigs.listing_check_out) { 2538 $(this).removeAttr('disabled').attr('selected', 'selected'); 2539 2540 return false; 2541 } 2542 }); 2543 } 2544 2545 html += '<div class="date-value"><b>' + parameters.end_book + '</b> - </div>' + $('#booking_checkout_field').html(); 2546 } else { 2547 html += bookingConfigs.check_out 2548 ? parameters.end_book + ' - ' + bookingConfigs.check_out 2549 : parameters.end_book 2550 } 2551 } 2552 } 2553 2554 html += '</div></div>'; 2555 2556 if (bookingConfigs.Booking_type !== 'time_range') { 2557 html += '<div class="table-cell">'; 2558 html += '<div class="name"><div><span>' + lang.booking_nights + '</span></div></div>'; 2559 html += '<div class="value">'; 2560 html += parameters && parameters.total_days ? parameters.total_days : ''; 2561 html += '</div></div>'; 2562 } 2563 2564 if (bookingConfigs.total_cost || bookingConfigs.Booking_type === 'time_range') { 2565 html += '<div class="table-cell">'; 2566 html += '<div class="name"><div><span>' + lang.booking_amount + '</span></div></div>'; 2567 html += '<div class="value amount">'; 2568 2569 // adding total price 2570 var total_cost = bookingConfigs.total_cost ? bookingConfigs.total_cost : lang.not_available; 2571 2572 if (bookingConfigs.total_cost) { 2573 html += bookingConfigs.system_currency_position === 'before' 2574 ? bookingConfigs.defCurrency + ' ' + total_cost 2575 : total_cost + ' ' + bookingConfigs.defCurrency; 2576 } else { 2577 html += total_cost; 2578 } 2579 2580 html += '</div></div>'; 2581 2582 // added downpayment data 2583 if (bookingConfigs.prepayment) { 2584 var downpayment = self.countPrepayment(bookingConfigs.total_cost); 2585 2586 html += '<div class="table-cell">'; 2587 html += '<div class="name"><div><span>' + lang.booking_prepayment_step + '</span></div></div>'; 2588 html += '<div class="value downpayment">' + downpayment + '</div></div>'; 2589 } 2590 } 2591 2592 html += '</div>'; 2593 } 2594 2595 // next step button 2596 html += '<div class="form-buttons">'; 2597 2598 // hidden fields with system values 2599 html += '<form method="post" action="' + bookingConfigs.booking_order_page + '">'; 2600 html += '<input type="hidden" name="listing_id" value="' + bookingConfigs.listing_id + '">'; 2601 html += '<input type="hidden" name="start_date" value="' + bookingConfigs.db_start + '">'; 2602 html += '<input type="hidden" name="start_date_value" value="'; 2603 html += parameters && parameters.start_book ? parameters.start_book : ''; 2604 html += '">'; 2605 html += '<input type="hidden" name="checkin" value="' + bookingConfigs.check_in + '">'; 2606 html += '<input type="hidden" name="end_date" value="' + bookingConfigs.db_end + '">'; 2607 html += '<input type="hidden" name="end_date_value" value="'; 2608 html += parameters && parameters.end_book ? parameters.end_book : ''; 2609 html += '">'; 2610 html += '<input type="hidden" name="checkout" value="' + bookingConfigs.check_out + '">'; 2611 html += '<input type="hidden" name="total_cost" value="' + bookingConfigs.total_cost + '">'; 2612 html += '<input type="hidden" name="total_days" value="'; 2613 html += parameters && parameters.total_days ? parameters.total_days : ''; 2614 html += '">'; 2615 html += '<input '; 2616 html += rlPageInfo.controller === 'listing_details' 2617 ? 'type="submit" value="' + lang.booking_message_step_button + '"' 2618 : 'type="button" onclick="booking.stepsHandler(\'fields\', \'show\')" ' + 'value="' + lang.next_step + '"'; 2619 2620 if (bookingConfigs.Booking_type === 'time_range' 2621 && rlPageInfo.controller === 'booking_order' 2622 && !bookingConfigs.edit_action 2623 ) { 2624 html += ' class="disabled" disabled="disabled"'; 2625 } 2626 2627 html += ' /></form>'; 2628 html += '</div>'; 2629 2630 $('#booking_message').html(html); 2631 2632 if (typeof $.convertPrice == 'function') { 2633 $('#booking_message .value.amount, #booking_message .value.downpayment').convertPrice({ 2634 showCents: true, 2635 shortView: true 2636 }); 2637 } 2638 2639 // add copy of button which will be added after all fields 2640 if (rlPageInfo.controller === 'booking_order') { 2641 $('.booking_message_clone').remove(); 2642 2643 let $buttonForm = $('#booking_message').find('input[type="button"]'); 2644 let $button = $buttonForm.clone(); 2645 $buttonForm.hide(); 2646 $button.addClass('booking_message_clone'); 2647 $('#booking_message_obj').append( 2648 $('<div>', {class: 'table-cell'}).append( 2649 $('<div>', {class: 'name'}), 2650 $('<div>', {class: 'value'}).append( 2651 $button 2652 ) 2653 ) 2654 ); 2655 $button.show(); 2656 } 2657 2658 $('#booking_message_obj').fadeIn('slow'); 2659 2660 if (rlPageInfo.controller === 'listing_details') { 2661 flynax.slideTo('#area_booking'); 2662 } 2663 2664 if (rlPageInfo.controller === 'booking_order') { 2665 self.dateTimeRangeHandler(); 2666 2667 if (bookingConfigs.Booking_type === 'time_range') { 2668 self.escortFieldsValidateHandler(); 2669 self.escortAmountHandler(); 2670 2671 if (bookingConfigs.edit_action) { 2672 $('[name="escort_duration"]').change(); 2673 } 2674 } 2675 } 2676 } else { 2677 html += '<div class="name"><div><span>'; 2678 2679 html += bookingConfigs.Booking_type === 'time_range' 2680 ? lang.booking_escort_date 2681 : lang.booking_checkin; 2682 2683 html += '</span></div></div>'; 2684 html += '<div class="value">'; 2685 2686 html += bookingConfigs.check_in && bookingConfigs.Booking_type !== 'time_range' 2687 ? parameters.start_book + ' - ' + bookingConfigs.check_in 2688 : parameters.start_book; 2689 2690 html += '<span style="margin: 0 5px;">/</span><a href="javascript:void(0)" '; 2691 html += 'onclick="booking.escortChangeDate()">'; 2692 html += lang['booking_button_select_date'] + '</a>'; 2693 2694 html += '</div>'; 2695 2696 // update start date 2697 $('#booking_message').find('form input[name="start_date"]').val(bookingConfigs.db_start); 2698 2699 // update start date value 2700 $('#booking_message').find('form input[name="start_date_value"]').val(parameters.start_book); 2701 2702 // update date for user 2703 $('.table-cell.escort-date').html(html); 2704 } 2705 } 2706 } else if (steps === 'fields') { 2707 if (action === 'show') { 2708 if (rlPageInfo.controller === 'booking_order') { 2709 // Saving escort data to form 2710 if (bookingConfigs.Booking_type === 'time_range') { 2711 var $bookingForm = $('#booking_message'); 2712 2713 $bookingForm.find('[name="checkin"]').val(bookingConfigs.escort_type_service); 2714 $bookingForm.find('[name="checkout"]').val(bookingConfigs.escort_time_service); 2715 $bookingForm.find('[name="end_date"]').val($('[name="escort_duration"] option:selected').val()); 2716 $bookingForm.find('[name="total_cost"]').val(bookingConfigs.total_cost); 2717 } 2718 2719 var $booking_form = $('#booking_message form'); 2720 var action_url = $booking_form.attr('action'); 2721 2722 $booking_form.find('[type="button"]') 2723 .addClass('disabled') 2724 .attr('disabled', true) 2725 .val(lang.loading); 2726 2727 if (action_url) { 2728 if (rlConfig.mod_rewrite) { 2729 action_url = action_url.replace('.html', '/') + 'contact-details.html'; 2730 action_url += bookingConfigs.edit_action ? '?edit' : ''; 2731 } else { 2732 action_url = action_url + '&step=contact-details'; 2733 action_url += bookingConfigs.edit_action ? '&edit' : ''; 2734 } 2735 2736 $booking_form.attr('action', action_url); 2737 $booking_form.submit(); 2738 } 2739 } else { 2740 $('#step_2').fadeIn('slow'); 2741 self.bookingFieldsValidator(); 2742 $('#booking_message [type="button"]').closest('.table-cell').hide(); 2743 } 2744 } else if (action === 'hide') { 2745 $('#step_2').fadeOut('fast'); 2746 } 2747 } else if (steps === 'all') { 2748 if (action === 'hide') { 2749 $('#step_2, #booking_message_obj').fadeOut('fast'); 2750 bookingConfigs.first = 0; 2751 self.book_color(true); 2752 } 2753 } else if (steps === 'update_period') { 2754 if (action === 'update') { 2755 if (bookingConfigs.Booking_type === 'date_time_range' 2756 && bookingConfigs.listing_check_in 2757 && bookingConfigs.listing_check_out 2758 ) { 2759 /* build html for check in field */ 2760 checkin_html = '<div class="name"><div><span>' + lang.booking_checkin; 2761 checkin_html += '</span></div></div>'; 2762 checkin_html += '<div class="field start_date">'; 2763 2764 // block unavailable time 2765 $('[name="f[booking_check_in]"] option').each(function(){ 2766 $(this).attr('disabled', 'disabled'); 2767 2768 if ($(this).attr('value') === bookingConfigs.listing_check_in) { 2769 $(this).removeAttr('disabled').attr('selected', 'selected'); 2770 2771 return false;
2772 } 2773 }); 2774 2775 checkin_html += bookingConfigs.start_date_value + ' - '; 2776 checkin_html += $('#booking_checkin_field').html(); 2777 checkin_html += '</div>'; 2778 2779 $('.table-cell.check-in').html(checkin_html); 2780 /* end html for check-in field */ 2781 2782 /* build html for check-out field */ 2783 checkout_html = '<div class="name"><div><span>' + lang.booking_checkout; 2784 checkout_html += '</span></div></div>'; 2785 checkout_html += '<div class="field end_date">'; 2786 2787 $('[name="f[booking_check_out]"] option[value="0"]').attr('disabled', 'disabled'); 2788 2789 // block unavailable time 2790 $($('[name="f[booking_check_out]"] option').get().reverse()).each(function(){ 2791 $(this).attr('disabled', 'disabled'); 2792 2793 if ($(this).attr('value') === bookingConfigs.listing_check_out) { 2794 $(this).removeAttr('disabled').attr('selected', 'selected'); 2795 2796 return false; 2797 } 2798 }); 2799 2800 checkout_html += '<b>' + bookingConfigs.end_date_value + '</b> - '; 2801 checkout_html += $('#booking_checkout_field').html(); 2802 checkout_html += '</div>'; 2803 2804 $('.table-cell.check-out').html(checkout_html); 2805 /* end html for check-out field */ 2806 2807 self.dateTimeRangeHandler(); 2808 } else { 2809 if (bookingConfigs.start_date_value) { 2810 let start_date = bookingConfigs.check_in 2811 ? '<b>' + bookingConfigs.start_date_value + '</b> - ' + bookingConfigs.check_in 2812 : '<b>' + bookingConfigs.start_date_value + '</b>'; 2813 2814 $('#area_booking .field.start_date').html(start_date); 2815 } 2816 2817 if (bookingConfigs.end_date_value) { 2818 let end_date = bookingConfigs.check_out 2819 ? '<b>' + bookingConfigs.end_date_value + '</b> - ' + bookingConfigs.check_out 2820 : '<b>' + bookingConfigs.end_date_value + '</b>'; 2821 2822 $('#area_booking .field.end_date').html(end_date); 2823 } 2824 2825 if (bookingConfigs.Booking_type === 'date_range' && bookingConfigs.db_start && bookingConfigs.db_end) { 2826 let nightsCount = self.getCountDaysBetween2Timestamps( 2827 bookingConfigs.db_start, 2828 bookingConfigs.db_end 2829 ); 2830 2831 $('#area_booking .field.nights-count').html(nightsCount); 2832 } 2833 } 2834 2835 if (bookingConfigs.total_cost) { 2836 var price = bookingConfigs.system_currency_position === 'before' 2837 ? bookingConfigs.defCurrency + ' ' + bookingConfigs.total_cost 2838 : bookingConfigs.total_cost + ' ' + bookingConfigs.defCurrency; 2839 2840 $('#area_booking .field.total_cost').text(price); 2841 2842 if (typeof $.convertPrice == 'function') { 2843 $('#area_booking .field.total_cost').convertPrice({showCents: true, shortView: true}); 2844 } 2845 } 2846 2847 bookingConfigs.period_updated = true; 2848 } 2849 } 2850 }; 2851 2852 /** 2853 * Show calendar in modal window for escort package 2854 */ 2855 this.escortChangeDate = function() { 2856 $(document).flModal({ 2857 caption : lang['booking_button_select_date'], 2858 content : '<div id="booking_calendar" class="in_popup"' + '>' + lang['loading'] + '</div>', 2859 ready : function() { 2860 bookingConfigs['in_popup'] = true; 2861 bookingConfigs['s_id'] = 0; 2862 2863 self.getDates(bookingConfigs.listing_id, null, true); 2864 }, 2865 width : '400', 2866 height : 'auto', 2867 click : false 2868 }); 2869 }; 2870 2871 /** 2872 * Control filling escort fields (type, time, duration) 2873 */ 2874 this.escortFieldsValidateHandler = function() { 2875 var $typeSelector = $('[name="escort_rates"]'), 2876 $timeSelector = $('[name="f[booking_check_out]"]'), 2877 $durationSelector = $('[name="escort_duration"]'); 2878 2879 $typeSelector.change(function(){ 2880 // reset time/duration fields 2881 var type_service = Number($typeSelector.find('option:selected').val()); 2882 var hours_in_type = Number($typeSelector.find('option:selected').data('hours')); 2883 2884 self.selectFirstActiveOption($timeSelector); 2885 self.selectFirstActiveOption($durationSelector); 2886 2887 if (type_service < 0) { 2888 $timeSelector.addClass('disabled').attr('disabled', 'disabled'); 2889 $durationSelector.addClass('disabled').attr('disabled', 'disabled'); 2890 } else { 2891 bookingConfigs.escort_type_service = type_service; 2892 bookingConfigs.escort_type_service_title = trim($typeSelector.find('option:selected').html()); 2893 2894 // enable all options 2895 $durationSelector.find('option').removeClass('hide').removeAttr('disabled'); 2896 2897 if (hours_in_type) { 2898 let activeWorkOptions = $timeSelector.find('option:not(:disabled)').length; 2899 let activeWorkHours = (0.5 * activeWorkOptions) - 0.5; // Exclude last option with end of workday 2900 2901 // enable only options which can be used with selected type of service 2902 $durationSelector.find('option').each(function(){ 2903 var option_value = parseFloat($(this).attr('value')); 2904 2905 if ((option_value > 0 && option_value % hours_in_type !== 0) 2906 || (activeWorkHours > 0 && option_value > activeWorkHours) 2907 ) { 2908 $(this).attr('disabled', true).addClass('hide'); 2909 } 2910 }); 2911 2912 $durationSelector.removeClass('disabled').removeAttr('disabled'); 2913 } else { 2914 bookingConfigs['escort_duration'] = false;
2915 $durationSelector.addClass('disabled').attr('disabled', 'disabled'); 2916 } 2917 2918 if ($timeSelector.hasClass('disabled')) { 2919 $timeSelector.removeClass('disabled').removeAttr('disabled'); 2920 2921 if (Number($timeSelector.find('option:selected').val()) > 0 && hours_in_type) { 2922 $durationSelector.removeClass('disabled').removeAttr('disabled'); 2923 } 2924 } 2925 2926 self.selectFirstActiveOption($durationSelector); 2927 } 2928 2929 if (!bookingConfigs.Booking_repeatedly) { 2930 let $hourlyTime = $('.hourly-time .view'); 2931 2932 if (type_service >= 0) { 2933 $hourlyTime.text(trim($durationSelector.find('option:selected').html())); 2934 } else { 2935 $hourlyTime.text(lang.not_available); 2936 } 2937 } 2938 2939 self.updateEscortAvailabilityData(); 2940 }); 2941 2942 $timeSelector.change(function(){ 2943 var time = parseInt($timeSelector.find('option:selected').val()); 2944 2945 if (time > 0) { 2946 bookingConfigs.escort_time_service = $timeSelector.find('option:selected').val(); 2947 bookingConfigs.escortTimeServiceValue = trim($timeSelector.find('option:selected').html()); 2948 2949 if (parseInt($typeSelector.find('option:selected').data('hours')) > 1) { 2950 $durationSelector.removeClass('disabled').removeAttr('disabled'); 2951 } 2952 2953 // Enable all options 2954 $durationSelector.find('option').removeClass('hide').removeAttr('disabled'); 2955 2956 var hours_in_type = Number($typeSelector.find('option:selected').data('hours')); 2957 2958 if (hours_in_type) { 2959 let activeWorkHours = 0, currentTime = false; 2960 $timeSelector.find('option').each(function() { 2961 if (currentTime && !$(this).is(':disabled')) { 2962 activeWorkHours += 0.5; 2963 } 2964 2965 if ($(this).is(':selected')) { 2966 currentTime = true; 2967 } 2968 }); 2969 2970 // Enable only options which can be used with selected time and rest of time 2971 if (activeWorkHours === 0) { 2972 $durationSelector.find('option:not(:first)').attr('disabled', true).addClass('hide'); 2973 } else { 2974 $($durationSelector.find('option').get().reverse()).each(function(){ 2975 var optionValue = parseFloat($(this).attr('value')); 2976 2977 if ((optionValue > 0 && optionValue % hours_in_type !== 0) 2978 || (activeWorkHours > 0 && optionValue > activeWorkHours) 2979 ) { 2980 $(this).attr('disabled', true).addClass('hide'); 2981 } 2982 }); 2983 } 2984 } 2985 2986 self.selectFirstActiveOption($durationSelector); 2987 } else { 2988 $durationSelector.addClass('disabled').attr('disabled', 'disabled'); 2989 } 2990 }); 2991 2992 $durationSelector.change(function () { 2993 if (rlPageInfo.controller !== 'booking_requests') { 2994 return; 2995 } 2996 2997 bookingConfigs.escort_duration = $durationSelector.find('option:selected').val(); 2998 bookingConfigs.escort_duration_title = trim($durationSelector.find('option:selected').html()); 2999 }); 3000 }; 3001 3002 /** 3003 * Count total booking amount for escort 3004 */ 3005 this.escortAmountHandler = function() { 3006 let $nextButton = $('#booking_message input[type="button"]'), 3007 $amountContainer = $('#booking_message,#booking_details').find('.value.amount,.field.amount'), 3008 $answerContainer = $('#owner_actions'), 3009 $downpaymentContainer = $('.table-cell .value.downpayment'); 3010 3011 $('[name="escort_rates"],[name="f[booking_check_out]"],[name="escort_duration"]').change(function(){ 3012 let $selectedType = $('[name="escort_rates"] option:selected'), 3013 amount = 0, 3014 activeWorkHours = 0, 3015 $timeSelector = $('[name="f[booking_check_out]"]'), 3016 type = parseInt($selectedType.val()), 3017 time = parseInt($('[name="f[booking_check_out]"] option:selected').val()), 3018 duration = parseFloat($('[name="escort_duration"] option:selected').val()), 3019 price = parseFloat($selectedType.data('price')), 3020 hoursInType = parseFloat($selectedType.data('hours')); 3021 3022 $timeSelector.find('option').each(function() { 3023 if (!$(this).is(':disabled')) { 3024 activeWorkHours += 0.5; 3025 } 3026 }); 3027 3028 if (type !== -1 3029 && time !== 0 3030 && (duration !== -1 || (duration === -1 && !hoursInType)) 3031 && bookingConfigs.db_start 3032 && price 3033 && (activeWorkHours && activeWorkHours >= hoursInType) 3034 ) { 3035 $nextButton.removeClass('disabled').removeAttr('disabled'); 3036 $answerContainer.removeClass('hide'); 3037 3038 if (rlPageInfo.controller === 'booking_order') { 3039 $('.booking_message_clone').removeClass('disabled').removeAttr('disabled'); 3040 } 3041 3042 // show price without calculation 3043 if (duration === -1 && !hoursInType) { 3044 amount = price; 3045 } else { 3046 bookingConfigs.escort_duration = duration; 3047 3048 if (hoursInType === duration) { 3049 amount = price; 3050 } else { 3051 duration = hoursInType > 0 ? duration / hoursInType : duration; 3052 amount = Math.round((price * duration) * 100) / 100; 3053 } 3054 } 3055 3056 bookingConfigs.total_cost = amount; 3057 3058 amount = bookingConfigs.system_currency_position === 'before' 3059 ? bookingConfigs.defCurrency + ' ' + amount 3060 : amount + ' ' + bookingConfigs.defCurrency; 3061 3062 $amountContainer.text(amount); 3063 3064 if (typeof $.convertPrice == 'function') { 3065 $amountContainer.convertPrice({showCents: true, shortView: true}); 3066 } 3067 3068 // update downpayment if it exist 3069 var downpayment = self.countPrepayment(bookingConfigs.total_cost); 3070 if (bookingConfigs.prepayment) { 3071 $downpaymentContainer.text(downpayment); 3072 3073 if (typeof $.convertPrice == 'function') { 3074 $downpaymentContainer.convertPrice({showCents: true, shortView: true}); 3075 } 3076 } 3077 } else { 3078 $nextButton.addClass('disabled').attr('disabled', 'disabled'); 3079 $answerContainer.addClass('hide'); 3080 $amountContainer.text(lang.not_available); 3081 3082 if (bookingConfigs.prepayment) { 3083 $downpaymentContainer.text(lang.not_available); 3084 } 3085 3086 if (rlPageInfo.controller === 'booking_order') { 3087 $('.booking_message_clone').addClass('disabled').attr('disabled', 'disabled'); 3088 } 3089 } 3090 }); 3091 }; 3092 3093 /** 3094 * Count prepayment by price 3095 * @param {string} price 3096 * @return {string} 3097 */ 3098 this.countPrepayment = function(price) { 3099 var downpayment = lang.not_available; 3100 3101 if (price && bookingConfigs.prepayment) { 3102 downpayment = (parseFloat(price.toString().replace(/[^0-9.]+/g, "")) / 100) * bookingConfigs.prepayment; 3103 downpayment = Math.round((downpayment) * 100) / 100; 3104 downpayment = bookingConfigs.system_currency_position === 'before' 3105 ? bookingConfigs.defCurrency + ' ' + downpayment 3106 : downpayment + ' ' + bookingConfigs.defCurrency; 3107 } 3108 3109 return downpayment; 3110 }; 3111 3112 /** 3113 * Get availability of selected day 3114 * 3115 * @since 3.2.0 3116 *
3117 * @param day - Date in timestamp 3118 * @returns {string|boolean} 3119 */ 3120 this.getAvailabilityOfDay = function(day) { 3121 day = Number(day); 3122 3123 if (!day) { 3124 return false; 3125 } 3126 3127 var av_mon = bookingConfigs.availability.day_1 ? bookingConfigs.availability.day_1 : ''; 3128 var av_tue = bookingConfigs.availability.day_2 ? bookingConfigs.availability.day_2 : ''; 3129 var av_wed = bookingConfigs.availability.day_3 ? bookingConfigs.availability.day_3 : ''; 3130 var av_thu = bookingConfigs.availability.day_4 ? bookingConfigs.availability.day_4 : ''; 3131 var av_fri = bookingConfigs.availability.day_5 ? bookingConfigs.availability.day_5 : ''; 3132 var av_sat = bookingConfigs.availability.day_6 ? bookingConfigs.availability.day_6 : ''; 3133 var av_sun = bookingConfigs.availability.day_7 ? bookingConfigs.availability.day_7 : ''; 3134 3135 var selected_day = self.getDateByTimeZone(day, 'ddd').toLowerCase(); 3136 var current_av = ''; 3137 3138 // get availability data of selected day 3139 if (selected_day === 'mon' && av_mon) { 3140 current_av = av_mon; 3141 } else if (selected_day === 'tue' && av_tue) { 3142 current_av = av_tue; 3143 } else if (selected_day === 'wed' && av_wed) { 3144 current_av = av_wed; 3145 } else if (selected_day === 'thu' && av_thu) { 3146 current_av = av_thu; 3147 } else if (selected_day === 'fri' && av_fri) { 3148 current_av = av_fri; 3149 } else if (selected_day === 'sat' && av_sat) { 3150 current_av = av_sat; 3151 } else if (selected_day === 'sun' && av_sun) { 3152 current_av = av_sun; 3153 } 3154 3155 return current_av; 3156 }; 3157 3158 /** 3159 * Update data in "Time of Service" field 3160 */ 3161 this.updateEscortAvailabilityData = function() { 3162 let $timeSelector = $('[name="f[booking_check_out]"]'); 3163 let $timeOptions = $timeSelector.find('option'); 3164 let $selectedRate = $('select[name="escort_rates"] option[value="' + bookingConfigs.escort_type_service + '"]'); 3165 let rateType = $selectedRate.length ? $selectedRate.data('type') : null; 3166 let rateIndex = $selectedRate.length ? $selectedRate.val() : null; 3167 3168 // reset options 3169 $($timeOptions.get()).each(function(){ 3170 $(this).removeAttr('disabled'); 3171 3172 if (!bookingConfigs.edit_action) { 3173 $(this).removeAttr('selected'); 3174 } 3175 }); 3176 3177 var current_av = self.getAvailabilityOfDay(bookingConfigs.db_start); 3178 3179 // update by availability data 3180 if (current_av) { 3181 var av_from = ''; 3182 if (current_av[0] !== lang.time_midnight && current_av[0] !== lang.time_noon) { 3183 av_from = current_av[0]; 3184 } else { 3185 if (current_av[0] === lang.time_midnight) { 3186 av_from = '12:00 am'; 3187 } else if (current_av[0] === lang.time_noon) { 3188 av_from = '12:00 pm'; 3189 } 3190 } 3191 3192 var av_to = ''; 3193 if (current_av[1] !== lang.time_midnight && current_av[1] !== lang.time_noon) { 3194 av_to = current_av[1]; 3195 } else { 3196 if (current_av[1] === lang.time_midnight) { 3197 av_to = '12:00 am'; 3198 } else if (current_av[1] === lang.time_noon) { 3199 av_to = '12:00 pm'; 3200 } 3201 } 3202 3203 // set "from" 3204 $($timeOptions.get()).each(function(){ 3205 $(this).attr('disabled', 'disabled'); 3206 var option_value = $(this).attr('value'); 3207 3208 if (option_value === av_from) { 3209 $(this).removeAttr('disabled'); 3210 3211 if (!bookingConfigs.edit_action) { 3212 $(this).attr('selected', 'selected'); 3213 bookingConfigs.escort_time_service = option_value; 3214 } else { 3215 bookingConfigs.escort_time_service = bookingConfigs.check_out; 3216 } 3217 3218 return false;
3219 } 3220 }); 3221 3222 // set "to" 3223 $($timeOptions.get().reverse()).each(function(){ 3224 $(this).attr('disabled', 'disabled'); 3225 3226 if ($(this).attr('value').replace(' ' + lang.booking_time_next_day, '') === av_to) { 3227 // Disable the end of work-day 3228 $(this).removeAttr('disabled'); 3229 return false; 3230 } 3231 }); 3232 3233 // Disable already booked time by other bookings 3234 if (bookingConfigs.usBook) { 3235 for (var i in bookingConfigs.usBook) { 3236 if (!bookingConfigs.usBook.hasOwnProperty(i)) { 3237 continue; 3238 } 3239 3240 var userBook = bookingConfigs.usBook[i]; 3241 3242 // Skip booking from other days 3243 if (userBook[1] != bookingConfigs.db_start) { 3244 continue; 3245 } 3246 3247 // Skip own request in requests page 3248 if (rlPageInfo.controller === 'booking_requests' && userBook[3] == bookingConfigs.request_id) { 3249 continue; 3250 } 3251 3252 // Miss all booked time which using other type of rate 3253 if (((rateType && rateIndex !== userBook[8]) || !rateType) 3254 && bookingConfigs.Booking_repeatedly === false 3255 && bookingConfigs.is_escort === false 3256 ) { 3257 continue; 3258 } 3259 3260 var checkInTime = userBook[5]; 3261 var duration = userBook[6]; 3262 var countDisabledOptions = duration * 2; // 1h => 30m * 2, 2h => 30m * 4 and etc. 3263 3264 $($timeOptions.get()).each(function(){ 3265 if ($(this).val() === '0' || $(this).val().indexOf(lang.booking_time_next_day) > 0) { 3266 return true; 3267 } 3268 3269 if ($(this).val() === checkInTime) { 3270 $(this).attr('disabled', 'disabled'); 3271 var $option = $(this); 3272 3273 for (var i = 1; i <= countDisabledOptions; i++) { 3274 $option.attr('disabled', 'disabled'); 3275 $option = $option.next(); 3276 } 3277 } 3278 }); 3279 } 3280 } 3281 3282 self.selectFirstActiveOption($timeSelector); 3283 bookingConfigs.escort_time_service = $timeSelector.find('option:selected').val(); 3284 } 3285 }; 3286 3287 /** 3288 * Check booking fields before submit form 3289 */ 3290 this.bookingFieldsValidator = function() { 3291 $('#checkValid').unbind('click').click(function(){ 3292 var error_fields = field_names = cond_fields_names = ''; 3293 $(this).closest('form').submit(function(){ return false }); 3294 3295 // get all fields from form 3296 $(this).closest('form').find('.submit-cell:not(.buttons)').each(function(){ 3297 var field = $(this).find('input,textarea'); 3298 var field_name = field.closest('.submit-cell').find('.name').text().replace('* ', '').trim(); 3299 var field_key = field.attr('name'); 3300 var field_val = field.val(); 3301 3302 // check "text", "number" and "textarea" fields 3303 if (field.hasClass('required') && !field.hasClass('bool') && !field_val) { 3304 // collect field names 3305 field_names += (field_names ? ',' : '') + '"<b>' + field_name + '</b>"'; 3306 3307 // collect field keys 3308 if (error_fields.indexOf(field_key) < 0) { 3309 error_fields = error_fields ? error_fields + ',' + field_key : field_key; 3310 } 3311 } 3312 3313 // check conditions (isUrl, isDomain, isEmail) 3314 if (field.hasClass('required') 3315 && ((field.hasClass('isUrl') && !self.checkCondition(field_val, 'url')) 3316 || (field.hasClass('isDomain') && !self.checkCondition(field_val, 'domain')) 3317 || (field.hasClass('isEmail') && !self.checkCondition(field_val, 'mail')) 3318 ) 3319 ) { 3320 // collect field names 3321 cond_fields_names += (cond_fields_names ? ',' : '') + '"<b>' + field_name + '</b>"'; 3322 3323 // collect field keys & if key not exist in list already 3324 if (error_fields.indexOf(field_key) < 0) { 3325 error_fields = error_fields ? error_fields + ',' + field_key : field_key; 3326 } 3327 } 3328 }); 3329 3330 if (error_fields && (field_names || cond_fields_names)) { 3331 // some fields are empty && values incorrect 3332 if (error_fields && field_names && cond_fields_names) { 3333 var errors_content = '<ul>'; 3334 errors_content += '<li>'; 3335 errors_content += lang['booking_field_error'].replace('error_field', field_names); 3336 errors_content += '</li>'; 3337 errors_content += '<li>'; 3338 errors_content += lang['booking_inccorect_field_error'].replace('error_field', cond_fields_names); 3339 errors_content += '</li>'; 3340 3341 printMessage('error', errors_content, error_fields); 3342 } 3343 // some fields are empty 3344 else if (error_fields && field_names) { 3345 printMessage( 3346 'error', 3347 lang['booking_field_error'].replace('error_field', field_names), 3348 error_fields 3349 ); 3350 } 3351 // values incorrect 3352 else if (error_fields && cond_fields_names) { 3353 printMessage( 3354 'error', 3355 lang['booking_inccorect_field_error'].replace('error_field', cond_fields_names), 3356 error_fields 3357 ); 3358 } 3359 } else { 3360 $(this).closest('form').unbind('submit').submit(function(){ 3361 $('#checkValid').addClass('disabled').attr('disabled', true).val(lang['loading']); 3362 3363 if (bookingConfigs['booking_order_page']) { 3364 var $booking_form = $(this); 3365 var action_url = bookingConfigs['booking_order_page']; 3366 3367 if (action_url) { 3368 if (bookingConfigs.prepayment) { 3369 if (rlConfig['mod_rewrite']) { 3370 action_url = action_url.replace('.html', '/') + 'prepayment.html'; 3371 } else { 3372 action_url = action_url + '&step=prepayment'; 3373 } 3374 } 3375 3376 $booking_form.attr('action', action_url); 3377 } 3378 } 3379 3380 return true; 3381 }); 3382 } 3383 }); 3384 }; 3385 3386 /** 3387 * Validate string by condition 3388 * @param {string} string - Incoming string 3389 * @param {string} mode - Type of condition 3390 * @return {bool} 3391 */ 3392 this.checkCondition = function(string, mode) { 3393 var pattern; 3394 3395 if (mode === 'domain') { 3396 pattern = /\S+\.\S+/; 3397 } else if (mode === 'url') { 3398 pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; 3399 } else if (mode === 'mail') { 3400 pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 3401 } 3402 3403 return string && pattern ? pattern.test(string) : false;
3404 }; 3405 3406 /** 3407 * Copying data from selectors to output form 3408 */ 3409 this.dateTimeRangeHandler = function() { 3410 // check-in time field 3411 $('[name="f[booking_check_in]"]').change(function(){ 3412 var checkin_time = $(this).val(); 3413 $('[name="checkin"]').val(checkin_time); 3414 3415 // decrease booking amount if user reduce time of check in 3416 if (checkin_time && bookingConfigs['booking_regular_per_hour']) { 3417 var new_checkin_time = checkin_time.split(':'); 3418 var old_checkin_time = rlPageInfo.controller === 'booking_requests' 3419 ? bookingConfigs['listing_check_in'].split(':') 3420 : bookingConfigs['check_in'].split(':'); 3421 3422 var new_hour = new_checkin_time[0] ? parseInt(new_checkin_time[0]) : 0; 3423 var time_period = new_checkin_time[1] ? new_checkin_time[1].split(' ') : false; 3424 new_hour = time_period['1'] && time_period['1'] === 'pm' && new_hour < 12 ? new_hour + 12 : new_hour; 3425 3426 var old_hour = old_checkin_time[0] ? parseInt(old_checkin_time[0]) : 0; 3427 time_period = old_checkin_time[1] ? old_checkin_time[1].split(' ') : false; 3428 old_hour = time_period['1'] && time_period['1'] === 'pm' && old_hour < 12 ? old_hour + 12 : old_hour; 3429 3430 var new_minutes = new_checkin_time[1] ? parseInt(new_checkin_time[1]) : 0; 3431 var old_minutes = old_checkin_time[1] ? parseInt(old_checkin_time[1]) : 0; 3432 3433 if (new_hour > old_hour || (new_hour === old_hour && new_minutes > old_minutes)) { 3434 var difference_time = new_hour - old_hour; 3435 difference_time = new_minutes > old_minutes ? difference_time + 0.5 : difference_time; 3436 3437 var price_per_hour = bookingConfigs.booking_regular_per_hour; 3438 var difference_price = difference_time && price_per_hour 3439 ? difference_time * price_per_hour 3440 : price_per_hour; 3441 3442 var current_booking_amount = parseFloat(bookingConfigs.total_cost); 3443 3444 if (current_booking_amount && difference_price) { 3445 var new_booking_amount = Math.round((current_booking_amount - difference_price) * 100) / 100; 3446 3447 $('[name="total_cost"]').val(new_booking_amount); 3448 3449 $('.amount').text( 3450 bookingConfigs.system_currency_position === 'before' 3451 ? bookingConfigs.defCurrency + ' ' + new_booking_amount 3452 : new_booking_amount + ' ' + bookingConfigs.defCurrency 3453 ); 3454 } 3455 } else { 3456 $('[name="total_cost"]').val(bookingConfigs.total_cost); 3457 $('.amount').text( 3458 bookingConfigs.system_currency_position === 'before' 3459 ? bookingConfigs.defCurrency + ' ' + bookingConfigs.total_cost 3460 : bookingConfigs.total_cost + ' ' + bookingConfigs.defCurrency 3461 ); 3462 } 3463 } 3464 }); 3465 3466 // check-out time field 3467 $('[name="f[booking_check_out]"]').change(function(){ 3468 var checkout_time = $(this).val(); 3469 $('[name="checkout"]').val(checkout_time); 3470 3471 // Decrease booking amount if user reduce time of check out 3472 if (checkout_time && bookingConfigs['booking_regular_per_hour']) { 3473 var new_checkout_time = checkout_time.split(':'); 3474 var old_checkout_time = rlPageInfo.controller == 'booking_requests' 3475 ? bookingConfigs['listing_check_out'].split(':') 3476 : bookingConfigs['check_out'].split(':'); 3477 3478 var new_hour = new_checkout_time[0] ? parseInt(new_checkout_time[0]) : 0; 3479 var time_period = new_checkout_time[1] ? new_checkout_time[1].split(' ') : false; 3480 3481 if (time_period['1'] && time_period['1'] == 'pm' && new_hour < 12) { 3482 new_hour += 12; 3483 } else if (time_period['1'] && time_period['1'] == 'am' && new_hour == 12) { 3484 new_hour = 0; 3485 } 3486 3487 var old_hour = old_checkout_time[0] ? parseInt(old_checkout_time[0]) : 0; 3488 time_period = old_checkout_time[1] ? old_checkout_time[1].split(' ') : false;
3489 old_hour = time_period['1'] && time_period['1'] == 'pm' && old_hour < 12 ? old_hour + 12 : old_hour; 3490 3491 var new_minutes = new_checkout_time[1] ? parseInt(new_checkout_time[1]) : 0; 3492 var old_minutes = old_checkout_time[1] ? parseInt(old_checkout_time[1]) : 0; 3493 3494 if (new_hour < old_hour || (new_hour == old_hour && new_minutes != old_minutes)) { 3495 var difference_time = old_hour - new_hour; 3496 difference_time = new_minutes > old_minutes ? difference_time - 0.5 : difference_time; 3497 3498 var price_per_hour = bookingConfigs['booking_regular_per_hour']; 3499 var difference_price = difference_time && price_per_hour 3500 ? (Math.round((difference_time * price_per_hour) * 100) / 100) 3501 : price_per_hour; 3502 3503 var current_booking_amount = parseFloat(bookingConfigs['total_cost']); 3504 3505 if (current_booking_amount && difference_price) { 3506 var new_booking_amount = Math.round((current_booking_amount - difference_price) * 100) / 100; 3507 3508 $('[name="total_cost"]').val(new_booking_amount); 3509 3510 $('.amount').text( 3511 bookingConfigs['system_currency_position'] == 'before' 3512 ? bookingConfigs['defCurrency'] + ' ' + new_booking_amount 3513 : new_booking_amount + ' ' + bookingConfigs['defCurrency'] 3514 ); 3515 } 3516 } else { 3517 $('[name="total_cost"]').val(bookingConfigs['total_cost']); 3518 $('.amount').text( 3519 bookingConfigs['system_currency_position'] == 'before' 3520 ? bookingConfigs['defCurrency'] + ' ' + bookingConfigs['total_cost'] 3521 : bookingConfigs['total_cost'] + ' ' + bookingConfigs['defCurrency'] 3522 ); 3523 } 3524 } 3525 }); 3526 }; 3527 3528 /** 3529 * Handler for "Change Period" button 3530 */ 3531 this.changePeriodHandler = function() { 3532 // Save request data 3533 tmpBookingConfigs.db_start = bookingConfigs.db_start; 3534 tmpBookingConfigs.start_date_value = bookingConfigs.start_date_value; 3535 tmpBookingConfigs.db_end = bookingConfigs.db_end; 3536 tmpBookingConfigs.end_date_value = bookingConfigs.end_date_value; 3537 tmpBookingConfigs.total_cost = self.str2money(bookingConfigs.total_cost); 3538 tmpBookingConfigs.check_in = bookingConfigs.check_in; 3539 tmpBookingConfigs.check_out = bookingConfigs.check_out; 3540 tmpBookingConfigs.escort_duration = bookingConfigs.escort_duration; 3541 tmpBookingConfigs.escort_duration_title = bookingConfigs.escort_duration_title; 3542 tmpBookingConfigs.escort_type_service = bookingConfigs.escort_type_service; 3543 tmpBookingConfigs.escort_type_service_title = bookingConfigs.escort_type_service_title; 3544 tmpBookingConfigs.escort_time_service = bookingConfigs.escort_time_service; 3545 3546 $('#change_period').click(function() { 3547 if ($(this).hasClass('process')) { 3548 $('#owner_actions').removeClass('hide'); 3549 $(this).removeClass('process').text(lang.booking_button_change_period); 3550 $('#cancel_changes').fadeOut(); 3551 $('#booking_calendar').addClass('disabled loading'); 3552 3553 if (bookingConfigs.Booking_type === 'date_time_range') { 3554 var $checkInCont = $('.check-in [name="f[booking_check_in]"]'), 3555 $checkOutCont = $('.check-out [name="f[booking_check_out]"]'); 3556 3557 let checkin_time = $checkInCont.length && $checkInCont.val() !== '0' 3558 && $checkInCont.val() !== bookingConfigs.check_in 3559 ? $checkInCont.val() 3560 : bookingConfigs.check_in; 3561 3562 let checkInTimeHuman = $checkInCont.length && $checkInCont.val() !== '0' 3563 ? $checkInCont.find('option:selected').html() 3564 : bookingConfigs.check_in 3565 3566 bookingConfigs.check_in = checkin_time; 3567 3568 if (bookingConfigs.start_date_value) { 3569 let start_date = checkInTimeHuman 3570 ? '<b>' + bookingConfigs.start_date_value + '</b> - ' + checkInTimeHuman 3571 : '<b>' + bookingConfigs.start_date_value + '</b>'; 3572 3573 $('#area_booking .field.start_date').html(start_date); 3574 } 3575 3576 let checkout_time = $checkOutCont.length && $checkOutCont.val() !== '0' 3577 && $checkOutCont.val() !== bookingConfigs.check_out 3578 ? $checkOutCont.val() 3579 : bookingConfigs.check_out; 3580 3581 let checkOutTimeHuman = $checkOutCont.length && $checkOutCont.val() !== '0' 3582 ? $checkOutCont.find('option:selected').html() 3583 : bookingConfigs.check_out 3584 3585 bookingConfigs.check_out = checkout_time; 3586 3587 if (bookingConfigs.end_date_value) { 3588 let end_date = checkOutTimeHuman 3589 ? '<b>' + bookingConfigs.end_date_value + '</b> - ' + checkOutTimeHuman 3590 : '<b>' + bookingConfigs.end_date_value + '</b>'; 3591 3592 $('#area_booking .field.end_date').html(end_date); 3593 } 3594 3595 if (bookingConfigs.check_in !== bookingConfigs.listing_check_in 3596 || bookingConfigs.check_out !== bookingConfigs.listing_check_out 3597 ) { 3598 bookingConfigs.period_updated = true; 3599 } 3600 } else if (bookingConfigs.Booking_type === 'time_range') { 3601 // Move selectors to initial place 3602 $('[name="escort_rates"]').detach().appendTo($('#escort_rates_obj')); 3603 $('[name="f[booking_check_out]"]').detach().appendTo($('#booking_checkout_field')); 3604 $('[name="escort_duration"]').detach().appendTo($('#escort_duration_obj')); 3605 3606 if (bookingConfigs.start_date_value) { 3607 $('#area_booking .field.start_date').html('<b>' + bookingConfigs.start_date_value + '</b>'); 3608 } 3609 3610 if (bookingConfigs.escort_type_service_title) { 3611 $('#area_booking .field.type').html(bookingConfigs.escort_type_service_title); 3612 } 3613 3614 if (bookingConfigs.escortTimeServiceValue) { 3615 $('#area_booking .field.time').html(bookingConfigs.escortTimeServiceValue); 3616 } 3617 3618 if (bookingConfigs.escort_duration_title) { 3619 $('#area_booking .field.duration').html(bookingConfigs.escort_duration_title); 3620 } 3621 3622 $('#area_booking').removeClass('request-details'); 3623 3624 bookingConfigs.period_updated = true; 3625 } 3626 } else { 3627 $('#owner_actions').addClass('hide'); 3628 $(this).text(lang.save).addClass('process'); 3629 $(this).next().fadeIn('fast'); 3630 3631 if (bookingConfigs.Booking_type === 'time_range') { 3632 var $bookingDetailsContainer = $('#booking_details'), 3633 $typeContainer = $('[name="escort_rates"]'), 3634 $timeContainer = $('[name="f[booking_check_out]"]'), 3635 $durationContainer = $('[name="escort_duration"]'); 3636 3637 // Add padding in details 3638 $('#area_booking').addClass('request-details'); 3639 3640 // Add "Change date" button to "Date Of Service" field 3641 var html = '<a id="change_date_button" href="javascript:void(0)">'; 3642 html += lang.booking_button_select_date + '</a>'; 3643 3644 $bookingDetailsContainer.find('div.field.start_date') 3645 .html(trim($bookingDetailsContainer.find('div.field.start_date').html()) + html); 3646 3647 $('#change_date_button').click(function() { 3648 self.escortChangeDate(); 3649 }); 3650 3651 // Add escort rates to "Type Of Service" field 3652 if (bookingConfigs.check_in) { 3653 $typeContainer.find('option[value="' + bookingConfigs.check_in + '"]').attr('selected', true); 3654 $typeContainer = $typeContainer.detach(); 3655 $typeContainer.appendTo($bookingDetailsContainer.find('div.field.type').html('')); 3656 } 3657 3658 // Add checkout-time selector to "Time Of Service" field 3659 if (bookingConfigs.check_out) { 3660 self.updateEscortAvailabilityData(); 3661 3662 $timeContainer.find('option[value="' + bookingConfigs.check_out + '"]').attr('selected', true); 3663 $timeContainer.removeClass('disabled').removeAttr('disabled'); 3664 $timeContainer = $timeContainer.detach(); 3665 $timeContainer.appendTo($bookingDetailsContainer.find('div.field.time').html('')); 3666 } 3667 3668 // Add hours selector to "Duration (Hours)" field 3669 if (bookingConfigs.db_end) { 3670 $durationContainer.find('option[value="' + bookingConfigs.db_end + '"]').attr('selected', true); 3671 $durationContainer.removeClass('disabled').removeAttr('disabled'); 3672 } 3673 $durationContainer = $durationContainer.detach(); 3674 3675 if (!bookingConfigs.Booking_repeatedly) {
3676 $durationContainer = $('<div>', {class: 'hourly-time'}).append( 3677 $('<div>', {class: 'view'}).text(lang.not_available), 3678 $('<div>', {class: 'origin hide'}).append($durationContainer) 3679 ) 3680 } 3681 3682 $durationContainer.appendTo($bookingDetailsContainer.find('div.field.duration').html('')); 3683 3684 self.escortFieldsValidateHandler(); 3685 self.escortAmountHandler(); 3686 3687 // Hide unavailable values in "Duration" field 3688 var hours_in_type = parseInt($typeContainer.find('option:selected').data('hours')); 3689 3690 $durationContainer.find('option').each(function(){ 3691 var option_value = parseInt($(this).attr('value')); 3692 3693 if (option_value > 0 && option_value % hours_in_type !== 0) { 3694 $(this).attr('disabled', true).addClass('hide'); 3695 } 3696 }); 3697 3698 $('div.field.duration').closest('div.table-cell').removeClass('hide'); 3699 $typeContainer.change(); 3700 } else { 3701 self.getDates(bookingConfigs.listing_id, null, true); 3702 } 3703 } 3704 }); 3705 }; 3706 3707 /** 3708 * Revert data of request to initial 3709 */ 3710 this.revertRequestChanges = function() { 3711 if (tmpBookingConfigs['db_start'] && tmpBookingConfigs['db_end']) { 3712 $('#cancel_changes').click(function(){ 3713 bookingConfigs['db_start'] = tmpBookingConfigs['db_start']; 3714 bookingConfigs['start_date_value'] = tmpBookingConfigs['start_date_value']; 3715 bookingConfigs['db_end'] = tmpBookingConfigs['db_end']; 3716 bookingConfigs['end_date_value'] = tmpBookingConfigs['end_date_value']; 3717 bookingConfigs['total_cost'] = tmpBookingConfigs['total_cost']; 3718 bookingConfigs['check_in'] = tmpBookingConfigs['check_in']; 3719 bookingConfigs['check_out'] = tmpBookingConfigs['check_out'] 3720 bookingConfigs['escort_duration'] = tmpBookingConfigs['escort_duration']; 3721 bookingConfigs['escort_duration_title'] = tmpBookingConfigs['escort_duration_title']; 3722 bookingConfigs['escort_type_service'] = tmpBookingConfigs['escort_type_service']; 3723 bookingConfigs['escort_type_service_title'] = tmpBookingConfigs['escort_type_service_title']; 3724 bookingConfigs['escort_time_service'] = tmpBookingConfigs['escort_time_service']; 3725 3726 self.getDates(bookingConfigs['listing_id']); 3727 self.stepsHandler('update_period', 'update'); 3728 3729 if (bookingConfigs['Booking_type'] == 'date_time_range') { 3730 if (bookingConfigs['start_date_value']) { 3731 var start_date = bookingConfigs['check_in'] 3732 ? '<b>' + bookingConfigs['start_date_value'] + '</b> - ' + bookingConfigs['check_in'] 3733 : '<b>' + bookingConfigs['start_date_value'] + '</b>'; 3734 3735 $('#area_booking .field.start_date').html(start_date); 3736 } 3737 3738 if (bookingConfigs['end_date_value']) { 3739 var end_date = bookingConfigs['check_out'] 3740 ? '<b>' + bookingConfigs['end_date_value'] + '</b> - ' + bookingConfigs['check_out'] 3741 : '<b>' + bookingConfigs['end_date_value'] + '</b>'; 3742 3743 $('#area_booking .field.end_date').html(end_date); 3744 } 3745 } else if (bookingConfigs['Booking_type'] == 'time_range') { 3746 // move selectors to inital place 3747 $('[name="escort_rates"]').detach().appendTo($('#escort_rates_obj')); 3748 $('[name="f[booking_check_out]"]').detach().appendTo($('#booking_checkout_field')); 3749 $('[name="escort_duration"]').detach().appendTo($('#escort_duration_obj')); 3750 3751 if (bookingConfigs['start_date_value']) { 3752 $('#area_booking .field.start_date').html('<b>' + bookingConfigs['start_date_value'] + '</b>'); 3753 } 3754 3755 if (bookingConfigs['escort_type_service_title']) { 3756 $('#area_booking .field.type').html(bookingConfigs['escort_type_service_title']); 3757 } 3758 3759 if (bookingConfigs['escort_time_service']) { 3760 $('#area_booking .field.time').html(bookingConfigs['escort_time_service']); 3761 } 3762 3763 if (bookingConfigs['escort_duration_title']) { 3764 $('#area_booking .field.duration').html(bookingConfigs['escort_duration_title']); 3765 } 3766 3767 $('#area_booking').removeClass('request-details'); 3768 } 3769 3770 $('#change_period').text(lang['booking_button_change_period']).removeClass('process'); 3771 $('#cancel_changes').fadeOut(); 3772 $('#owner_actions').removeClass('hide'); 3773 }); 3774 } 3775 }; 3776 3777 /** 3778 * Find first option without "disabled" attribute and select it 3779 * @param {object} $container 3780 */ 3781 this.selectFirstActiveOption = function($container) { 3782 if ($container.length < 0) { 3783 return false;
3784 } 3785 3786 // remove selection from active option 3787 $container.find('option:selected').removeAttr('selected').removeProp('selected'); 3788 3789 // select first active option 3790 $container.find('option').each(function(){ 3791 if (!$(this).prop('disabled') && $(this).val() != '-1' && !$(this).hasClass('hide')) { 3792 $(this).prop('selected', true); 3793 return false; 3794 } 3795 }); 3796 3797 $container.trigger('change'); 3798 }; 3799 3800 /** 3801 * Convert date by selected timezone 3802 * @param {int} timestamp 3803 * @param {string} custom_format 3804 * @return {string} - Converted date 3805 */ 3806 this.getDateByTimeZone = function(timestamp, custom_format) { 3807 if (!timestamp) { 3808 return ''; 3809 } 3810 3811 var format = custom_format 3812 ? custom_format 3813 : bookingConfigs['bookingDateFormat'].toUpperCase().replace(/%/g, '').replace('B', 'MMM'); 3814 3815 if (timestamp && format) { 3816 return moment.tz(new Date(timestamp * 1000), bookingConfigs.bookingTimeZone).format(format); 3817 } 3818 }; 3819 3820 /** 3821 * Remove decimals and convert price to short forms (1k, 1m, 1b) 3822 * 3823 * @since 3.2.0 Rename method from "adaptNumbersinPrice" to "adaptNumbersInPrice" 3824 * @since 3.1.0 3825 * 3826 * @param {float} price 3827 * @return {int} - Adapted price 3828 */ 3829 this.adaptNumbersInPrice = function(price) { 3830 if (!price) { 3831 return 0; 3832 } 3833 3834 if (typeof $.convertPrice == 'function') { 3835 return price; 3836 } 3837 3838 price = parseInt(price); 3839 var price_val = price.toString(); 3840 var separator = Math.floor(price_val.length/3); 3841 3842 separator -= price_val.length % 3 == 0 ? 1 : 0; 3843 3844 if (separator > 0) { 3845 var sign, short; 3846 3847 if (separator == 1) { 3848 sign = lang['booking_short_price_k']; 3849 short = price / 1000; 3850 } else if (separator == 2) { 3851 sign = lang['booking_short_price_m']; 3852 short = price / 1000000; 3853 } else if (separator > 2) { 3854 sign = lang['booking_short_price_b']; 3855 short = price / 1000000000; 3856 } 3857 3858 if (sign) { 3859 short = Math.round(short * 10)/10; 3860 price = short + sign; 3861 } 3862 } 3863 3864 return price; 3865 }; 3866 3867 /** 3868 * Get title of day by current localization 3869 * 3870 * @since 3.2.0 3871 * 3872 * @param bindCheckin 3873 * @param weekDays 3874 * @returns {string} 3875 */ 3876 this.getBindDaysByLocale = function (bindCheckin, weekDays) { 3877 bindCheckin = bindCheckin.split(','); 3878 3879 if (!bindCheckin) { 3880 return ''; 3881 } 3882 3883 let bindLocale = ''; 3884 3885 for (let dayIndex in bindCheckin) { 3886 if (!bindCheckin.hasOwnProperty(dayIndex)) { 3887 continue; 3888 } 3889 3890 switch (bindCheckin[dayIndex]) { 3891 case 'Mon': 3892 bindLocale += (bindLocale ? ', ' : '') + weekDays[1]; 3893 break; 3894 case 'Tue': 3895 bindLocale += (bindLocale ? ', ' : '') + weekDays[2]; 3896 break; 3897 case 'Wed': 3898 bindLocale += (bindLocale ? ', ' : '') + weekDays[3]; 3899 break; 3900 case 'Thu': 3901 bindLocale += (bindLocale ? ', ' : '') + weekDays[4]; 3902 break; 3903 case 'Fri': 3904 bindLocale += (bindLocale ? ', ' : '') + weekDays[5]; 3905 break; 3906 case 'Sat': 3907 bindLocale += (bindLocale ? ', ' : '') + weekDays[6]; 3908 break; 3909 case 'Sun': 3910 bindLocale += (bindLocale ? ', ' : '') + weekDays[7]; 3911 break; 3912 } 3913 } 3914 3915 return bindLocale; 3916 } 3917 3918 /** 3919 * Load all external JS libraries (momentJS etc.) asynchronously 3920 * @since 3.3.0 3921 * @param {function} callback 3922 */ 3923 this.loadExternalScripts = function (callback) { 3924 flUtil.loadScript(rlConfig.plugins_url + 'booking/static/moment.min.js', function () { 3925 flUtil.loadScript(rlConfig.plugins_url + 'booking/static/moment-timezone-with-data.min.js', function () { 3926 if (callback && typeof callback === 'function') { 3927 callback.call(this); 3928 } 3929 }); 3930 }); 3931 } 3932 3933 /** 3934 * Get count of days between 2 timestamps in days 3935 * @param {timestamp} date1 3936 * @param {timestamp} date2 3937 * @return {number} 3938 */ 3939 this.getCountDaysBetween2Timestamps = function(date1, date2) { 3940 if (!date1 || !date2) { 3941 return 0; 3942 } 3943 3944 date1 = moment.tz(new Date(date1 * 1000), bookingConfigs.bookingTimeZone); 3945 date2 = moment.tz(new Date(date2 * 1000), bookingConfigs.bookingTimeZone); 3946 return Math.abs(date1.diff(date2, 'days')); 3947 } 3948 3949 /**
3950 * Add count of days to date in timestamp format 3951 * @since 3.3.0 3952 * @param {timestamp} timestamp 3953 * @param {number} days 3954 * @return {timestamp} 3955 */ 3956 this.addDaysToTimestamp = function(timestamp, days = 1) { 3957 return self.modifyTimestamp(timestamp, days, '+'); 3958 } 3959 3960 /** 3961 * Subtract count of days to date in timestamp format 3962 * @since 3.3.0 3963 * @param {timestamp} timestamp 3964 * @param {number} days 3965 * @return {timestamp} 3966 */ 3967 this.subtractDaysFromTimestamp = function(timestamp, days = 1) { 3968 return self.modifyTimestamp(timestamp, days, '-'); 3969 } 3970 3971 /** 3972 * Add/subtract count of days to date in timestamp format 3973 * @since 3.3.0 3974 * @param {timestamp} timestamp 3975 * @param {number} days 3976 * @param {string} action 3977 * @return {timestamp} 3978 */ 3979 this.modifyTimestamp = function(timestamp, days, action = '+') { 3980 if (!timestamp) { 3981 return timestamp; 3982 } 3983 3984 if (action === '+') { 3985 return moment.tz(new Date(timestamp * 1000), bookingConfigs.bookingTimeZone).add(days, 'days').unix(); 3986 } else { 3987 return moment.tz(new Date(timestamp * 1000), bookingConfigs.bookingTimeZone).subtract(days, 'days').unix(); 3988 } 3989 } 3990 3991 /** 3992 * Initialization process of booking section (add/edit listing) 3993 */ 3994 this.init = function() { 3995 self.rateParentTag = bookingConfigs && bookingConfigs.isAdmin ? 'tr' : 'div'; 3996 self.rateChildTag = bookingConfigs && bookingConfigs.isAdmin ? 'td' : 'div'; 3997 self.$checkInSection = $('#booking_checkin_field'); 3998 self.$checkOutSection = $('#booking_checkout_field'); 3999 self.$bookingRadioButton = $('[name="f[booking_module]"]'); 4000 self.$bookingSection = self.$bookingRadioButton.parent().parent().parent(); 4001 4002 var $rates = $('.rates-field-container .rates'); 4003 self.rateIndex = $rates.length ? $rates.length : 1; 4004 4005 self.bookingSectionHandler(); 4006 } 4007}; 4008 4009var booking = new bookingClass(); 4010 4011function in_array(needle,haystack,argStrict){var key='',strict=!!argStrict;if(strict){for(key in haystack){if(haystack[key]===needle){return true;}}}else{for(key in haystack){if(haystack[key]==needle){return true;}}}return false;}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.