PageSourceSearch

https://facednatest.com/wp-content/plugins/booked/assets/js/functions.js?ver=2.3.5

js facednatest.com collected 2026-10-01 14:47:12 UTC 45,975 bytes, 1,471 lines download raw bytes

1// make it a global variable so other scripts can access it
2var booked_load_calendar_date_booking_options,
3	booked_appt_form_options,
4	bookedNewAppointment;
5
6;(function($, window, document, undefined) {
7
8	var $win = $(window);
9
10	$.fn.spin.presets.booked = {
11	 	lines: 10, // The number of lines to draw
12		length: 7, // The length of each line
13		width: 5, // The line thickness
14		radius: 11, // The radius of the inner circle
15		corners: 1, // Corner roundness (0..1)
16		rotate: 0, // The rotation offset
17		direction: 1, // 1: clockwise, -1: counterclockwise
18		color: '#555', // #rgb or #rrggbb or array of colors
19		speed: 1, // Rounds per second
20		trail: 60, // Afterglow percentage
21		shadow: false, // Whether to render a shadow
22		hwaccel: false, // Whether to use hardware acceleration
23		className: 'booked-spinner', // The CSS class to assign to the spinner
24		zIndex: 2e9, // The z-index (defaults to 2000000000)
25		top: '50%', // Top position relative to parent
26		left: '50%' // Left position relative to parent
27	}
28
29	$.fn.spin.presets.booked_top = {
30	 	lines: 11, // The number of lines to draw
31		length: 10, // The length of each line
32		width: 6, // The line thickness
33		radius: 15, // The radius of the inner circle
34		corners: 1, // Corner roundness (0..1)
35		rotate: 0, // The rotation offset
36		scale: 0.5,
37		direction: 1, // 1: clockwise, -1: counterclockwise
38		color: '#aaaaaa', // #rgb or #rrggbb or array of colors
39		speed: 1, // Rounds per second
40		trail: 60, // Afterglow percentage
41		shadow: false, // Whether to render a shadow
42		hwaccel: false, // Whether to use hardware acceleration
43		className: 'booked-spinner booked-spinner-top', // The CSS class to assign to the spinner
44		zIndex: 2e9, // The z-index (defaults to 2000000000)
45		top: '15px', // Top position relative to parent
46		left: '50%' // Left position relative to parent
47	}
48
49	$.fn.spin.presets.booked_white = {
50	 	lines: 13, // The number of lines to draw
51		length: 11, // The length of each line
52		width: 5, // The line thickness
53		radius: 18, // The radius of the inner circle
54		scale: 1,
55		corners: 1, // Corner roundness (0..1)
56		rotate: 0, // The rotation offset
57		direction: 1, // 1: clockwise, -1: counterclockwise
58		color: '#fff', // #rgb or #rrggbb or array of colors
59		speed: 1, // Rounds per second
60		trail: 60, // Afterglow percentage
61		shadow: false, // Whether to render a shadow
62		hwaccel: false, // Whether to use hardware acceleration
63		className: 'booked-spinner booked-white', // The CSS class to assign to the spinner
64		zIndex: 2e9, // The z-index (defaults to 2000000000)
65		top: '50%', // Top position relative to parent
66		left: '50%' // Left position relative to parent
67	}
68
69	// Adjust the calendar sizing when resizing the window
70	$win.on('resize', function(){
71
72		adjust_calendar_boxes();
73		resize_booked_modal();
74
75	});
76
77	$win.on('load', function() {
78
79		BookedTabs.Init();
80
81		var ajaxRequests = [];
82
83		// Adjust the calendar sizing on load
84		adjust_calendar_boxes();
85
86		$('.booked-calendar-wrap').each(function(){
87			var thisCalendar = $(this);
88			var calendar_month = thisCalendar.find('table.booked-calendar').attr('data-calendar-date');
89			thisCalendar.attr('data-default',calendar_month);
90			init_tooltips(thisCalendar);
91		});
92
93		$('.booked-list-view').each(function(){
94			var thisList = $(this);
95			var list_date = thisList.find('.booked-appt-list').attr('data-list-date');
96			thisList.attr('data-default',list_date);
97		});
98
99		bookedRemoveEmptyTRs();
100		init_appt_list_date_picker();
101
102		$('.booked_calendar_chooser').change(function(e){
103
104			e.preventDefault();
105
106			var $selector 			= $(this),
107				thisIsCalendar		= $selector.parents('.booked-calendarSwitcher').hasClass('calendar');
108
109			if (!thisIsCalendar){
110
111				var thisCalendarWrap	= $selector.parents('.booked-calendar-shortcode-wrap').find('.booked-list-view'),
112				thisDefaultDate			= thisCalendarWrap.attr('data-default'),
113				thisIsCalendar			= $selector.parents('.booked-calendarSwitcher').hasClass('calendar');
114
115				if (typeof thisDefaultDate == 'undefined'){ thisDefaultDate = false; }
116
117				thisCalendarWrap.addClass('booked-loading');
118
119				var args = {
120					'action'		: 'booked_appointment_list_date',
121					'date'		: thisDefaultDate,
122					'calendar_id'	: $selector.val()
123				};
124
125				$(document).trigger("booked-before-loading-appointment-list-booking-options");
126				thisCalendarWrap.spin('booked_top');
127
128				$.ajax({
129					url: booked_js_vars.ajax_url,
130					type: 'post',
131					data: args,
132					success: function( html ) {
133
134						thisCalendarWrap.html( html );
135
136						init_appt_list_date_picker();
137						setTimeout(function(){
138							thisCalendarWrap.removeClass('booked-loading');
139						},1);
140
141					}
142				});
143
144			} else {
145
146				var thisCalendarWrap 	= $selector.parents('.booked-calendar-shortcode-wrap').find('.booked-calendar-wrap'),
147				thisDefaultDate			= thisCalendarWrap.attr('data-default');
148				if (typeof thisDefaultDate == 'undefined'){ thisDefaultDate = false; }
149
150				var args = {
151					'action'		: 'booked_calendar_month',
152					'gotoMonth'		: thisDefaultDate,
153					'calendar_id'	: $selector.val()
154				};
155
156				savingState(true,thisCalendarWrap);
157
158				$.ajax({
159					url: booked_js_vars.ajax_url,
160					type: 'post',
161					data: args,
162					success: function( html ) {
163
164						thisCalendarWrap.html( html );
165
166						adjust_calendar_boxes();
167						bookedRemoveEmptyTRs();
168						init_tooltips(thisCalendarWrap);
169					 	$(window).trigger('booked-load-calendar', args, $selector );
170
171					}
172				});
173
174			}
175
176			return false;
177
178		});
179
180		// Calendar Next/Prev Click
181		$('body').on('click', '.booked-calendar-wrap .page-right, .booked-calendar-wrap .page-left, .booked-calendar-wrap .monthName a', function(e) {
182
183			e.preventDefault();
184
185			var $button 			= $(this),
186				gotoMonth			= $button.attr('data-goto'),
187				thisCalendarWrap 	= $button.parents('.booked-calendar-wrap'),
188				thisCalendarDefault = thisCalendarWrap.attr('data-default'),
189				calendar_id			= $button.parents('table.booked-calendar').attr('data-calendar-id');
190
191			if (typeof thisCalendarDefault == 'undefined'){ thisCalendarDefault = false; }
192
193			var args = {
194				'action'		: 'booked_calendar_month',
195				'gotoMonth'		: gotoMonth,
196				'calendar_id'	: calendar_id,
197				'force_default'	: thisCalendarDefault
198			};
199
200			savingState(true,thisCalendarWrap);
201
202			$.ajax({
203				url: booked_js_vars.ajax_url,
204				type: 'post',
205				data: args,
206				success: function( html ) {
207
208					thisCalendarWrap.html( html );
209
210					adjust_calendar_boxes();
211					bookedRemoveEmptyTRs();
212					init_tooltips(thisCalendarWrap);
213					$(window).trigger('booked-load-calendar', args, $button );
214
215				}
216			});
217
218			return false;
219
220		});
221
222		// Calendar Date Click
223		$('body').on('click', '.booked-calendar-wrap tr.week td', function(e) {
224
225			e.preventDefault();
226
227			var $thisDate 				= $(this),
228				booked_calendar_table 	= $thisDate.parents('table.booked-calendar'),
229				$thisRow				= $thisDate.parent(),
230				date					= $thisDate.attr('data-date'),
231				calendar_id				= booked_calendar_table.attr('data-calendar-id'),
232				colspanSetting			= $thisRow.find('td').length;
233
234			if (!calendar_id){ calendar_id = 0; }
235
236			if ($thisDate.hasClass('blur') || $thisDate.hasClass('booked') && !booked_js_vars.publicAppointments || $thisDate.hasClass('prev-date')){
237
238				// Do nothing.
239
240			} else if ($thisDate.hasClass('active')){
241
242				$thisDate.removeClass('active');
243				$('tr.entryBlock').remove();
244
245				var calendarHeight = booked_calendar_table.height();
246				booked_calendar_table.parent().height(calendarHeight);
247
248			} else {
249
250				$('tr.week td').removeClass('active');
251				$thisDate.addClass('active');
252
253				$('tr.entryBlock').remove();
254				$thisRow.after('<tr class="entryBlock booked-loading"><td colspan="'+colspanSetting+'"></td></tr>');
255				$('tr.entryBlock').find('td').spin('booked');
256
257				booked_load_calendar_date_booking_options = {'action':'booked_calendar_date','date':date,'calendar_id':calendar_id};
258				$(document).trigger("booked-before-loading-calendar-booking-options");
259
260				var calendarHeight = booked_calendar_table.height();
261				booked_calendar_table.parent().height(calendarHeight);
262
263				$.ajax({
264					url: booked_js_vars.ajax_url,
265					type: 'post',
266					data: booked_load_calendar_date_booking_options,
267					success: function( html ) {
268
269						$('tr.entryBlock').find('td').html( html );
270
271						$('tr.entryBlock').removeClass('booked-loading');
272						$('tr.entryBlock').find('.booked-appt-list').fadeIn(300);
273						$('tr.entryBlock').find('.booked-appt-list').addClass('shown');
274						adjust_calendar_boxes();
275
276					}
277				});
278
279			}
280
281			return;
282
283		});
284
285		// Appointment List Next/Prev Date Click
286		$('body').on('click', '.booked-list-view .booked-list-view-date-prev, .booked-list-view .booked-list-view-date-next', function(e) {
287
288			e.preventDefault();
289
290			var $thisLink 			= $(this),
291				date				= $thisLink.attr('data-date'),
292				thisList			= $thisLink.parents('.booked-list-view'),
293				defaultDate			= thisList.attr('data-default'),
294				calendar_id			= $thisLink.parents('.booked-list-view-nav').attr('data-calendar-id');
295
296			if (typeof defaultDate == 'undefined'){ defaultDate = false; }
297
298			if (!calendar_id){ calendar_id = 0; }
299
300			thisList.addClass('booked-loading');
301
302			var booked_load_list_view_date_booking_options = {
303				'action'		: 'booked_appointment_list_date',
304				'date'			: date,
305				'calendar_id'	: calendar_id,
306				'force_default'	: defaultDate
307			};
308
309			$(document).trigger("booked-before-loading-appointment-list-booking-options");
310			thisList.spin('booked_top');
311
312			$.ajax({
313				url: booked_js_vars.ajax_url,
314				type: 'post',
315				data: booked_load_list_view_date_booking_options,
316				success: function( html ) {
317
318					thisList.html( html );
319
320					init_appt_list_date_picker();
321					setTimeout(function(){
322						thisList.removeClass('booked-loading');
323					},1);
324
325				}
326			});
327
328			return false;
329
330		});
331
332		// New Appointment Click
333		bookedNewAppointment = function(e) {
334			e.preventDefault();
335
336			var $button 		= $(this),
337				title           = $button.attr('data-title'),
338				timeslot		= $button.attr('data-timeslot'),
339				date			= $button.attr('data-date'),
340				calendar_id		= $button.attr('data-calendar-id'),
341				$thisTimeslot	= $button.parents('.timeslot'),
342				is_list_view	= $button.parents('.booked-calendar-wrap').hasClass('booked-list-view');
343
344			if (typeof is_list_view != 'undefined' && is_list_view){
345				var new_calendar_id	= $button.parents('.booked-list-view').find('.booked-list-view-nav').attr('data-calendar-id');
346			} else {
347				var new_calendar_id	= $button.parents('table.booked-calendar').attr('data-calendar-id');
348			}
349			calendar_id = new_calendar_id ? new_calendar_id : calendar_id;
350
351			booked_appt_form_options = {'action':'booked_new_appointment_form','date':date,'timeslot':timeslot,'calendar_id':calendar_id,'title':title};
352			$(document).trigger("booked-before-loading-booking-form");
353
354			create_booked_modal();
355			setTimeout(function(){
356
357				$.ajax({
358					url: booked_js_vars.ajax_url,
359					type: 'post',
360					data: booked_appt_form_options,
361					success: function( html ) {
362
363						$('.bm-window').html( html );
364
365						var bookedModal = $('.booked-modal');
366						var bmWindow = bookedModal.find('.bm-window');
367						bmWindow.css({'visibility':'hidden'});
368						bookedModal.removeClass('bm-loading');
369						$(document).trigger("booked-on-new-app");
370						resize_booked_modal();
371						bmWindow.hide();
372						$('.booked-modal .bm-overlay').find('.booked-spinner').remove();
373
374						setTimeout(function(){
375							bmWindow.css({'visibility':'visible'});
376							bmWindow.show();
377						},50);
378
379					}
380				});
381
382			},100);
383
384			return false;
385		}
386		$('body').on('click', '.booked-calendar-wrap button.new-appt', bookedNewAppointment);
387
388		// Profile Tabs
389		var profileTabs = $('.booked-tabs');
390
391		if (!profileTabs.find('li.active').length){
392			profileTabs.find('li:first-child').addClass("active");
393		}
394
395		if (profileTabs.length){
396			$('.booked-tab-content').hide();
397			var activeTab = profileTabs.find('.active > a').attr('href');
398			activeTab = activeTab.split('#');
399			activeTab = activeTab[1];
400			$('#profile-'+activeTab).show();
401
402			profileTabs.find('li > a').on('click', function(e) {
403
404				e.preventDefault();
405				$('.booked-tab-content').hide();
406				profileTabs.find('li').removeClass('active');
407
408				$(this).parent().addClass('active');
409				var activeTab = $(this).attr('href');
410				activeTab = activeTab.split('#');
411				activeTab = activeTab[1];
412
413				$('#profile-'+activeTab).show();
414				return false;
415
416			});
417		}
418
419		// Show Additional Information
420		$('body').on('click', '.booked-profile-appt-list .booked-show-cf', function(e) {
421
422			e.preventDefault();
423			var hiddenBlock = $(this).parent().find('.cf-meta-values-hidden');
424
425			if(hiddenBlock.is(':visible')){
426				hiddenBlock.hide();
427				$(this).removeClass('booked-cf-active');
428			} else {
429				hiddenBlock.show();
430				$(this).addClass('booked-cf-active');
431			}
432
433			return false;
434
435		});
436
437		// Check Login/Registration/Forgot Password forms before Submitting
438		if ($('#loginform').length){
439			$('#loginform input[type="submit"]').on('click',function(e) {
440				if ($('#loginform input[name="log"]').val() && $('#loginform input[name="pwd"]').val()){
441					$('#loginform .booked-custom-error').hide();
442				} else {
443					if ( $('#loginform').parents('.booked-form-wrap').length ){
444						e.preventDefault();
445						$('#loginform').parents('.booked-form-wrap').find('.booked-custom-error').fadeOut(200).fadeIn(200);
446					}
447				}
448			});
449		}
450
451		if ($('#profile-forgot').length){
452			$('#profile-forgot input[type="submit"]').on('click',function(e) {
453				if ($('#profile-forgot input[name="user_login"]').val()){
454					$('#profile-forgot .booked-custom-error').hide();
455				} else {
456					e.preventDefault();
457					$('#profile-forgot').find('.booked-custom-error').fadeOut(200).fadeIn(200);
458				}
459			});
460		}
461
462		// Custom Upload Field
463		if ($('.booked-upload-wrap').length){
464
465			$('.booked-upload-wrap input[type=file]').on('change',function(){
466
467				var fileName = $(this).val();
468				$(this).parent().find('span').html(fileName);
469				$(this).parent().addClass('hasFile');
470
471			});
472
473		}
474
475		// Delete Appointment
476		$('body').on('click', '.booked-profile-appt-list .appt-block .cancel', function(e) {
477
478			e.preventDefault();
479
480			var $button 		= $(this),
481				$thisParent		= $button.parents('.appt-block'),
482				appt_id			= $thisParent.attr('data-appt-id');
483
484			confirm_delete = confirm(booked_js_vars.i18n_confirm_appt_delete);
485			if (confirm_delete == true){
486
487				var currentApptCount = parseInt($('.booked-profile-appt-list').find('h4').find('span.count').html());
488				currentApptCount = parseInt(currentApptCount - 1);
489				if (currentApptCount < 1){
490					$('.booked-profile-appt-list').find('h4').find('span.count').html('0');
491					$('.no-appts-message').slideDown('fast');
492				} else {
493					$('.booked-profile-appt-list').find('h4').find('span.count').html(currentApptCount);
494				}
495
496				$('.appt-block').animate({'opacity':0.4},0);
497
498	  			$thisParent.slideUp('fast',function(){
499					$(this).remove();
500				});
501
502				$.ajax({
503					'url' 		: booked_js_vars.ajax_url,
504					'method' 	: 'post',
505					'data'		: {
506						'action'     	: 'booked_cancel_appt',
507						'appt_id'     	: appt_id
508					},
509					success: function(data) {
510						$('.appt-block').animate({'opacity':1},150);
511					}
512				});
513
514			}
515
516			return false;
517
518		});
519
520		$('body').on('touchstart click','.bm-overlay, .bm-window .close, .booked-form .cancel',function(e){
521			e.preventDefault();
522			close_booked_modal();
523			return false;
524		});
525
526		$('body')
527		.on('focusin', '.booked-form input', function() {
528			if(this.title==this.value) {
529				$(this).addClass('hasContent');
530				this.value = '';
531			}
532		}).on('focusout', '.booked-form input', function(){
533			if(this.value==='') {
534				$(this).removeClass('hasContent');
535				this.value = this.title;
536			}
537		});
538
539		$('body').on('change','.booked-form input',function(){
540
541			var condition = $(this).attr('data-condition'),
542				thisVal = $(this).val();
543
544			if (condition && $('.condition-block').length) {
545				$('.condition-block.'+condition).hide();
546				$('#condition-'+thisVal).fadeIn(200);
547				resize_booked_modal();
548			}
549
550		});
551
552		// Perform AJAX login on form submit
553	    $('body').on('submit','form#ajaxlogin', function(e){
554		    e.preventDefault();
555
556	        $('form#ajaxlogin p.status').show().html('<i class="booked-icon booked-icon-spinner-clock booked-icon-spin"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_please_wait);
557	        resize_booked_modal();
558
559	        var $this = $(this),
560	        	date = $this.data('date'),
561	        	title = $this.data('title'),
562	        	timeslot = $this.data('timeslot'),
563	        	calendar_id = $this.data('calendar-id');
564
565	        $.ajax({
566		        type	: 'post',
567				url 	: booked_js_vars.ajax_url,
568				data	: $('form#ajaxlogin').serialize(),
569				success	: function(data) {
570					if (data == 'success'){
571
572						// close the modal box
573						close_booked_modal();
574
575						// reopen the modal box
576						var $button = $( '<button data-title="' + title + '" data-timeslot="' + timeslot + '" data-date="' + date + '" data-calendar-id="' + calendar_id + '"></button>' );
577						$button.on( 'click', window.bookedNewAppointment );
578						$button.triggerHandler( 'click' );
579						$button.unbind( 'click', window.bookedNewAppointment );
580						$button.detach();
581
582					} else {
583						$('form#ajaxlogin p.status').show().html('<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_wrong_username_pass);
584						resize_booked_modal();
585					}
586	            }
587	        });
588	        e.preventDefault();
589	    });
590
591	    $('body').on('click','.booked-forgot-password',function(e){
592
593			e.preventDefault();
594			$('#ajaxlogin').hide();
595			$('#ajaxforgot').show();
596
597			resize_booked_modal();
598
599	    });
600
601	     $('body').on('click','.booked-forgot-goback',function(e){
602
603			e.preventDefault();
604			$('#ajaxlogin').show();
605			$('#ajaxforgot').hide();
606
607			resize_booked_modal();
608
609	    });
610
611	    // Perform AJAX login on form submit
612
613	    $('body').on('submit','form#ajaxforgot', function(e){
614		    e.preventDefault();
615
616	        $('form#ajaxforgot p.status').show().html('<i class="booked-icon booked-icon-spinner-clock booked-icon-spin"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_please_wait);
617	        resize_booked_modal();
618
619	        var $this = $(this);
620
621	        $.ajax({
622		        type	: 'post',
623				url 	: booked_js_vars.ajax_url,
624				data	: $('form#ajaxforgot').serialize(),
625				success	: function(data) {
626					if (data == 'success'){
627
628						e.preventDefault();
629						$('#ajaxlogin').show();
630						$('#ajaxforgot').hide();
631
632						$('form#ajaxlogin p.status').show().html('<i class="booked-icon booked-icon-check" style="color:#56c477"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_password_reset);
633						resize_booked_modal();
634
635					} else {
636
637						//console.log(data);
638						$('form#ajaxforgot p.status').show().html('<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_password_reset_error);
639						resize_booked_modal();
640
641					}
642	            }
643	        });
644	        e.preventDefault();
645	    });
646
647
648		// Submit the "Request Appointment" Form
649		$('body').on('click','.booked-form input#submit-request-appointment',function(e){
650
651			$('form#newAppointmentForm p.status').show().html('<i class="booked-icon booked-icon-spinner-clock booked-icon-spin"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_please_wait);
652	        resize_booked_modal();
653
654			e.preventDefault();
655
656			var customerType        = $('#newAppointmentForm input[name=customer_type]').val(),
657				customerID          = $('#newAppointmentForm input[name=user_id]').val(),
658				name                = $('#newAppointmentForm input[name=booked_appt_name]').val(),
659				surname             = $('#newAppointmentForm input[name=booked_appt_surname]').val(),
660				surnameActive		= $('#newAppointmentForm input[name=booked_appt_surname]').length,
661				guest_name          = $('#newAppointmentForm input[name=guest_name]').val(),
662				guest_surname      	= $('#newAppointmentForm input[name=guest_surname]').val(),
663				guest_surnameActive = $('#newAppointmentForm input[name=guest_surname]').length,
664				guest_email			= $('#newAppointmentForm input[name=guest_email]').val(),
665				guest_emailActive 	= $('#newAppointmentForm input[name=guest_email]').length,
666				email               = $('#newAppointmentForm input[name=booked_appt_email]').val(),
667				password            = $('#newAppointmentForm input[name=booked_appt_password]').val(),
668				showRequiredError   = false,
669				ajaxRequests        = [];
670
671			$(this).parents('.booked-form').find('input,textarea,select').each(function(i,field){
672
673				var required = $(this).attr('required');
674
675				if (required && $(field).attr('type') == 'hidden'){
676					var fieldParts = $(field).attr('name');
677					fieldParts = fieldParts.split('---');
678					fieldName = fieldParts[0];
679					fieldNumber = fieldParts[1].split('___');
680					fieldNumber = fieldNumber[0];
681
682					if (fieldName == 'radio-buttons-label'){
683						var radioValue = false;
684						$('input:radio[name="single-radio-button---'+fieldNumber+'[]"]:checked').each(function(){
685							if ($(this).val()){
686								radioValue = $(this).val();
687							}
688						});
689						if (!radioValue){
690							showRequiredError = true;
691						}
692					} else if (fieldName == 'checkboxes-label'){
693						var checkboxValue = false;
694						$('input:checkbox[name="single-checkbox---'+fieldNumber+'[]"]:checked').each(function(){
695							if ($(this).val()){
696								checkboxValue = $(this).val();
697							}
698						});
699						if (!checkboxValue){
700							showRequiredError = true;
701						}
702					}
703
704				} else if (required && $(field).attr('type') != 'hidden' && $(field).val() == ''){
705		            showRequiredError = true;
706		        }
707
708		    });
709
710		    if (showRequiredError) {
711			    $('form#newAppointmentForm p.status').show().html('<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_fill_out_required_fields);
712				resize_booked_modal();
713			    return false;
714		    }
715
716			if ( customerType == 'new' && !name || customerType == 'new' && surnameActive && !surname || customerType == 'new' && !email || customerType == 'new' && !password ) {
717				$('form#newAppointmentForm p.status').show().html('<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_appt_required_fields);
718				resize_booked_modal();
719				return false;
720			}
721
722			if ( customerType == 'guest' && !guest_name || customerType == 'guest' && guest_emailActive && !guest_email || customerType == 'guest' && guest_surnameActive && !guest_surname ){
723				$('form#newAppointmentForm p.status').show().html('<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_appt_required_fields_guest);
724				resize_booked_modal();
725				return false;
726			}
727
728			if (customerType == 'current' && customerID ||
729				customerType == 'guest' && guest_name && !guest_surnameActive && !guest_emailActive ||
730				customerType == 'guest' && guest_name && guest_surnameActive && guest_surname && !guest_emailActive ||
731				customerType == 'guest' && guest_name && guest_emailActive && guest_email && !guest_surnameActive ||
732				customerType == 'guest' && guest_name && guest_emailActive && guest_email && guest_surnameActive && guest_surname ) {
733
734			    SubmitRequestAppointment.currentUserOrGuest();
735
736			}
737
738			if (customerType == 'new' && name && email && password) {
739				if ( !surnameActive || surnameActive && surname ){
740					SubmitRequestAppointment.newUser();
741				}
742			}
743
744		});
745
746		var SubmitRequestAppointment = {
747
748			formSelector: '#newAppointmentForm',
749			formBtnRequestSelector: '.booked-form input#submit-request-appointment',
750			formStatusSelector: 'p.status',
751			formSubmitBtnSelector: '#submit-request-appointment',
752
753			apptContainerSelector: '.booked-appointment-details',
754
755			baseFields: 	[ 'guest_name','guest_surname','guest_email','action', 'customer_type', 'user_id' ],
756			apptFields: 	[ 'appoinment', 'calendar_id', 'title', 'date', 'timestamp', 'timeslot' ],
757			userFields: 	[ 'booked_appt_name','booked_appt_surname','booked_appt_email', 'booked_appt_password' ],
758			captchaFields: 	[ 'captcha_word', 'captcha_code' ],
759
760			currentApptIndex: false,
761			currentApptCounter: false,
762			hasAnyErrors: false,
763
764			currentUserOrGuest: function() {
765				var total_appts = SubmitRequestAppointment._totalAppts();
766
767				if ( ! total_appts ) {
768					return;
769				}
770
771				SubmitRequestAppointment._showLoadingMessage();
772				SubmitRequestAppointment._resetDefaultValues();
773
774				var data = SubmitRequestAppointment._getBaseData();
775
776				SubmitRequestAppointment.currentApptIndex = 0;
777				SubmitRequestAppointment.currentApptCounter = 1;
778				SubmitRequestAppointment._doRequestAppointment( data, total_appts );
779
780			},
781
782			// pretty much the same as SubmitRequestAppointment.currentUserOrGuest(), however, it include the user name, email and password
783			newUser: function() {
784				var total_appts = SubmitRequestAppointment._totalAppts();
785
786				if ( ! total_appts ) {
787					return;
788				}
789
790				SubmitRequestAppointment._showLoadingMessage();
791				SubmitRequestAppointment._resetDefaultValues();
792
793				var data = SubmitRequestAppointment._getBaseData();
794
795				// when there are more than one appointment, we need to make the registration request first and then loop the appointments
796				if ( total_appts > 1 ) {
797					var data_obj_with_no_reference = null;
798					data_obj_with_no_reference = $.extend( true, {}, data );
799					data_obj_with_no_reference = SubmitRequestAppointment._addUserRegistrationData( data_obj_with_no_reference );
800					SubmitRequestAppointment._requestUserRegistration( data_obj_with_no_reference );
801
802					data.customer_type = 'current';
803				} else {
804					// add user registration fields values
805					data = SubmitRequestAppointment._addUserRegistrationData( data );
806				}
807
808				SubmitRequestAppointment.currentApptIndex = 0;
809				SubmitRequestAppointment._doRequestAppointment( data, total_appts );
810			},
811
812			_doRequestAppointment: function( data, total_appts ) {
813
814				var appt_fields = SubmitRequestAppointment.apptFields;
815
816				// for the first item only
817				if ( SubmitRequestAppointment.currentApptIndex === 0 ) {
818					SubmitRequestAppointment._hideCancelBtn();
819					SubmitRequestAppointment._disableSubmitBtn();
820					SubmitRequestAppointment.hasAnyErrors = false;
821				}
822				// <------end
823
824				var data_obj_with_no_reference = $.extend( true, {}, data );
825
826				// add the appointment fields to the data
827				for (var i = 0; i < appt_fields.length; i++) {
828					data_obj_with_no_reference[ appt_fields[i] ] = SubmitRequestAppointment._getFieldVal( appt_fields[i], SubmitRequestAppointment.currentApptIndex );
829				}
830
831				var calendar_id = SubmitRequestAppointment._getFieldVal( 'calendar_id', SubmitRequestAppointment.currentApptIndex );
832				data_obj_with_no_reference = SubmitRequestAppointment._addCustomFieldsData( data_obj_with_no_reference, calendar_id );
833
834				var $appt = SubmitRequestAppointment._getApptElement( SubmitRequestAppointment.currentApptIndex );
835
836				if ( ! $appt.hasClass('skip') ) {
837					$.ajax({
838						type    : 'post',
839						url     : booked_js_vars.ajax_url,
840						data    : data_obj_with_no_reference,
841						success	: function( response ) {
842
843							//SubmitRequestAppointment._enableSubmitBtn();
844							//SubmitRequestAppointment._showCancelBtn();
845
846							//console.log(response);
847							//return;
848
849							SubmitRequestAppointment._requestAppointmentResponseHandler( response );
850							SubmitRequestAppointment.currentApptIndex++;
851
852							setTimeout( function() {
853								if ( SubmitRequestAppointment.currentApptCounter === total_appts ) {
854									// for the last item only
855									if ( ! SubmitRequestAppointment.hasAnyErrors ) {
856										SubmitRequestAppointment._onAfterRequestAppointment();
857									} else {
858										SubmitRequestAppointment._enableSubmitBtn();
859										SubmitRequestAppointment._showCancelBtn();
860									}
861									// <------end
862								} else {
863									SubmitRequestAppointment.currentApptCounter++;
864									SubmitRequestAppointment._doRequestAppointment( data, total_appts );
865								}
866							}, 100 );
867						}
868					});
869				} else {
870					SubmitRequestAppointment.currentApptIndex++;
871					SubmitRequestAppointment.currentApptCounter++;
872					SubmitRequestAppointment._doRequestAppointment( data, total_appts, SubmitRequestAppointment.currentApptIndex );
873				}
874			},
875
876			_totalAppts: function() {
877				return $(SubmitRequestAppointment.formSelector + ' input[name="appoinment[]"]').length;
878			},
879
880			_getBaseData: function() {
881				var data = {},
882					fields = SubmitRequestAppointment.baseFields;
883
884				// set up the base form data
885				for ( var i = 0; i < fields.length; i++ ) {
886					data[ fields[i] ] = SubmitRequestAppointment._getFieldVal( fields[i] );
887				}
888
889				data['is_fe_form'] = true;
890				data['total_appts'] = SubmitRequestAppointment._totalAppts();
891
892				return data;
893			},
894
895			_getFieldVal: function( field_name, field_index ) {
896				var field_name = typeof field_name === 'undefined' ? '' : field_name,
897					field_index = typeof field_index === 'undefined' ? false : field_index,
898					selector = SubmitRequestAppointment.formSelector + ' ';
899
900				if ( field_index === false ) {
901					selector += ' [name=' + field_name + ']';
902					return $( selector ).val();
903				}
904
905				selector += ' [name="' + field_name + '[]"]';
906				return $( selector ).eq( field_index ).val();
907			},
908
909			_resetDefaultValues: function() {
910				 $('.booked-form input').each(function(){
911					var thisVal = $(this).val(),
912						thisDefault = $(this).attr('title');
913
914					if ( thisDefault == thisVal ){
915						$(this).val('');
916					}
917				});
918			},
919
920			_resetToDefaultValues: function() {
921				$('.booked-form input').each(function(){
922					var thisVal = $(this).val(),
923						thisDefault = $(this).attr('title');
924
925					if ( ! thisVal ){
926						$(this).val( thisDefault );
927					}
928				});
929			},
930
931			_addUserRegistrationData: function( data ) {
932				// populate the user data
933				$.each( SubmitRequestAppointment.userFields, function( index, field_name ) {
934					data[ field_name ] = SubmitRequestAppointment._getFieldVal( field_name );
935				} );
936
937				// populate captcha data if available
938				$.each( SubmitRequestAppointment.captchaFields, function( index, field_name ) {
939					var field_value = SubmitRequestAppointment._getFieldVal( field_name );
940
941					if ( ! field_value ) {
942						return;
943					}
944
945					data[ field_name ] = field_value;
946				} );
947
948				return data;
949			},
950
951			_addCustomFieldsData: function( data, calendar_id ) {
952				var custom_fields_data = $('.cf-block [name]')
953					.filter( function( index ) {
954						var $this = $(this);
955						return parseInt($this.data('calendar-id')) === parseInt(calendar_id) && $this.attr('name').match(/---\d+/g);
956					} )
957					.each( function( index ) {
958						var $this = $(this),
959							name = $this.attr('name'),
960							value = $this.val(),
961							type = $this.attr('type');
962
963						if ( ! value ) {
964							return;
965						}
966
967						if ( ! name.match(/checkbox|radio+/g) ) {
968							data[ name ] = value;
969							return;
970						}
971
972						if ( name.match(/radio+/g) && $this.is(':checked') ) {
973							data[ name ] = value;
974							return;
975						}
976
977						if ( ! name.match(/radio+/g) && typeof data[ name ] === 'undefined' || ! name.match(/radio+/g) && data[ name ].constructor !== Array ) {
978							data[ name ] = [];
979						}
980
981						if ( ! $this.is(':checked') ) {
982							return;
983						}
984
985						data[ name ].push( value );
986					} );
987
988				return data;
989			},
990
991			_requestUserRegistration: function( base_data, appt_index ) {
992				$.ajax({
993					type    : 'post',
994					url     : booked_js_vars.ajax_url,
995					data    : base_data,
996					async   : false,
997					success	: function( response ) {
998						SubmitRequestAppointment._requestUserRegistrationResponseHandler( response );
999					}
1000				});
1001			},
1002
1003			_requestUserRegistrationResponseHandler: function( response ) {
1004				var response_parts = response.split('###'),
1005					data_result = response_parts[0].substr( response_parts[0].length - 5 );
1006
1007				if ( data_result === 'error' ) {
1008					// do something on registration failure
1009					return;
1010				}
1011
1012				// do something on successful registration
1013			},
1014
1015			_requestAppointment: function( response ) {
1016				SubmitRequestAppointment._requestAppointmentResponseHandler( response );
1017			},
1018
1019			_requestAppointmentResponseHandler: function( response ) {
1020				var response_parts = response.split('###'),
1021					data_result = response_parts[0].substr( response_parts[0].length - 5 );
1022
1023				if ( data_result === 'error' ) {
1024					SubmitRequestAppointment._requestAppointmentOnError( response_parts );
1025					return;
1026				}
1027
1028				SubmitRequestAppointment._requestAppointmentOnSuccess( response_parts );
1029			},
1030
1031			_requestAppointmentOnError: function( response_parts ) {
1032				var $apptEl = SubmitRequestAppointment._getApptElement();
1033
1034				$(document).trigger("booked-on-requested-appt-error",[$apptEl]);
1035
1036				SubmitRequestAppointment._highlightAppt();
1037
1038				SubmitRequestAppointment._setStatusMsg( response_parts[1] );
1039
1040				SubmitRequestAppointment.hasAnyErrors = true;
1041
1042				resize_booked_modal();
1043			},
1044
1045			_requestAppointmentOnSuccess: function( response_parts ) {
1046				var $apptEl = SubmitRequestAppointment._getApptElement();
1047
1048				$(document).trigger("booked-on-requested-appt-success",[$apptEl]);
1049
1050				SubmitRequestAppointment._unhighlightAppt();
1051			},
1052
1053			_onAfterRequestAppointment: function() {
1054				var redirectObj = { redirect : false };
1055				var redirect = $(document).trigger("booked-on-requested-appointment",[redirectObj]);
1056
1057				if ( redirectObj.redirect ) {
1058					return;
1059				}
1060
1061				if ( booked_js_vars.profilePage ) {
1062					window.location = booked_js_vars.profilePage;
1063					return;
1064				}
1065
1066				SubmitRequestAppointment._reloadApptsList();
1067				SubmitRequestAppointment._reloadCalendarTable();
1068			},
1069
1070			_setStatusMsg: function( msg ) {
1071				var form_status_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formStatusSelector;
1072				$( form_status_selector ).show().html( '<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + msg );
1073			},
1074
1075			_getApptElement: function( appt_index ) {
1076				var appt_index = typeof appt_index === 'undefined' ? SubmitRequestAppointment.currentApptIndex : appt_index,
1077					appt_cnt_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.apptContainerSelector;
1078
1079				return $( appt_cnt_selector ).eq( appt_index );
1080			},
1081
1082			_highlightAppt: function( msg ) {
1083				var $apptEl = SubmitRequestAppointment._getApptElement();
1084
1085				if ( ! $apptEl.length ) {
1086					return;
1087				}
1088
1089				$apptEl.addClass('has-error');
1090			},
1091
1092			_unhighlightAppt: function( msg ) {
1093				var $apptEl = SubmitRequestAppointment._getApptElement();
1094
1095				if ( ! $apptEl.length ) {
1096					return;
1097				}
1098
1099				$apptEl.removeClass('has-error').addClass('skip');
1100			},
1101
1102			_enableSubmitBtn: function() {
1103				var btn_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formSubmitBtnSelector;
1104				$( btn_selector ).attr( 'disabled', false );
1105			},
1106
1107			_disableSubmitBtn: function() {
1108				var btn_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formSubmitBtnSelector;
1109				$( btn_selector ).attr( 'disabled', true );
1110			},
1111
1112			_showCancelBtn: function() {
1113				$( SubmitRequestAppointment.formSelector ).find('button.cancel').show();
1114			},
1115
1116			_hideCancelBtn: function() {
1117				$( SubmitRequestAppointment.formSelector ).find('button.cancel').hide();
1118			},
1119
1120			_showLoadingMessage: function() {
1121				$('form#newAppointmentForm p.status').show().html('<i class="booked-icon booked-icon-spinner-clock booked-icon-spin"></i>&nbsp;&nbsp;&nbsp;' + booked_js_vars.i18n_please_wait);
1122			},
1123
1124			_reloadApptsList: function() {
1125				if ( ! $('.booked-appt-list').length ){
1126					return;
1127				}
1128
1129				$('.booked-appt-list').each( function() {
1130					var $thisApptList  = $(this),
1131						date          = $thisApptList.attr('data-list-date'),
1132						thisList      = $thisApptList.parents('.booked-list-view'),
1133						defaultDate   = thisList.attr('data-default'),
1134						calendar_id   = parseInt($thisApptList.find('.booked-list-view-nav').attr('data-calendar-id')) || 0;
1135
1136					defaultDate = typeof defaultDate === 'undefined' ? false : defaultDate;
1137					calendar_id = calendar_id ? calendar_id : 0;
1138
1139					thisList.addClass('booked-loading');
1140
1141					var booked_load_list_view_date_booking_options = {
1142						'action'		: 'booked_appointment_list_date',
1143						'date'			: date,
1144						'calendar_id'	: calendar_id,
1145						'force_default'	: defaultDate
1146					};
1147
1148					$(document).trigger("booked-before-loading-appointment-list-booking-options");
1149					thisList.spin('booked_top');
1150
1151					$.ajax({
1152						url: booked_js_vars.ajax_url,
1153						type: 'post',
1154						data: booked_load_list_view_date_booking_options,
1155						success: function( html ) {
1156							thisList.html( html );
1157
1158							close_booked_modal();
1159							init_appt_list_date_picker();
1160							setTimeout(function(){
1161								thisList.removeClass('booked-loading');
1162							},1);
1163						}
1164					});
1165				});
1166			},
1167
1168			_reloadCalendarTable: function() {
1169				if ( ! $('td.active').length ) {
1170					return;
1171				}
1172
1173				var $activeTD = $('td.active'),
1174					activeDate = $activeTD.attr('data-date'),
1175					calendar_id = parseInt( $activeTD.parents('table').data('calendar-id') ) || 0;
1176
1177				booked_load_calendar_date_booking_options = { 'action':'booked_calendar_date', 'date':activeDate, 'calendar_id':calendar_id };
1178				$(document).trigger("booked-before-loading-calendar-booking-options");
1179
1180				$.ajax({
1181					url: booked_js_vars.ajax_url,
1182					type: 'post',
1183					data: booked_load_calendar_date_booking_options,
1184					success: function( html ) {
1185
1186						$('tr.entryBlock').find('td').html( html );
1187
1188						close_booked_modal();
1189						$('tr.entryBlock').removeClass('booked-loading');
1190						$('tr.entryBlock').find('.booked-appt-list').hide().fadeIn(300);
1191						$('tr.entryBlock').find('.booked-appt-list').addClass('shown');
1192						adjust_calendar_boxes();
1193					}
1194				});
1195			}
1196		}
1197	});
1198
1199	function bookedRemoveEmptyTRs(){
1200		$('table.booked-calendar').find('tr.week').each(function(){
1201			if ($(this).children().length == 0){
1202				$(this).remove();
1203			}
1204		});
1205	}
1206
1207	// Saving state updater
1208	function savingState(show,limit_to){
1209
1210		show = typeof show !== 'undefined' ? show : true;
1211		limit_to = typeof limit_to !== 'undefined' ? limit_to : false;
1212
1213		if (limit_to){
1214
1215			var $savingStateDIV = limit_to.find('li.active .savingState, .topSavingState.savingState, .calendarSavingState');
1216			var $stuffToHide = limit_to.find('.monthName');
1217			var $stuffToTransparent = limit_to.find('table.booked-calendar tbody');
1218
1219		} else {
1220
1221			var $savingStateDIV = $('li.active .savingState, .topSavingState.savingState, .calendarSavingState');
1222			var $stuffToHide = $('.monthName');
1223			var $stuffToTransparent = $('table.booked-calendar tbody');
1224
1225		}
1226
1227		if (show){
1228			$savingStateDIV.fadeIn(200);
1229			$stuffToHide.hide();
1230			$stuffToTransparent.animate({'opacity':0.2},100);
1231		} else {
1232			$savingStateDIV.hide();
1233			$stuffToHide.show();
1234			$stuffToTransparent.animate({'opacity':1},0);
1235		}
1236
1237	}
1238
1239	$(document).ajaxStop(function() {
1240		savingState(false);
1241	});
1242
1243	function init_appt_list_date_picker(){
1244
1245		$('.booked_list_date_picker').each(function(){
1246			var thisDatePicker = $(this);
1247			var minDateVal = thisDatePicker.parents('.booked-appt-list').attr('data-min-date');
1248			var maxDateVal = thisDatePicker.parents('.booked-appt-list').attr('data-max-date');
1249			if (typeof minDateVal == 'undefined'){ var minDateVal = thisDatePicker.attr('data-min-date'); }
1250
1251			thisDatePicker.datepicker({
1252		        dateFormat: 'yy-mm-dd',
1253		        minDate: minDateVal,
1254		        maxDate: maxDateVal,
1255		        showAnim: false,
1256		        beforeShow: function(input, inst) {
1257					$('#ui-datepicker-div').removeClass();
1258					$('#ui-datepicker-div').addClass('booked_custom_date_picker');
1259			    },
1260			    onClose: function(dateText){
1261					$('.booked_list_date_picker_trigger').removeClass('booked-dp-active');
1262			    },
1263			    onSelect: function(dateText){
1264
1265				   	var thisInput 			= $(this),
1266						date				= dateText,
1267						thisList			= thisInput.parents('.booked-list-view'),
1268						defaultDate			= thisList.attr('data-default'),
1269						calendar_id			= thisInput.parents('.booked-list-view-nav').attr('data-calendar-id');
1270
1271					if (typeof defaultDate == 'undefined'){ defaultDate = false; }
1272
1273					if (!calendar_id){ calendar_id = 0; }
1274					thisList.addClass('booked-loading');
1275
1276					var booked_load_list_view_date_booking_options = {
1277						'action'		: 'booked_appointment_list_date',
1278						'date'			: date,
1279						'calendar_id'	: calendar_id,
1280						'force_default'	: defaultDate
1281					};
1282
1283					$(document).trigger("booked-before-loading-appointment-list-booking-options");
1284					thisList.spin('booked_top');
1285
1286					$.ajax({
1287						url: booked_js_vars.ajax_url,
1288						type: 'post',
1289						data: booked_load_list_view_date_booking_options,
1290						success: function( html ) {
1291
1292							thisList.html( html );
1293
1294							init_appt_list_date_picker();
1295							setTimeout(function(){
1296								thisList.removeClass('booked-loading');
1297							},1);
1298
1299						}
1300					});
1301
1302					return false;
1303			    }
1304		    });
1305
1306		});
1307
1308		$('body').on('click','.booked_list_date_picker_trigger',function(e){
1309			e.preventDefault();
1310			if (!$(this).hasClass('booked-dp-active')){
1311				$(this).addClass('booked-dp-active');
1312				$(this).parents('.booked-appt-list').find('.booked_list_date_picker').datepicker('show');
1313			}
1314
1315	    });
1316
1317	}
1318
1319	var BookedTabs = {
1320		bookingModalSelector: '.booked-modal',
1321		tabSelector: '.booked-tabs',
1322		tabNavSelector: '.booked-tabs-nav span',
1323		tabCntSelector: '.booked-tabs-cnt',
1324
1325		Init: function() {
1326			$(document).on( 'click', this.tabNavSelector, this.tabsNav );
1327		},
1328
1329		tabsNav: function( event ) {
1330			event.preventDefault();
1331
1332			BookedTabs.switchToTab( $(this) );
1333			BookedTabs.maybeResizeBookingModal();
1334		},
1335
1336		switchToTab: function( tab_nav_item ) {
1337			var $nav_item = tab_nav_item,
1338				tab_cnt_class = '.' + $nav_item.data('tab-cnt'),
1339				$tabs_container = $nav_item.parents( BookedTabs.tabSelector );
1340
1341			$nav_item
1342				.addClass( 'active' )
1343				.siblings()
1344				.removeClass( 'active' )
1345
1346			$tabs_container
1347				.find( BookedTabs.tabCntSelector + ' ' + tab_cnt_class )
1348				.addClass( 'active' )
1349				.siblings()
1350				.removeClass( 'active' );
1351		},
1352
1353		maybeResizeBookingModal: function() {
1354			if ( ! $(BookedTabs.bookingModalSelector).length ) {
1355				return;
1356			}
1357
1358			resize_booked_modal();
1359		}
1360	}
1361
1362})(jQuery, window, document);
1363
1364// Create Booked Modal
1365function create_booked_modal(){
1366	var windowHeight = jQuery(window).height();
1367	var windowWidth = jQuery(window).width();
1368	if (windowWidth > 720){
1369		var maxModalHeight = windowHeight - 295;
1370	} else {
1371		var maxModalHeight = windowHeight;
1372	}
1373
1374	jQuery('body input, body textarea, body select').blur();
1375	jQuery('body').addClass('booked-noScroll');
1376	jQuery('<div class="booked-modal bm-loading"><div class="bm-overlay"></div><div class="bm-window"><div style="height:100px"></div></div></div>').appendTo('body');
1377	jQuery('.booked-modal .bm-overlay').spin('booked_white');
1378	jQuery('.booked-modal .bm-window').css({'max-height':maxModalHeight+'px'});
1379}
1380
1381var previousRealModalHeight = 100;
1382
1383function resize_booked_modal(){
1384
1385	var windowHeight = jQuery(window).height();
1386	var windowWidth = jQuery(window).width();
1387
1388	var common43 = 43;
1389
1390	if (jQuery('.booked-modal .bm-window .booked-scrollable').length){
1391		var realModalHeight = jQuery('.booked-modal .bm-window .booked-scrollable')[0].scrollHeight;
1392
1393		if (realModalHeight < 100){
1394			realModalHeight = previousRealModalHeight;
1395		} else {
1396			previousRealModalHeight = realModalHeight;
1397		}
1398
1399	} else {
1400		var realModalHeight = 0;
1401	}
1402	var minimumWindowHeight = realModalHeight + common43 + common43;
1403	var modalScrollableHeight = realModalHeight - common43;
1404	var maxModalHeight;
1405	var maxFormHeight;
1406
1407	if (windowHeight < minimumWindowHeight){
1408		modalScrollableHeight = windowHeight - common43 - common43;
1409	} else {
1410		modalScrollableHeight = realModalHeight;
1411	}
1412
1413	if (windowWidth > 720){
1414		maxModalHeight = modalScrollableHeight - 25;
1415		maxFormHeight = maxModalHeight - 15;
1416		var modalNegMargin = (maxModalHeight + 78) / 2;
1417	} else {
1418		maxModalHeight = windowHeight - common43;
1419		maxFormHeight = maxModalHeight - 60;
1420		var modalNegMargin = (maxModalHeight) / 2;
1421	}
1422
1423	jQuery('.booked-modal').css({'margin-top':'-'+modalNegMargin+'px'});
1424	jQuery('.booked-modal .bm-window').css({'max-height':maxModalHeight+'px'});
1425	jQuery('.booked-modal .bm-window .booked-scrollable').css({'max-height':maxFormHeight+'px'});
1426
1427}
1428
1429function close_booked_modal(){
1430	var modal = jQuery('.booked-modal');
1431	modal.fadeOut(200);
1432	modal.addClass('bm-closing');
1433	jQuery('body').removeClass('booked-noScroll');
1434	setTimeout(function(){
1435		modal.remove();
1436	},300);
1437}
1438
1439function init_tooltips(container){
1440	jQuery('.tooltipster').tooltipster({
1441		theme: 		'tooltipster-light',
1442		animation:	'grow',
1443		speed:		200,
1444		delay: 		50,
1445		offsetY:	-15
1446	});
1447}
1448
1449// Function to adjust calendar sizing
1450function adjust_calendar_boxes(){
1451	jQuery('.booked-calendar').each(function(){
1452
1453		var windowWidth = jQuery(window).width();
1454		var smallCalendar = jQuery(this).parents('.booked-calendar-wrap').hasClass('small');
1455		var boxesWidth = jQuery(this).find('tbody tr.week td').width();
1456		var calendarHeight = jQuery(this).height();
1457		boxesHeight = boxesWidth * 1;
1458		jQuery(this).find('tbody tr.week td').height(boxesHeight);
1459		jQuery(this).find('tbody tr.week td .date').css('line-height',boxesHeight+'px');
1460		jQuery(this).find('tbody tr.week td .date .number').css('line-height',boxesHeight+'px');
1461		if (smallCalendar || windowWidth < 720){
1462			jQuery(this).find('tbody tr.week td .date .number').css('line-height',boxesHeight+'px');
1463		} else {
1464			jQuery(this).find('tbody tr.week td .date .number').css('line-height','');
1465		}
1466
1467		var calendarHeight = jQuery(this).height();
1468		jQuery(this).parent().height(calendarHeight);
1469
1470	});
1471}

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.