PageSourceSearch

https://bebow.es/wp-content/plugins/booked/assets/js/functions.js?ver=2.9.1

js bebow.es collected 2026-09-27 06:28:35 UTC 46,314 bytes, 1,469 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		$('.booked-calendar-wrap').on('click', '.page-right, .page-left, .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		$('.booked-calendar-wrap').on('click', '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		$('.booked-list-view').on('click', '.booked-list-view-date-prev,.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		$('.booked-calendar-wrap').on('click', '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		$('.booked-profile-appt-list').on('click', '.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					e.preventDefault();
444					$('#loginform').parents('.booked-form-wrap').find('.booked-custom-error').fadeOut(200).fadeIn(200);
445				}
446			});
447		}
448
449		if ($('#profile-forgot').length){
450			$('#profile-forgot input[type="submit"]').on('click',function(e) {
451				if ($('#profile-forgot input[name="user_login"]').val()){
452					$('#profile-forgot .booked-custom-error').hide();
453				} else {
454					e.preventDefault();
455					$('#profile-forgot').find('.booked-custom-error').fadeOut(200).fadeIn(200);
456				}
457			});
458		}
459
460		// Custom Upload Field
461		if ($('.booked-upload-wrap').length){
462
463			$('.booked-upload-wrap input[type=file]').on('change',function(){
464
465				var fileName = $(this).val();
466				$(this).parent().find('span').html(fileName);
467				$(this).parent().addClass('hasFile');
468
469			});
470
471		}
472
473		// Delete Appointment
474		$('.booked-profile-appt-list').on('click', '.appt-block .cancel', function(e) {
475
476			e.preventDefault();
477
478			var $button 		= $(this),
479				$thisParent		= $button.parents('.appt-block'),
480				appt_id			= $thisParent.attr('data-appt-id');
481
482			confirm_delete = confirm(booked_js_vars.i18n_confirm_appt_delete);
483			if (confirm_delete == true){
484
485				var currentApptCount = parseInt($('.booked-profile-appt-list').find('h4').find('span.count').html());
486				currentApptCount = parseInt(currentApptCount - 1);
487				if (currentApptCount < 1){
488					$('.booked-profile-appt-list').find('h4').find('span.count').html('0');
489					$('.no-appts-message').slideDown('fast');
490				} else {
491					$('.booked-profile-appt-list').find('h4').find('span.count').html(currentApptCount);
492				}
493				
494				$('.appt-block').animate({'opacity':0.4},0);
495
496	  			$thisParent.slideUp('fast',function(){
497					$(this).remove();
498				});
499
500				$.ajax({
501					'url' 		: booked_js_vars.ajax_url,
502					'method' 	: 'post',
503					'data'		: {
504						'action'     	: 'booked_cancel_appt',
505						'appt_id'     	: appt_id
506					},
507					success: function(data) {
508						$('.appt-block').animate({'opacity':1},150);
509					}
510				});
511
512			}
513
514			return false;
515
516		});
517
518		$('body').on('touchstart click','.bm-overlay, .bm-window .close, .booked-form .cancel',function(e){
519			e.preventDefault();
520			close_booked_modal();
521			return false;
522		});
523
524		$('body')
525		.on('focusin', '.booked-form input', function() {
526			if(this.title==this.value) {
527				$(this).addClass('hasContent');
528				this.value = '';
529			}
530		}).on('focusout', '.booked-form input', function(){
531			if(this.value==='') {
532				$(this).removeClass('hasContent');
533				this.value = this.title;
534			}
535		});
536
537		$('body').on('change','.booked-form input',function(){
538
539			var condition = $(this).attr('data-condition'),
540				thisVal = $(this).val();
541
542			if (condition && $('.condition-block').length) {
543				$('.condition-block.'+condition).hide();
544				$('#condition-'+thisVal).fadeIn(200);
545				resize_booked_modal();
546			}
547
548		});
549
550		// Perform AJAX login on form submit
551	    $('body').on('submit','form#ajaxlogin', function(e){
552		    e.preventDefault();
553
554	        $('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);
555	        resize_booked_modal();
556
557	        var $this = $(this),
558	        	date = $this.data('date'),
559	        	title = $this.data('title'),
560	        	timeslot = $this.data('timeslot'),
561	        	calendar_id = $this.data('calendar-id');
562
563	        $.ajax({
564		        type	: 'post',
565				url 	: booked_js_vars.ajax_url,
566				data	: $('form#ajaxlogin').serialize(),
567				success	: function(data) {
568					if (data == 'success'){
569
570						// close the modal box
571						close_booked_modal();
572
573						// reopen the modal box
574						var $button = $( '<button data-title="' + title + '" data-timeslot="' + timeslot + '" data-date="' + date + '" data-calendar-id="' + calendar_id + '"></button>' );
575						$button.on( 'click', window.bookedNewAppointment );
576						$button.triggerHandler( 'click' );
577						$button.unbind( 'click', window.bookedNewAppointment );
578						$button.detach();
579						
580					} else {
581						$('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);
582						resize_booked_modal();
583					}
584	            }
585	        });
586	        e.preventDefault();
587	    });
588	    
589	    $('body').on('click','.booked-forgot-password',function(e){
590			
591			e.preventDefault();
592			$('#ajaxlogin').hide();
593			$('#ajaxforgot').show();
594			
595			resize_booked_modal();
596			 
597	    });
598	    
599	     $('body').on('click','.booked-forgot-goback',function(e){
600			
601			e.preventDefault();
602			$('#ajaxlogin').show();
603			$('#ajaxforgot').hide();
604			
605			resize_booked_modal();
606			 
607	    });
608	    
609	    // Perform AJAX login on form submit
610
611	    $('body').on('submit','form#ajaxforgot', function(e){
612		    e.preventDefault();
613
614	        $('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);
615	        resize_booked_modal();
616
617	        var $this = $(this);
618
619	        $.ajax({
620		        type	: 'post',
621				url 	: booked_js_vars.ajax_url,
622				data	: $('form#ajaxforgot').serialize(),
623				success	: function(data) {
624					if (data == 'success'){
625
626						e.preventDefault();
627						$('#ajaxlogin').show();
628						$('#ajaxforgot').hide();
629						
630						$('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);
631						resize_booked_modal();
632						
633					} else {
634						
635						//console.log(data);
636						$('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);
637						resize_booked_modal();
638						
639					}
640	            }
641	        });
642	        e.preventDefault();
643	    });
644
645
646		// Submit the "Request Appointment" Form
647		$('body').on('click','.booked-form input#submit-request-appointment',function(e){
648			
649			$('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);
650	        resize_booked_modal();
651			
652			e.preventDefault();
653			
654			var customerType        = $('#newAppointmentForm input[name=customer_type]').val(),
655				customerID          = $('#newAppointmentForm input[name=user_id]').val(),
656				name                = $('#newAppointmentForm input[name=booked_appt_name]').val(),
657				surname             = $('#newAppointmentForm input[name=booked_appt_surname]').val(),
658				surnameActive		= $('#newAppointmentForm input[name=booked_appt_surname]').length,
659				guest_name          = $('#newAppointmentForm input[name=guest_name]').val(),
660				guest_surname      	= $('#newAppointmentForm input[name=guest_surname]').val(),
661				guest_surnameActive = $('#newAppointmentForm input[name=guest_surname]').length,
662				guest_email			= $('#newAppointmentForm input[name=guest_email]').val(),
663				guest_emailActive 	= $('#newAppointmentForm input[name=guest_email]').length,
664				email               = $('#newAppointmentForm input[name=booked_appt_email]').val(),
665				password            = $('#newAppointmentForm input[name=booked_appt_password]').val(),
666				showRequiredError   = false,
667				ajaxRequests        = [];
668
669			$(this).parents('.booked-form').find('input,textarea,select').each(function(i,field){
670
671				var required = $(this).attr('required');
672
673				if (required && $(field).attr('type') == 'hidden'){
674					var fieldParts = $(field).attr('name');
675					fieldParts = fieldParts.split('---');
676					fieldName = fieldParts[0];
677					fieldNumber = fieldParts[1].split('___');
678					fieldNumber = fieldNumber[0];
679
680					if (fieldName == 'radio-buttons-label'){
681						var radioValue = false;
682						$('input:radio[name="single-radio-button---'+fieldNumber+'[]"]:checked').each(function(){
683							if ($(this).val()){
684								radioValue = $(this).val();
685							}
686						});
687						if (!radioValue){
688							showRequiredError = true;
689						}
690					} else if (fieldName == 'checkboxes-label'){
691						var checkboxValue = false;
692						$('input:checkbox[name="single-checkbox---'+fieldNumber+'[]"]:checked').each(function(){
693							if ($(this).val()){
694								checkboxValue = $(this).val();
695							}
696						});
697						if (!checkboxValue){
698							showRequiredError = true;
699						}
700					}
701
702				} else if (required && $(field).attr('type') != 'hidden' && $(field).val() == ''){
703		            showRequiredError = true;
704		        }
705
706		    });
707
708		    if (showRequiredError) {
709			    $('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);
710				resize_booked_modal();
711			    return false;
712		    }
713
714			if ( customerType == 'new' && !name || customerType == 'new' && surnameActive && !surname || customerType == 'new' && !email || customerType == 'new' && !password ) {
715				$('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);
716				resize_booked_modal();
717				return false;
718			}
719			
720			if ( customerType == 'guest' && !guest_name || customerType == 'guest' && guest_emailActive && !guest_email || customerType == 'guest' && guest_surnameActive && !guest_surname ){
721				$('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);
722				resize_booked_modal();
723				return false;
724			}
725			
726			if (customerType == 'current' && customerID ||
727				customerType == 'guest' && guest_name && !guest_surnameActive && !guest_emailActive ||
728				customerType == 'guest' && guest_name && guest_surnameActive && guest_surname && !guest_emailActive ||
729				customerType == 'guest' && guest_name && guest_emailActive && guest_email && !guest_surnameActive ||
730				customerType == 'guest' && guest_name && guest_emailActive && guest_email && guest_surnameActive && guest_surname ) {
731			   
732			    SubmitRequestAppointment.currentUserOrGuest();
733			
734			}
735
736			if (customerType == 'new' && name && email && password) {
737				if ( !surnameActive || surnameActive && surname ){
738					SubmitRequestAppointment.newUser();
739				}
740			}
741
742		});
743
744		var SubmitRequestAppointment = {
745
746			formSelector: '#newAppointmentForm',
747			formBtnRequestSelector: '.booked-form input#submit-request-appointment',
748			formStatusSelector: 'p.status',
749			formSubmitBtnSelector: '#submit-request-appointment',
750
751			apptContainerSelector: '.booked-appointment-details',
752
753			baseFields: 	[ 'guest_name','guest_surname','guest_email','action', 'customer_type', 'user_id' ],
754			apptFields: 	[ 'appoinment', 'calendar_id', 'title', 'date', 'timestamp', 'timeslot' ],
755			userFields: 	[ 'booked_appt_name','booked_appt_surname','booked_appt_email', 'booked_appt_password' ],
756			captchaFields: 	[ 'captcha_word', 'captcha_code' ],
757
758			currentApptIndex: false,
759			currentApptCounter: false,
760			hasAnyErrors: false,
761
762			currentUserOrGuest: function() {
763				var total_appts = SubmitRequestAppointment._totalAppts();
764
765				if ( ! total_appts ) {
766					return;
767				}
768
769				SubmitRequestAppointment._showLoadingMessage();
770				SubmitRequestAppointment._resetDefaultValues();
771
772				var data = SubmitRequestAppointment._getBaseData();
773
774				SubmitRequestAppointment.currentApptIndex = 0;
775				SubmitRequestAppointment.currentApptCounter = 1;
776				SubmitRequestAppointment._doRequestAppointment( data, total_appts );
777				
778			},
779
780			// pretty much the same as SubmitRequestAppointment.currentUserOrGuest(), however, it include the user name, email and password
781			newUser: function() {
782				var total_appts = SubmitRequestAppointment._totalAppts();
783
784				if ( ! total_appts ) {
785					return;
786				}
787
788				SubmitRequestAppointment._showLoadingMessage();
789				SubmitRequestAppointment._resetDefaultValues();
790
791				var data = SubmitRequestAppointment._getBaseData();
792
793				// when there are more than one appointment, we need to make the registration request first and then loop the appointments
794				if ( total_appts > 1 ) {
795					var data_obj_with_no_reference = null;
796					data_obj_with_no_reference = $.extend( true, {}, data );
797					data_obj_with_no_reference = SubmitRequestAppointment._addUserRegistrationData( data_obj_with_no_reference );
798					SubmitRequestAppointment._requestUserRegistration( data_obj_with_no_reference );
799
800					data.customer_type = 'current';
801				} else {
802					// add user registration fields values
803					data = SubmitRequestAppointment._addUserRegistrationData( data );
804				}
805
806				SubmitRequestAppointment.currentApptIndex = 0;
807				SubmitRequestAppointment._doRequestAppointment( data, total_appts );
808			},
809
810			_doRequestAppointment: function( data, total_appts ) {
811				
812				var appt_fields = SubmitRequestAppointment.apptFields;
813
814				// for the first item only
815				if ( SubmitRequestAppointment.currentApptIndex === 0 ) {
816					SubmitRequestAppointment._hideCancelBtn();
817					SubmitRequestAppointment._disableSubmitBtn();
818					SubmitRequestAppointment.hasAnyErrors = false;
819				}
820				// <------end
821
822				var data_obj_with_no_reference = $.extend( true, {}, data );
823
824				// add the appointment fields to the data
825				for (var i = 0; i < appt_fields.length; i++) {
826					data_obj_with_no_reference[ appt_fields[i] ] = SubmitRequestAppointment._getFieldVal( appt_fields[i], SubmitRequestAppointment.currentApptIndex );
827				}
828
829				var calendar_id = SubmitRequestAppointment._getFieldVal( 'calendar_id', SubmitRequestAppointment.currentApptIndex );
830				data_obj_with_no_reference = SubmitRequestAppointment._addCustomFieldsData( data_obj_with_no_reference, calendar_id );
831
832				var $appt = SubmitRequestAppointment._getApptElement( SubmitRequestAppointment.currentApptIndex );
833
834				if ( ! $appt.hasClass('skip') ) {
835					$.ajax({
836						type    : 'post',
837						url     : booked_js_vars.ajax_url,
838						data    : data_obj_with_no_reference,
839						success	: function( response ) {
840
841							//SubmitRequestAppointment._enableSubmitBtn();
842							//SubmitRequestAppointment._showCancelBtn();
843
844							//console.log(response);
845							//return;
846
847							SubmitRequestAppointment._requestAppointmentResponseHandler( response );
848							SubmitRequestAppointment.currentApptIndex++;
849
850							setTimeout( function() {
851								if ( SubmitRequestAppointment.currentApptCounter === total_appts ) {
852									// for the last item only
853									if ( ! SubmitRequestAppointment.hasAnyErrors ) {
854										SubmitRequestAppointment._onAfterRequestAppointment();
855									} else {
856										SubmitRequestAppointment._enableSubmitBtn();
857										SubmitRequestAppointment._showCancelBtn();
858									}
859									// <------end
860								} else {
861									SubmitRequestAppointment.currentApptCounter++;
862									SubmitRequestAppointment._doRequestAppointment( data, total_appts );
863								}
864							}, 100 );
865						}
866					});
867				} else {
868					SubmitRequestAppointment.currentApptIndex++;
869					SubmitRequestAppointment.currentApptCounter++;
870					SubmitRequestAppointment._doRequestAppointment( data, total_appts, SubmitRequestAppointment.currentApptIndex );
871				}
872			},
873
874			_totalAppts: function() {
875				return $(SubmitRequestAppointment.formSelector + ' input[name="appoinment[]"]').length;
876			},
877
878			_getBaseData: function() {
879				var data = {},
880					fields = SubmitRequestAppointment.baseFields;
881
882				// set up the base form data
883				for ( var i = 0; i < fields.length; i++ ) {
884					data[ fields[i] ] = SubmitRequestAppointment._getFieldVal( fields[i] );
885				}
886
887				data['is_fe_form'] = true;
888				data['total_appts'] = SubmitRequestAppointment._totalAppts();
889
890				return data;
891			},
892
893			_getFieldVal: function( field_name, field_index ) {
894				var field_name = typeof field_name === 'undefined' ? '' : field_name,
895					field_index = typeof field_index === 'undefined' ? false : field_index,
896					selector = SubmitRequestAppointment.formSelector + ' ';
897					
898				if ( field_index === false ) {
899					selector += ' [name=' + field_name + ']';
900					return $( selector ).val();
901				}
902
903				selector += ' [name="' + field_name + '[]"]';
904				return $( selector ).eq( field_index ).val();
905			},
906
907			_resetDefaultValues: function() {
908				 $('.booked-form input').each(function(){
909					var thisVal = $(this).val(),
910						thisDefault = $(this).attr('title');
911
912					if ( thisDefault == thisVal ){ 
913						$(this).val(''); 
914					}
915				});
916			},
917
918			_resetToDefaultValues: function() {
919				$('.booked-form input').each(function(){
920					var thisVal = $(this).val(),
921						thisDefault = $(this).attr('title');
922
923					if ( ! thisVal ){ 
924						$(this).val( thisDefault ); 
925					}
926				});
927			},
928
929			_addUserRegistrationData: function( data ) {
930				// populate the user data
931				$.each( SubmitRequestAppointment.userFields, function( index, field_name ) {
932					data[ field_name ] = SubmitRequestAppointment._getFieldVal( field_name );
933				} );
934
935				// populate captcha data if available
936				$.each( SubmitRequestAppointment.captchaFields, function( index, field_name ) {
937					var field_value = SubmitRequestAppointment._getFieldVal( field_name );
938
939					if ( ! field_value ) {
940						return;
941					}
942
943					data[ field_name ] = field_value;
944				} );
945
946				return data;
947			},
948
949			_addCustomFieldsData: function( data, calendar_id ) {
950				var custom_fields_data = $('.cf-block [name]')
951					.filter( function( index ) {
952						var $this = $(this);
953						return parseInt($this.data('calendar-id')) === parseInt(calendar_id) && $this.attr('name').match(/---\d+/g);
954					} )
955					.each( function( index ) {
956						var $this = $(this),
957							name = $this.attr('name'),
958							value = $this.val(),
959							type = $this.attr('type');
960
961						if ( ! value ) {
962							return;
963						}
964
965						if ( ! name.match(/checkbox|radio+/g) ) {
966							data[ name ] = value;
967							return;
968						}
969
970						if ( name.match(/radio+/g) && $this.is(':checked') ) {
971							data[ name ] = value;
972							return;
973						}
974
975						if ( ! name.match(/radio+/g) && typeof data[ name ] === 'undefined' || ! name.match(/radio+/g) && data[ name ].constructor !== Array ) {
976							data[ name ] = [];
977						}
978
979						if ( ! $this.is(':checked') ) {
980							return;
981						}
982
983						data[ name ].push( value );
984					} );
985
986				return data;
987			},
988
989			_requestUserRegistration: function( base_data, appt_index ) {
990				$.ajax({
991					type    : 'post',
992					url     : booked_js_vars.ajax_url,
993					data    : base_data,
994					async   : false,
995					success	: function( response ) {
996						SubmitRequestAppointment._requestUserRegistrationResponseHandler( response );
997					}
998				});
999			},
1000
1001			_requestUserRegistrationResponseHandler: function( response ) {
1002				var response_parts = response.split('###'),
1003					data_result = response_parts[0].substr( response_parts[0].length - 5 );
1004
1005				if ( data_result === 'error' ) {
1006					// do something on registration failure
1007					return;
1008				}
1009
1010				// do something on successful registration
1011			},
1012
1013			_requestAppointment: function( response ) {
1014				SubmitRequestAppointment._requestAppointmentResponseHandler( response );
1015			},
1016
1017			_requestAppointmentResponseHandler: function( response ) {
1018				var response_parts = response.split('###'),
1019					data_result = response_parts[0].substr( response_parts[0].length - 5 );
1020
1021				if ( data_result === 'error' ) {
1022					SubmitRequestAppointment._requestAppointmentOnError( response_parts );
1023					return;
1024				}
1025
1026				SubmitRequestAppointment._requestAppointmentOnSuccess( response_parts );
1027			},
1028
1029			_requestAppointmentOnError: function( response_parts ) {
1030				var $apptEl = SubmitRequestAppointment._getApptElement();
1031
1032				$(document).trigger("booked-on-requested-appt-error",[$apptEl]);
1033
1034				SubmitRequestAppointment._highlightAppt();
1035
1036				SubmitRequestAppointment._setStatusMsg( response_parts[1] );
1037
1038				SubmitRequestAppointment.hasAnyErrors = true;
1039
1040				resize_booked_modal();
1041			},
1042
1043			_requestAppointmentOnSuccess: function( response_parts ) {
1044				var $apptEl = SubmitRequestAppointment._getApptElement();
1045
1046				$(document).trigger("booked-on-requested-appt-success",[$apptEl]);
1047
1048				SubmitRequestAppointment._unhighlightAppt();
1049			},
1050
1051			_onAfterRequestAppointment: function() {
1052				var redirectObj = { redirect : false };
1053				var redirect = $(document).trigger("booked-on-requested-appointment",[redirectObj]);
1054
1055				if ( redirectObj.redirect ) {
1056					return;
1057				}
1058
1059				if ( booked_js_vars.profilePage ) {
1060					window.location = booked_js_vars.profilePage;
1061					return;
1062				}
1063
1064				SubmitRequestAppointment._reloadApptsList();
1065				SubmitRequestAppointment._reloadCalendarTable();
1066			},
1067
1068			_setStatusMsg: function( msg ) {
1069				var form_status_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formStatusSelector;
1070				$( form_status_selector ).show().html( '<i class="booked-icon booked-icon-alert" style="color:#E35656"></i>&nbsp;&nbsp;&nbsp;' + msg );
1071			},
1072
1073			_getApptElement: function( appt_index ) {
1074				var appt_index = typeof appt_index === 'undefined' ? SubmitRequestAppointment.currentApptIndex : appt_index,
1075					appt_cnt_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.apptContainerSelector;
1076
1077				return $( appt_cnt_selector ).eq( appt_index );
1078			},
1079
1080			_highlightAppt: function( msg ) {
1081				var $apptEl = SubmitRequestAppointment._getApptElement();
1082
1083				if ( ! $apptEl.length ) {
1084					return;
1085				}
1086
1087				$apptEl.addClass('has-error');
1088			},
1089
1090			_unhighlightAppt: function( msg ) {
1091				var $apptEl = SubmitRequestAppointment._getApptElement();
1092
1093				if ( ! $apptEl.length ) {
1094					return;
1095				}
1096
1097				$apptEl.removeClass('has-error').addClass('skip');
1098			},
1099
1100			_enableSubmitBtn: function() {
1101				var btn_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formSubmitBtnSelector;
1102				$( btn_selector ).attr( 'disabled', false );
1103			},
1104
1105			_disableSubmitBtn: function() {
1106				var btn_selector = SubmitRequestAppointment.formSelector + ' ' + SubmitRequestAppointment.formSubmitBtnSelector;
1107				$( btn_selector ).attr( 'disabled', true );
1108			},
1109
1110			_showCancelBtn: function() {
1111				$( SubmitRequestAppointment.formSelector ).find('button.cancel').show();
1112			},
1113
1114			_hideCancelBtn: function() {
1115				$( SubmitRequestAppointment.formSelector ).find('button.cancel').hide();
1116			},
1117
1118			_showLoadingMessage: function() {
1119				$('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);
1120			},
1121
1122			_reloadApptsList: function() {
1123				if ( ! $('.booked-appt-list').length ){
1124					return;
1125				}
1126
1127				$('.booked-appt-list').each( function() {
1128					var $thisApptList  = $(this),
1129						date          = $thisApptList.attr('data-list-date'),
1130						thisList      = $thisApptList.parents('.booked-list-view'),
1131						defaultDate   = thisList.attr('data-default'),
1132						calendar_id   = parseInt($thisApptList.find('.booked-list-view-nav').attr('data-calendar-id')) || 0;
1133					
1134					defaultDate = typeof defaultDate === 'undefined' ? false : defaultDate;
1135					calendar_id = calendar_id ? calendar_id : 0;
1136
1137					thisList.addClass('booked-loading');
1138
1139					var booked_load_list_view_date_booking_options = {
1140						'action'		: 'booked_appointment_list_date',
1141						'date'			: date,
1142						'calendar_id'	: calendar_id,
1143						'force_default'	: defaultDate
1144					};
1145					
1146					$(document).trigger("booked-before-loading-appointment-list-booking-options");
1147					thisList.spin('booked_top');
1148				
1149					$.ajax({
1150						url: booked_js_vars.ajax_url,
1151						type: 'post',
1152						data: booked_load_list_view_date_booking_options,
1153						success: function( html ) {
1154							thisList.html( html );
1155							
1156							close_booked_modal();
1157							init_appt_list_date_picker();
1158							setTimeout(function(){
1159								thisList.removeClass('booked-loading');
1160							},1);
1161						}
1162					});
1163				});
1164			},
1165
1166			_reloadCalendarTable: function() {
1167				if ( ! $('td.active').length ) {
1168					return;
1169				}
1170
1171				var $activeTD = $('td.active'),
1172					activeDate = $activeTD.attr('data-date'),
1173					calendar_id = parseInt( $activeTD.parents('table').data('calendar-id') ) || 0;
1174
1175				booked_load_calendar_date_booking_options = { 'action':'booked_calendar_date', 'date':activeDate, 'calendar_id':calendar_id };
1176				$(document).trigger("booked-before-loading-calendar-booking-options");
1177				
1178				$.ajax({
1179					url: booked_js_vars.ajax_url,
1180					type: 'post',
1181					data: booked_load_calendar_date_booking_options,
1182					success: function( html ) {
1183						
1184						$('tr.entryBlock').find('td').html( html );
1185						
1186						close_booked_modal();
1187						$('tr.entryBlock').removeClass('booked-loading');
1188						$('tr.entryBlock').find('.booked-appt-list').hide().fadeIn(300);
1189						$('tr.entryBlock').find('.booked-appt-list').addClass('shown');
1190						adjust_calendar_boxes();
1191					}
1192				});
1193			}
1194		}
1195	});
1196	
1197	function bookedRemoveEmptyTRs(){
1198		$('table.booked-calendar').find('tr.week').each(function(){
1199			if ($(this).children().length == 0){
1200				$(this).remove();
1201			}
1202		});
1203	}
1204
1205	// Saving state updater
1206	function savingState(show,limit_to){
1207
1208		show = typeof show !== 'undefined' ? show : true;
1209		limit_to = typeof limit_to !== 'undefined' ? limit_to : false;
1210
1211		if (limit_to){
1212
1213			var $savingStateDIV = limit_to.find('li.active .savingState, .topSavingState.savingState, .calendarSavingState');
1214			var $stuffToHide = limit_to.find('.monthName');
1215			var $stuffToTransparent = limit_to.find('table.booked-calendar tbody');
1216
1217		} else {
1218
1219			var $savingStateDIV = $('li.active .savingState, .topSavingState.savingState, .calendarSavingState');
1220			var $stuffToHide = $('.monthName');
1221			var $stuffToTransparent = $('table.booked-calendar tbody');
1222
1223		}
1224
1225		if (show){
1226			$savingStateDIV.fadeIn(200);
1227			$stuffToHide.hide();
1228			$stuffToTransparent.animate({'opacity':0.2},100);
1229		} else {
1230			$savingStateDIV.hide();
1231			$stuffToHide.show();
1232			$stuffToTransparent.animate({'opacity':1},0);
1233		}
1234
1235	}
1236
1237	$(document).ajaxStop(function() {
1238		savingState(false);
1239	});
1240	
1241	function init_appt_list_date_picker(){
1242		
1243		$('.booked_list_date_picker').each(function(){
1244			var thisDatePicker = $(this);
1245			var minDateVal = thisDatePicker.parents('.booked-appt-list').attr('data-min-date');
1246			var maxDateVal = thisDatePicker.parents('.booked-appt-list').attr('data-max-date');
1247			if (typeof minDateVal == 'undefined'){ var minDateVal = thisDatePicker.attr('data-min-date'); }
1248		
1249			thisDatePicker.datepicker({
1250		        dateFormat: 'yy-mm-dd',
1251		        minDate: minDateVal,
1252		        maxDate: maxDateVal,
1253		        showAnim: false,
1254		        beforeShow: function(input, inst) {
1255					$('#ui-datepicker-div').removeClass();
1256					$('#ui-datepicker-div').addClass('booked_custom_date_picker');
1257			    },
1258			    onClose: function(dateText){
1259					$('.booked_list_date_picker_trigger').removeClass('booked-dp-active'); 
1260			    },
1261			    onSelect: function(dateText){
1262				   
1263				   	var thisInput 			= $(this),
1264						date				= dateText,
1265						thisList			= thisInput.parents('.booked-list-view'),
1266						defaultDate			= thisList.attr('data-default'),
1267						calendar_id			= thisInput.parents('.booked-list-view-nav').attr('data-calendar-id');
1268						
1269					if (typeof defaultDate == 'undefined'){ defaultDate = false; }
1270						
1271					if (!calendar_id){ calendar_id = 0; }
1272					thisList.addClass('booked-loading');
1273					
1274					var booked_load_list_view_date_booking_options = {
1275						'action'		: 'booked_appointment_list_date',
1276						'date'			: date,
1277						'calendar_id'	: calendar_id,
1278						'force_default'	: defaultDate
1279					};
1280					
1281					$(document).trigger("booked-before-loading-appointment-list-booking-options");
1282					thisList.spin('booked_top');
1283				
1284					$.ajax({
1285						url: booked_js_vars.ajax_url,
1286						type: 'post',
1287						data: booked_load_list_view_date_booking_options,
1288						success: function( html ) {
1289							
1290							thisList.html( html );
1291							
1292							init_appt_list_date_picker();
1293							setTimeout(function(){
1294								thisList.removeClass('booked-loading');
1295							},1);
1296							
1297						}
1298					});
1299					
1300					return false;
1301			    }
1302		    });
1303		    
1304		});
1305		
1306		$('body').on('click','.booked_list_date_picker_trigger',function(e){
1307			e.preventDefault();
1308			if (!$(this).hasClass('booked-dp-active')){
1309				$(this).addClass('booked-dp-active');
1310				$(this).parents('.booked-appt-list').find('.booked_list_date_picker').datepicker('show');
1311			}
1312			
1313	    }); 
1314	    
1315	}
1316
1317	var BookedTabs = {
1318		bookingModalSelector: '.booked-modal',
1319		tabSelector: '.booked-tabs',
1320		tabNavSelector: '.booked-tabs-nav span',
1321		tabCntSelector: '.booked-tabs-cnt',
1322
1323		Init: function() {
1324			$(document).on( 'click', this.tabNavSelector, this.tabsNav );
1325		},
1326
1327		tabsNav: function( event ) {
1328			event.preventDefault();
1329
1330			BookedTabs.switchToTab( $(this) );
1331			BookedTabs.maybeResizeBookingModal();
1332		},
1333
1334		switchToTab: function( tab_nav_item ) {
1335			var $nav_item = tab_nav_item,
1336				tab_cnt_class = '.' + $nav_item.data('tab-cnt'),
1337				$tabs_container = $nav_item.parents( BookedTabs.tabSelector );
1338
1339			$nav_item
1340				.addClass( 'active' )
1341				.siblings()
1342				.removeClass( 'active' )
1343
1344			$tabs_container
1345				.find( BookedTabs.tabCntSelector + ' ' + tab_cnt_class )
1346				.addClass( 'active' )
1347				.siblings()
1348				.removeClass( 'active' );
1349		},
1350
1351		maybeResizeBookingModal: function() {
1352			if ( ! $(BookedTabs.bookingModalSelector).length ) {
1353				return;
1354			}
1355			
1356			resize_booked_modal();
1357		}
1358	}
1359
1360})(jQuery, window, document);
1361
1362// Create Booked Modal
1363function create_booked_modal(){
1364	var windowHeight = jQuery(window).height();
1365	var windowWidth = jQuery(window).width();
1366	if (windowWidth > 720){
1367		var maxModalHeight = windowHeight - 295;
1368	} else {
1369		var maxModalHeight = windowHeight;
1370	}
1371	
1372	jQuery('body input, body textarea, body select').blur();
1373	jQuery('body').addClass('booked-noScroll');
1374	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');
1375	jQuery('.booked-modal .bm-overlay').spin('booked_white');
1376	jQuery('.booked-modal .bm-window').css({'max-height':maxModalHeight+'px'});
1377}
1378
1379var previousRealModalHeight = 100;
1380
1381function resize_booked_modal(){
1382	
1383	var windowHeight = jQuery(window).height();
1384	var windowWidth = jQuery(window).width();
1385	
1386	var common43 = 43;
1387	
1388	if (jQuery('.booked-modal .bm-window .booked-scrollable').length){
1389		var realModalHeight = jQuery('.booked-modal .bm-window .booked-scrollable')[0].scrollHeight;
1390		
1391		if (realModalHeight < 100){
1392			realModalHeight = previousRealModalHeight;
1393		} else {
1394			previousRealModalHeight = realModalHeight;
1395		}
1396		
1397	} else {
1398		var realModalHeight = 0;
1399	}
1400	var minimumWindowHeight = realModalHeight + common43 + common43;
1401	var modalScrollableHeight = realModalHeight - common43;
1402	var maxModalHeight;
1403	var maxFormHeight;
1404	
1405	if (windowHeight < minimumWindowHeight){
1406		modalScrollableHeight = windowHeight - common43 - common43;
1407	} else {
1408		modalScrollableHeight = realModalHeight;
1409	}
1410	
1411	if (windowWidth > 720){
1412		maxModalHeight = modalScrollableHeight - 25;
1413		maxFormHeight = maxModalHeight - 15;
1414		var modalNegMargin = (maxModalHeight + 78) / 2;
1415	} else {
1416		maxModalHeight = windowHeight - common43;
1417		maxFormHeight = maxModalHeight - 60 - common43;
1418		var modalNegMargin = (maxModalHeight) / 2;
1419	}
1420	
1421	jQuery('.booked-modal').css({'margin-top':'-'+modalNegMargin+'px'});
1422	jQuery('.booked-modal .bm-window').css({'max-height':maxModalHeight+'px'});
1423	jQuery('.booked-modal .bm-window .booked-scrollable').css({'max-height':maxFormHeight+'px'});
1424	
1425}
1426
1427function close_booked_modal(){
1428	var modal = jQuery('.booked-modal');
1429	modal.fadeOut(200);
1430	modal.addClass('bm-closing');
1431	jQuery('body').removeClass('booked-noScroll');
1432	setTimeout(function(){
1433		modal.remove();
1434	},300);
1435}
1436
1437function init_tooltips(container){
1438	jQuery('.tooltipster').tooltipster({
1439		theme: 		'tooltipster-light',
1440		animation:	'grow',
1441		speed:		200,
1442		delay: 		50,
1443		offsetY:	-15
1444	});
1445}
1446
1447// Function to adjust calendar sizing
1448function adjust_calendar_boxes(){
1449	jQuery('.booked-calendar').each(function(){
1450		
1451		var windowWidth = jQuery(window).width();
1452		var smallCalendar = jQuery(this).parents('.booked-calendar-wrap').hasClass('small');
1453		var boxesWidth = jQuery(this).find('tbody tr.week td').width();
1454		var calendarHeight = jQuery(this).height();
1455		boxesHeight = boxesWidth * 1;
1456		jQuery(this).find('tbody tr.week td').height(boxesHeight);
1457		jQuery(this).find('tbody tr.week td .date').css('line-height',boxesHeight+'px');
1458		jQuery(this).find('tbody tr.week td .date .number').css('line-height',boxesHeight+'px');
1459		if (smallCalendar || windowWidth < 720){
1460			jQuery(this).find('tbody tr.week td .date .number').css('line-height',boxesHeight+'px');
1461		} else {
1462			jQuery(this).find('tbody tr.week td .date .number').css('line-height','');
1463		}
1464
1465		var calendarHeight = jQuery(this).height();
1466		jQuery(this).parent().height(calendarHeight);
1467
1468	});
1469}

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.