1; 2(function ($, window, document, undefined) { 3 "use strict"; 4 var pluginName = "amPatronRoomPicker", 5 defaults = { 6 singleScene: false, 7 animation: true, 8 templates: false, 9 enablePatronNotes: false, 10 enableExpectedAttendees: false, 11 expectedAttendeesRequired: false, 12 emailRequired: false, 13 layoutRequired: false, 14 chargingEnabled: false, 15 ecommerceEnabled: false, 16 pinlessAuth: false, 17 phoneRequired: false, 18 loginRequired: false, 19 useSetupBreakdown: true, 20 adjustSetupBreakdown: false, 21 roomsPatronDetailsReadonly: false, 22 timezone: 'America/New_York', 23 scenes: [] 24 }; 25 var self = false; 26 // The actual plugin constructor 27 function Plugin(element, options) { 28 self = this; 29 this.element = element; 30 this.$element = $(element); 31 this.settings = $.extend(true, {}, defaults, options); 32 this._defaults = defaults; 33 this._name = pluginName; 34 this.booking = {}; 35 self.locations = {}; 36 self.rooms = []; 37 self.moving = false; 38 self.singleBranch = false; 39 this.init(); 40 } 41 $.extend(true, Plugin.prototype, $.fn['amShared']); 42 $.extend(Plugin.prototype, { 43 init: function () { 44 self._buildInterface(); 45 self._bindEvents(); 46 }, 47 _buildInterface: function () { 48 // self.extras=$('.amrp-room-extras').clone(true).removeAttr('style'); 49 self.holder = $('<div class="amrp-holder"></div>').appendTo(self.element); 50 self.screenHeader = $('<div class="amrp-screen-header"></div>').appendTo(self.holder).hide(); 51 self.chooseScreen = $('<div class="amrp-choose-screen"></div>').appendTo(self.holder); 52 self.reserveScreen = $('<div class="amrp-reserve-screen"></div>').appendTo(self.holder).hide(); 53 self.confirmScreen = $('<div class="amrp-confirm-screen"></div>').appendTo(self.holder).hide(); 54 self.screenThankyou = $('<div class="amrp-thanks-screen"></div>').appendTo(self.holder).hide(); 55 // self.chooseTabs = $('<ul class="nav nav-tabs" role="tablist">'+ 56 // '<li class="active"><a href="#bblocation" data-toggle="tab" data-type="location">Book by location</a></li>'+ 57 // '<li><a href="#bbresource" data-toggle="tab" data-type="resource">Book by resource</a></li>'+ 58 // // '<li><a href="#bbavailability" data-toggle="tab" data-type="availability">Book by availability</a></li>'+ 59 // '</ul>').appendTo(self.chooseScreen); 60 /*=============start book by location===========*/ 61 var topRow = $('<div></div>').addClass('row').appendTo(self.chooseScreen); 62 self.locationBottomRow = $('<div></div>').appendTo(self.chooseScreen).hide(); 63 self.locationCol = $('<div></div>').addClass('col-md-4').prepend('<h2>Choose a branch</h2>').appendTo(topRow); 64 self.locationClosed = $('<div>Sorry this branch is closed on the selected day</div>').appendTo(self.chooseScreen).hide(); 65 var dateCol = $('<div>' + '<div class="form-group">' + '<div class="input-group amrp-datepicker">' + '<input type="text" class="form-control" />' + '<span class="input-group-addon">' + '<span class="am-events"></span>' + '</span>' + '</div>' + '</div>' + +'</div>').addClass('col-md-4').prepend('<h2>Choose a date</h2>').appendTo(topRow); 66 var timeCol = $('<div></div>').addClass('col-md-4').prepend('<h2>Choose a time</h2>').appendTo(topRow); 67 self.timeRange = $('<div class="amrp-time-range input-group"></div>').appendTo(timeCol); 68 self.startTime = $('<input autocomplete="off" id="stime" class="form-control input-small" value="9:00am"/>').appendTo(self.timeRange) 69 $('<span class="input-group-addon"></span>').text('to').appendTo(self.timeRange); 70 self.endTime = $('<input autocomplete="off" id="etime" class="form-control input-small" value="10:00am"/>').appendTo(self.timeRange); 71 self.locationList = $('<select class="form-control input-sm"></select>').appendTo(self.locationCol); 72 $.getJSON(self.settings.apiServer + '/v1/' + self.settings.client + '/locations', { 73 only_with_external_rooms: 1, 74 only_with_patron_rooms: 1 75 }, function (json, textStatus) { 76 $('<option></option>').text('Please choose....').attr('value', '').appendTo(self.locationList); 77 for (var i = 0; i < json.length; i++) { 78 self.locations[json[i].id] = json[i]; 79 $('<option></option>').text(json[i].name).attr('value', json[i].id).appendTo(self.locationList); 80 } 81 if (json.length <= 1) { 82 self.singleBranch = true; 83 self.locationList.val(json[0].id).trigger('change'); 84 self.locationCol.hide(); 85 } 86 }); 87 self.roomList = $('<div class="amrp-rooms-list"></div>').appendTo(self.locationBottomRow); 88 var key = $('<div class="amrp-rooms-key">' + '<span><span class="amrp-rooms-key-i"></span>Available</span>' + '<span><span class="amrp-rooms-key-i" data-status="1"></span>Unavailable</span>' + '</div>').appendTo(self.locationBottomRow); 89 if (self.settings.useSetupBreakdown) { 90 $('<span class="amrp-key-message">Time is needed for library staff to set up and break down some rooms.</span>').prependTo(key); 91 $('<span><span class="amrp-rooms-key-i amrp-setup-breakdown"></span>Setup & Breakdown</span>').appendTo(key); 92 } 93 /*=============end book by location===========*/ 94 /*=============start book by resource===========*/
95 self.ressourceCol = $('<div></div>').addClass('col-md-4').prepend('<h2>Choose a resource</h2>').prependTo(topRow).hide(); 96 self.resourceList = $('<select class="form-control input-sm"></select>').appendTo(self.ressourceCol); 97 $.getJSON(self.settings.apiServer + '/v1/' + self.settings.client + '/resources', function (json, textStatus) { 98 $('<option></option>').text('Please choose....').attr('value', '').appendTo(self.resourceList); 99 $.each(json, function (index, val) { 100 self.resources[val.id] = val; 101 $('<option></option>').text(val.name).attr('value', val.id).appendTo(self.resourceList); 102 }); 103 }); 104 /*=============end book by resource===========*/ 105 $('<div class="amrp-room-summary-back link amrp-back-to-picker">Back to room picker</div>').appendTo(self.screenHeader); 106 self.reserveRoomSummary = $('<div class="amrp-room-summary"></div>').appendTo(self.screenHeader); 107 self.loginForm = $('<div class="amrp-login-form"></div>').appendTo(self.reserveScreen); 108 if(self.settings.pinlessAuth){ 109 if (self.settings.loginRequired) { 110 self._createField('login_card', 'text', 'Library card number', false, '<span data-loading-text="<i class=\'fa fa-circle-o-notch fa-spin\'></i>" class="btn btn-edit amrp-lookup input-group-addon">Login</span>', 'A library card is required to book a room.') 111 .appendTo(self.loginForm); 112 } 113 }else{ 114 self._createField('login_card', 'text', 'Library card number', false).addClass('amrp-card').appendTo(self.loginForm); 115 if (self.settings.loginRequired) { 116 var pin = self._createField('login_pin', 'password', 'PIN / Password', false, '<span data-loading-text="<i class=\'fa fa-circle-o-notch fa-spin\'></i>" class="btn btn-edit amrp-lookup input-group-addon">Login</span>', 'A library card is required to book a room.') 117 .appendTo(self.loginForm); 118 } else{ 119 var pin = self._createField('login_pin', 'password', 'PIN / Password', false, '<span data-loading-text="<i class=\'fa fa-circle-o-notch fa-spin\'></i>" class="btn btn-edit amrp-lookup input-group-addon">Look up details</span>', 'Enter your Library card number and PIN and we\'ll look up your details to fill in the next fields.').appendTo(self.loginForm); 120 } 121 } 122 $('<div class="amrp-spacer"><div class="events2-error-message"></div></div>').appendTo(self.reserveScreen); 123 self.detailsForm = $('<div></div>').appendTo(self.reserveScreen); 124 125 self._createField('contact_first_name', 'text', 'First name', true).appendTo(self.detailsForm); 126 self._createField('contact_last_name', 'text', 'Last name', true).appendTo(self.detailsForm); 127 // self._createField('zip_code', 'text', 'Zip code', true).appendTo(self.detailsForm); 128 self._createField('contact_email', 'text', 'Email', self.settings.emailRequired, false, 'We\'ll use the email address to confirm the booking and to notify if the room becomes unavailable.').appendTo(self.detailsForm); 129 self._createField('contact_tel', 'text', 'Phone', self.settings.phoneRequired, false).appendTo(self.detailsForm); 130 $('<input type="hidden" id="librarycard" value="">').appendTo(self.detailsForm); 131 self._createField('group_name', 'text', 'Group name', true, false, '(This is <b>not displayed</b> to the public)').appendTo(self.detailsForm); 132 self._createField('booking_title', 'text', 'Booking title', true, false, '(This <b>will be displayed</b> to the public)').appendTo(self.detailsForm); 133 if (self.settings.enableExpectedAttendees) { 134 self._createField('expected_attendees', 'number', 'Attendees', self.settings.expectedAttendeesRequired, false, 'Number of attendees expected.',0).appendTo(self.detailsForm); 135 } 136 if (self.settings.enablePatronNotes) { 137 self._createField('patron_notes', 'textarea', 'Notes', false, false, false).appendTo(self.detailsForm); 138 } 139 self.customQuestions = $('<div class="amrp-custom-questions"></div>').appendTo(self.detailsForm); 140 $('<div class="amrp-buttons">' + '<span class="amrp-required-label"><span class="required-field"></span> field required</span>' + '<button class="btn btn-edit amrp-back-to-picker">Cancel</button>' + '<button class="btn btn-success amrp-to-confirm-screen">Next</button>' + '</div>').appendTo(self.detailsForm); 141 $('<div class="row">' + '<div class="col-sm-3 amrp-booking-room-details"></div>' + '<div class="col-sm-6 amrp-booking-options"></div>' + '<div class="col-sm-3 amrp-booking-final-summary"></div>' + '</div>').appendTo(self.confirmScreen); 142 $('<div class="amrp-buttons">' + '<button class="btn btn-edit amrp-back-to-reserve">Back</button>' + '<button class="btn btn-success amrp-submit-booking" disabled="true">Reserve</button>' + '</div>').appendTo(self.confirmScreen); 143 144 if (self.settings.loginRequired) { 145 self.detailsForm.hide(); 146 } else { 147 self.loginForm.hide(); 148 149 if(self.settings.librarycardnumber) $('#librarycard', self.detailsForm).val(self.settings.librarycardnumber); 150 if(self.settings.patron.data && self.settings.patron.data.names[0]) $('#contact_first_name', self.detailsForm).val(self.settings.patron.data.names[0].first_name); 151 if(self.settings.patron.data && self.settings.patron.data.names[0]) $('#contact_last_name', self.detailsForm).val(self.settings.patron.data.names[0].last_name); 152 if(self.settings.patron.data && self.settings.patron.data.emails[0]) $('#contact_email', self.detailsForm).val(self.settings.patron.data.emails[0]); 153 if(self.settings.patron.data && self.settings.patron.data.phones[
1530]) $('#contact_tel', self.detailsForm).val(self.settings.patron.data.phones[0]); 154 } 155 }, 156 _reset: function () { 157 self.booking = {}; 158 $('.amrp-submit-booking').prop('disabled', 'true'); 159 $('input[type=text],input[type=password]', self.reserveScreen).val(""); 160 if($('option', self.locationList).length>2){ 161 self.locationList.val("").trigger('change'); 162 } 163 }, 164 _bindEvents: function () { 165 // $('a[data-toggle="tab"]', self.chooseTabs).on('shown.bs.tab', function (e) { 166 // var target = $(this).attr("data-type"); 167 // switch(target){ 168 // case 'resource': 169 // self.locationCol.hide(); 170 // self.ressourceCol.show(); 171 // break; 172 // case 'location': 173 // default: 174 // self.locationCol.show(); 175 // self.ressourceCol.hide(); 176 // break; 177 // } 178 // }); 179 self.confirmScreen.on('change', '.amrp-bookable-assets-list input, .amrp-bookable-assets-list select', function (event) { 180 event.preventDefault(); 181 self._updateBookedAssets(); 182 }).on('change', '.agreed', function (event) { 183 event.preventDefault(); 184 if ($(this).is(':checked')) { 185 $('.amrp-submit-booking').removeProp('disabled'); 186 } else { 187 $('.amrp-submit-booking').prop('disabled', 'true'); 188 } 189 }); 190 self.holder.on('click', '.amrp-submit-booking', function (event) { 191 event.preventDefault(); 192 // if(self.booking.layout.length) 193 var start = moment(self.booking.start_time); 194 var end = moment(self.booking.end_time); 195 var booking = JSON.parse(JSON.stringify(self.booking)); 196 booking.room_id = booking.room.id; 197 booking.layout_id = booking.layout.id; 198 booking.customQuestions = JSON.stringify(booking.customQuestions); 199 var room = JSON.parse(JSON.stringify(booking.room)); 200 if(self.settings.layoutRequired && room.layouts && room.layouts.length>0 && !self.booking.layout.id){ 201 alert('Please select a room layout'); 202 return; 203 } 204 205 delete booking.room; 206 delete booking.layout; 207 208 $.post('/reserve?action=submit', booking, function (json, textStatus) { 209 if(!json.ok){ 210 alert(json.message || 'Sorry there was a problem creating your booking, please try again.'); 211 return; 212 } 213 self.chooseScreen.hide(); 214 self.reserveScreen.hide(); 215 self.confirmScreen.hide(); 216 self.screenHeader.hide(); 217 self.screenThankyou.show().empty(); 218 219 var extra = ''; 220 if (room.restrictions.unmediated) { 221 $('<div class="events2-reg-thanks-stage">' + '<div class="events2-reg-thanks-title">Thank you!</div>' + '<div class="events2-reg-thanks-details">Your booking for the following room is now confirmed: ' + '<div class="events2-reg-thanks-evtitle">' + self.booking.room.title + '</div>' + '<div class="events2-reg-thanks-evlocation">' + self.locations[self.booking.room.location_id].name + '</div>' + '<div class="events2-reg-thanks-evdate">' + start.format('MMMM DD, YYYY') + '</div>' + '<div class="events2-reg-thanks-evtime">' + start.format('h:mma') + ' - ' + end.format('h:mma') + '</div>' + extra + '</div>' + '<div class="events2-reg-thanks-online">' + '<div class="events2-reg-thanks-online-title">View online</div>' + '<div class="events2-reg-thanks-message">You can view the status of your room bookings at:</div>' + '<div><a href="/myreservations">' + window.location.hostname + '/myreservations</a></div>' + '<div class="events2-reg-thanks-ref">This event registration reference: <b>' + json.reference + '<b></div>' + '</div>' + '</div>').appendTo(self.screenThankyou); 222 } else { 223 $('<div class="events2-reg-thanks-stage">' + '<div class="events2-reg-thanks-title">Thank you!</div>' + '<div class="events2-reg-thanks-details">We have received your request for a room booking for: ' + '<div class="events2-reg-thanks-evtitle">' + self.booking.room.title + '</div>' + '<div class="events2-reg-thanks-evlocation">' + self.locations[self.booking.room.location_id].name + '</div>' + '<div class="events2-reg-thanks-evdate">' + start.format('MMMM DD, YYYY') + '</div>' + '<div class="events2-reg-thanks-evtime">' + start.format('h:mma') + ' - ' + end.format('h:mma') + '</div>' + extra + '<div class="events2-reg-thanks-message">Once your reservation has been approved you will receive confirmation.</div>' + '</div>' + '<div class="events2-reg-thanks-online">' + '<div class="events2-reg-thanks-online-title">View online</div>' + '<div class="events2-reg-thanks-message">You can view the status of your room bookings at:</div>' + '<div><a href="/myreservations">' + window.location.hostname + '/myreservations</a></div>' + '<div class="events2-reg-thanks-ref">This event registration reference: <b>' + json.reference + '<b></div>' + '</div>' + '</div>').appendTo(self.screenThankyou); 224 } 225 $('<div class="amrp-room-summary-back link amrp-back-to-picker">Make another reservation</div>').appendTo(self.screenThankyou); 226 self._reset(); 227 }, 'json'); 228 }).on('click', '.amrp-back-to-picker', function (event) { 229 event.preventDefault(); 230 self.chooseScreen.show(); 231 self.reserveScreen.hide(); 232 self.confirmScreen.hide(); 233 self.screenHeader.hide(); 234 self.screenThankyou.hide(); 235 if (self.settings.loginRequired) { 236 self.loginForm.show(); 237 self.detailsForm.hide(); 238 } 239 }).on('click', '.amrp-back-to-reserve', function (event) { 240 event.preventDefault(); 241 self.chooseScreen.hide(); 242 self.reserveScreen.show(); 243 self.confirmScreen.hide(); 244 self.screenHeader.show(); 245 }).on('click', '.amrp-to-confirm-screen', function (event) { 246 event.preventDefault(); 247 if (!self.booking.contact) self.booking.contact = {}; 248 self.booking.contact.first_name = $('#contact_first_name', self.holder).val(); 249 self.booking.contact.last_name = $('#contact_last_name', self.holder).val(); 250 self.booking.contact.phone = $('#contact_tel', self.holder).val(); 251 self.booking.contact.email = $('#contact_email', self.holder).val(); 252 self.booking.contact.librarycard = $('#librarycard', self.holder).val(); 253 self.booking.contact.group_name = $('#group_name', self.holder).val(); 254 self.booking.contact.booking_title = $('#booking_title', self.holder).val(); 255 self.booking.expected_attendees = parseInt($('#expected_attendees', self.holder).val()||0, 10); 256 self.booking.patron_notes = $('#patron_notes', self.holder).val(); 257 258 // CH#1957 - CK - Fix for when max is 0 to ignore the message. 259 // 2-26-18 - Fix for wrong room object being used in V1 as compared to other pickers. 260 var maxCapacity = Math.max(parseInt(self.booking.room.capacity_standing, 10), parseInt(self.booking.room.capacity_chairs, 10), parseInt(self.booking.room.capacity_tables, 10)); 261 if (self.settings.enforceMaxAttendees && (self.booking.expected_attendees > maxCapacity) && maxCapacity > 0) { 262 $('.events2-error-message', self.holder).text('Expected attendees exceeds capacity').fadeIn().delay(3000).fadeOut(); 263 $('#expected_attendees', self.holder).addClass('amrp-missing-field'); 264 return; 265 } 266 self.booking.customQuestions = {}; 267 var reemail = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 268 var rephone = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im; 269 if (!self._isFormClean(self.reserveScreen)) { 270 $('.events2-error-message', self.holder).text('Please enter information for all required fields').fadeIn().delay(3000).fadeOut(); 271 return; 272 } 273 if (!$('#contact_email', self.holder).prop('disabled') && self.booking.contact.email.length > 0 && !reemail.test(self.booking.contact.email)) { 274 $('.events2-error-message', self.holder).text('Please enter a valid email address').fadeIn().delay(3000).fadeOut(); 275 $('#contact_email', self.holder).addClass('amrp-missing-field'); 276 return; 277 } 278 if (!$('#contact_tel', self.holder).prop('disabled') && self.booking.contact.phone.length > 0 && !rephone.test(self.booking.contact.phone)) { 279 $('.events2-error-message', self.holder).text('Please enter a valid phone number').fadeIn().delay(3000).fadeOut(); 280 $('#contact_tel', self.holder).addClass('amrp-missing-field'); 281 return; 282 } 283 if (self.booking.room.custom_fields && self.booking.room.custom_fields.fields && self.booking.room.custom_fields.fields.length > 0) { 284 for (var i = self.booking.room.custom_fields.fields.length - 1; i >= 0; i--) { 285 var field = self.booking.room.custom_fields.fields[i]; 286 var val = false;
287 switch (field.type) { 288 case 'checkbox': 289 val = $('#' + field.name, self.customQuestions).is(':checked'); 290 break; 291 default: 292 val = $('#' + field.name, self.customQuestions).val(); 293 break; 294 } 295 switch (field.validate) { 296 case 'custom': 297 var flags = field.regex.replace(/.*\/([gimy]*)$/, '$1'); 298 var pattern = field.regex.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1'); 299 var regex = new RegExp(pattern, flags); 300 if (val.length > 0 && !regex.test(val)) { 301 $('.events2-error-message', self.holder).text('The information entered is not valid').fadeIn().delay(3000).fadeOut(); 302 $('#' + field.name, self.holder).addClass('amrp-missing-field'); 303 return; 304 } 305 break; 306 case 'email': 307 if (val.length > 0 && !reemail.test(val)) { 308 $('.events2-error-message', self.holder).text('Please enter a valid email address').fadeIn().delay(3000).fadeOut(); 309 $('#' + field.name, self.holder).addClass('amrp-missing-field'); 310 return; 311 } 312 break; 313 case 'phone': 314 if (val.length > 0 && !rephone.test(val)) { 315 $('.events2-error-message', self.holder).text('Please enter a valid phone number').fadeIn().delay(3000).fadeOut(); 316 $('#' + field.name, self.holder).addClass('amrp-missing-field'); 317 return; 318 } 319 break; 320 } 321 if (val) self.booking.customQuestions[field.name] = val; 322 } 323 } 324 self._confirmScreen(); 325 }).on('click', '.amrp-lookup', function (event) { 326 event.preventDefault(); 327 var b = $(this).button('loading'); 328 329 // CH#1942 - Trim the card/pin fields to prevent blanks. 330 var card = $.trim($('#login_card', self.holder).val()); 331 var loginData = {u:card, 'type':'reserve'}; 332 if(!self.settings.pinlessAuth){ 333 loginData.p = $.trim($('#login_pin', self.holder).val()); 334 } 335 $.getJSON(self.settings.apiServer + '/v1/' + self.settings.client + '/patron', loginData, function (json, textStatus) { 336 if (json.result == 'ok') { 337 if(!self.settings.pinlessAuth){ 338 if (json.data.names.length > 0) { 339 $('#contact_first_name', self.holder).val(json.data.names[0].first_name); 340 $('#contact_last_name', self.holder).val(json.data.names[0].last_name); 341 if(self.settings.roomsPatronDetailsReadonly){ 342 $('#contact_first_name', self.holder).prop('disabled', true); 343 $('#contact_last_name', self.holder).prop('disabled', true); 344 } 345 } 346 if (json.data.phones.length > 0) { 347 $('#contact_tel', self.holder).val(json.data.phones[0]); 348 if(self.settings.roomsPatronDetailsReadonly){ 349 $('#contact_tel', self.holder).prop('disabled', true); 350 } 351 } 352 if (json.data.emails.length > 0) { 353 $('#contact_email', self.holder).val(json.data.emails[0]); 354 if(self.settings.roomsPatronDetailsReadonly){ 355 $('#contact_email', self.holder).prop('disabled', true); 356 } } 357 } 358 if (json.data.barcodes.length > 0) { 359 $('#librarycard', self.holder).val(json.data.barcodes[0]); 360 } 361 if (self.settings.loginRequired) { 362 self.loginForm.hide(); 363 self.detailsForm.show(); 364 } 365 } else { 366 var msg = self.settings.pinlessAuth?'Sorry, card number not found':'Sorry, pin or card number not found'; 367 if( json.message && json.message.length>0 ){ 368 msg = json.message; 369 } 370 $('.events2-error-message', self.holder).text(json.message||msg).fadeIn().delay(3000).fadeOut(); 371 } 372 b.button('reset'); 373 }).error(function () { 374 $('.events2-error-message', self.holder).text('Sorry, there was a problem making the request').fadeIn().delay(3000).fadeOut(); 375 b.button('reset'); 376 }); 377 }); 378 self.reserveScreen.on('focus', '.amrp-missing-field', function (event) { 379 $(this).removeClass('amrp-missing-field'); 380 }); 381 self.datePicker = $('.amrp-datepicker', self.holder); 382 self.startTime.timepicker({ 383 minuteStep: 5, 384 showInputs: false 385 }).on('changeTime.timepicker', function (event) { 386 if (!self.moving) self._changed(); 387 }); 388 self.endTime.timepicker({ 389 minuteStep: 5, 390 showInputs: false 391 }).on('changeTime.timepicker', function (event) { 392 if (!self.moving) self._changed(); 393 }); 394 self.datePicker.datetimepicker({ 395 icons: { 396 previous: 'fa fa-chevron-left', 397 next: 'fa fa-chevron-right' 398 }, 399 minDate: moment().format('MM/DD/YYYY'), 400 defaultDate: moment().format('MM/DD/YYYY'), 401 format: 'LL' 402 }).on('dp.change', function (event) { 403 self._update(); 404 }); 405 self.locationList.on('change', function (event) { 406 event.preventDefault(); 407 self.openingHours = false;
408 self._update(); 409 }); 410 self.resourceList.on('change', function (event) { 411 event.preventDefault(); 412 self._changed(); 413 }); 414 interact('.amrp-booking', { 415 context: self.roomList[0] 416 }).draggable({ 417 restrict: { 418 restriction: "parent", 419 endOnly: false, 420 elementRect: { 421 top: 0, 422 left: 0, 423 bottom: 1, 424 right: 1 425 } 426 }, 427 onstart: function (event) { 428 self.moving = true; 429 }, 430 onmove: function (event) { 431 var $target = $(event.target); 432 var start = (parseFloat($target.css('left')) || 0) 433 var x = start + event.dx; 434 $('.amrp-booking', self.roomList).css({ 435 left: x + 'px' 436 }); 437 self._updateBookingTime(); 438 self._updateButtons(); 439 }, 440 onend: function (event) { 441 self.moving = false; 442 self._updateCurrent(event); 443 } 444 }); 445 self.roomList.on('click', '.amrp-ava-btn', function (event) { 446 event.preventDefault(); 447 self.booking.room = $(this).closest('.amrp-room').data('room'); 448 self.booking.contact = {}; 449 self.booking.layout = {}; 450 self.booking.assets = []; 451 self._reserveScreen(); 452 }).on('mouseenter', '.amrp-room-title img', function (event) { 453 event.preventDefault(); 454 var room = $(this).closest('.amrp-room').data('room'); 455 $(this).qtip({ 456 overwrite: false, // Don't overwrite tooltips already bound 457 content: { 458 text: function (event, api) { 459 var $data = $('<div></div>'); 460 var $top = $('<div class="amrp-room-popup-top"></div>').appendTo($data); 461 var $row = $('<div class="row"></div>').appendTo($data); 462 var $left = $('<div class="col-sm-7"></div>').appendTo($row); 463 var $right = $('<div class="col-sm-5"></div>').appendTo($row); 464 var min = parseInt(room.restrictions.minimum_booking_time, 10); 465 var max = parseInt(room.restrictions.maximum_booking_time, 10); 466 var near = parseInt(room.restrictions.nearest_booking_days, 10); 467 var far = parseInt(room.restrictions.furthest_booking_days, 10); 468 469 if (room.image && room.image.length > 0) { 470 $('<img/>').attr('src', '//' + self.settings.client + '.libnet.info/images/roombooking/' + self.settings.client + '/' + room.image).attr('alt', room.title).appendTo(img); 471 } 472 473 $('<h3></h3>').text(room.title).appendTo($top); 474 if (max > 0) { 475 $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-info">'+ self.settings.roomsMaxBookingMessage.replace('{{amount}}', self._formatMinsAsString(max)) +'</span></div>').appendTo($top); 476 } 477 if (min > 0) { 478 $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-info">'+ self.settings.roomsMinBookingMessage.replace('{{amount}}', self._formatMinsAsString(min)) +'</span></div>').appendTo($top); 479 } 480 if (near > 0) { 481 $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-info">' + self.settings.roomsNearBookingMessage.replace('{{amount}}', near) + '</span></div>').appendTo($top); 482 } 483 if (far > -1) { 484 $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-info">' + self.settings.roomsFarBookingMessage.replace('{{amount}}', far) + '</span></div>').appendTo($top); 485 } 486 if (room.length || room.width || room.area) { 487 $('<div class="amrp-rrom-popup-title">Room size</div>').appendTo($left); 488 if (room.length) $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-label">Length</span><span class="amrp-room-popup-value">' + room.length + ' ft</span></div>').appendTo($left); 489 if (room.width) $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-label">Width</span><span class="amrp-room-popup-value">' + room.width + ' ft</span></div>').appendTo($left); 490 if (room.area) $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-label">Area</span><span class="amrp-room-popup-value">' + room.area + ' sq ft</span></div>').appendTo($left); 491 } 492 // #4762 - CK 493 var maxCap = Math.max(room.capacity_standing, room.capacity_chairs, room.capacity_tables, 0); 494 $('<div class="events2-room-popup-title">
494Room capacity</div>').appendTo($left); 495 $('<div class="events2-room-popup-item"><span class="events2-room-popup-label">Max Capacity</span><span class="events2-room-popup-value">' + maxCap + '</span></div>').appendTo($left); 496 497 var $bottom = $('<div class="amrp-room-popup-bottom"></div>').appendTo($data); 498 if (room.description) $('<div class="amrp-room-popup-description"><div class="amrp-rrom-popup-title">Room description</div>' + room.description + '</div>').appendTo($bottom); 499 if (room.assets && room.assets.length > 0) { 500 $('<div class="amrp-rrom-popup-title">Room features</div>').appendTo($bottom); 501 $.each(room.assets, function (index, asset) { 502 var a = $('<div class="amrp-room-popup-asset"></div>').appendTo($bottom); 503 $('<span class="amrp-room-popup-asset-name">' + asset.name + '</span>').appendTo(a); 504 if (asset.qty > 1) { 505 $('<span class="amrp-room-popup-asset-qty">' + asset.qty + '</span>').appendTo(a); 506 } 507 if (asset.description) { 508 $('<span class="amrp-room-popup-asset-description"> (' + asset.description + ') </span>').appendTo(a); 509 } 510 }); 511 } 512 if (room.layouts && room.layouts.length > 0) { 513 var layoutsList = $('<div class="amrp-room-popup-bottom"></div>').appendTo($data); 514 $.each(room.layouts, function (index, layout) { 515 layoutsList.append(self._getLayoutDetailView(layout)); 516 layoutsList.append('<br>'); 517 }); 518 } else if (self.settings.useSetupBreakdown) { 519 if (room.setup_time && parseInt(room.setup_time) > 0) $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-label">Setup time</span><span class="amrp-room-popup-value">' + room.setup_time + ' minutes</span></div>').appendTo($data); 520 if (room.breakdown_time && parseInt(room.breakdown_time) > 0) $('<div class="amrp-room-popup-item"><span class="amrp-room-popup-label">Breakdown time</span><span class="amrp-room-popup-value">' + room.breakdown_time + ' minutes</span></div>').appendTo($data); 521 } 522 return $data; 523 } 524 }, 525 position: { 526 my: 'left top', 527 at: 'top right' 528 }, 529 style: { 530 classes: 'qtip-shadow qtip-light qtip-rounded amrp-room-popup' 531 }, 532 show: { 533 delay: 500, 534 ready: true // Show immediately - important! 535 }, 536 hide: { 537 delay: 200, 538 fixed: true, // <--- add this 539 effect: function () { 540 $(this).fadeOut(250); 541 } 542 }, 543 }); 544 }); 545 }, 546 _updateBookingTime: function () { 547 var elementTime = self._getElTime($('.amrp-booking', self.roomList).first()); 548 var start = moment(elementTime.from); 549 var end = moment(elementTime.to); 550 self.booking.start_time = start.format('YYYY-MM-DD HH:mm:ss'); 551 self.booking.end_time = end.format('YYYY-MM-DD HH:mm:ss'); 552 self.startTime.timepicker('setTime', start.format('h:mma')); 553 self.endTime.timepicker('setTime', end.format('h:mma')); 554 return true; 555 }, 556 getSecondsFromMidnight: function (time, date) { 557 return moment(date+' '+time, 'YYYY-MM-DD h:mma').diff(moment(date, 'YYYY-MM-DD').startOf('day'), 'seconds'); 558 }, 559 _updateCurrent: function (event) { 560 var $target = $(event.target); 561 var elementTime = self._getElTime($(event.target)); 562 self.booking.start_time = elementTime.from.format('YYYY-MM-DD HH:mm:ss'); 563 self.booking.end_time = elementTime.to.format('YYYY-MM-DD HH:mm:ss'); 564 self._renderList(); 565 }, 566 _update: function () { 567 var loc = self.locationList.val(); 568 if (loc == '') { 569 self.locationBottomRow.hide(); 570 } else { 571 var dateString = self.datePicker.data("DateTimePicker").date().clone().startOf('day').format('YYYY-MM-DD'); 572 $.getJSON(self.settings.apiServer + '/v2/' + self.settings.client + '/rooms/' + loc, { 573 date: dateString, 574 external_only: 1, 575 classtype: 1 576 }, function (json, textStatus) { 577 self.rooms = json; 578 if (self.settings.useSetupBreakdown) { 579 $.each(self.rooms, function (index, room) { 580 $.each(room.bookings, function (index, booking) { 581 if (room.setup_time) { 582 booking.start_time = moment(booking.start_time).add(room.setup_time * -1, 'minutes').format('YYYY-MM-DD HH:mm:ss'); 583 } 584 if (room.breakdown_time) { 585 booking.end_time = moment(booking.end_time).add(room.breakdown_time, 'minutes').format('YYYY-MM-DD HH:mm:ss'); 586 } 587 }); 588 }); 589 } 590 $.getJSON(self.settings.apiServer + '/v1/' + self.settings.client + '/opening-hours/' + dateString + '/1', function (openingTimes, textStatus) { 591 self.openingHours = openingTimes[loc][dateString]; 592 var d = moment(dateString).startOf('day'); 593 self.openingHours.raw_open_time = d.clone().add(moment(self.openingHours.open, 'h:mma').diff(moment().startOf('day'), 'seconds'), 'seconds').format('YYYY-MM-DD HH:mm:ss'); 594 self.openingHours.raw_close_time = d.clone().add(moment(self.openingHours.close, 'h:mma').diff(moment().startOf('day'), 'seconds'), 'seconds').format('YYYY-MM-DD HH:mm:ss'); 595 if (self.openingHours.raw_open_time == self.openingHours.raw_close_time) { 596 self.locationBottomRow.hide(); 597 self.locationClosed.show(); 598 } else { 599 self.locationBottomRow.show(); 600 self.locationClosed.hide(); 601 self._changed(); 602 self._renderList(); 603 } 604 }); 605 }); 606 } 607 }, 608 _changed: function () { 609 var d = self.datePicker.data("DateTimePicker").date().clone().startOf('day'); 610 var s = self.getSecondsFromMidnight(self.startTime.val(), d.format('YYYY-MM-DD')); 611 var e = self.getSecondsFromMidnight(self.endTime.val(), d.format('YYYY-MM-DD')); 612 var new_start_time = d.clone().add(Math.min(s, e), 'seconds'); 613 var new_end_time = d.clone().add(Math.max(s, e), 'seconds'); 614 var badTime = e <= s; 615 616 if (badTime) { 617 self.moving = true; 618 self.endTime.timepicker('setTime', d.clone().add(s, 'seconds').add(1, 'hour').format('h:mma')); 619 e = self.getSecondsFromMidnight(self.endTime.val(), d.format('YYYY-MM-DD')); 620 self.moving = false;
621 } 622 623 self.booking.start_time = d.clone().add(Math.min(s, e), 'seconds').format('YYYY-MM-DD HH:mm:ss'); 624 self.booking.end_time = d.clone().add(Math.max(s, e), 'seconds').format('YYYY-MM-DD HH:mm:ss'); 625 self._renderList(); 626 }, 627 _renderList: function () { 628 self.roomList.empty(); 629 var markers = $('<div class="amrp-roomlist-markers"></div>').appendTo(self.roomList); 630 var w = markers.width() - 22; 631 for (var i = 3; i < 24; i += 3) { 632 var left = ((w / 24) * i); 633 $('<span class="l"></span>').css('left', left + 'px').appendTo(markers); 634 left -= 18; 635 $('<span class="t">' + moment(i + ':00', ["HH:mm"]).format("h:mma") + '</span>').css('left', left + 'px').appendTo(markers); 636 } 637 $.each(self.rooms, function (index, val) { 638 var b = val.bookings; 639 // CH#2461 - This fix below was already here but applies to this ticket. 640 if(val.restrictions.viewable===false) return; 641 var room = $('<div class="amrp-room"></div>').data('bookings', b).data('room', val).attr('data-roomid', val.id).appendTo(self.roomList); 642 var title = $('<div class="amrp-room-title"></div>').text(val.title).appendTo(room); 643 if (val.image.length > 0) { 644 $('<img/>').attr('src', '//' + self.settings.client + '.libnet.info/images/roombooking/' + self.settings.client + '/' + val.image).attr('alt', val.title).prependTo(title); 645 } 646 var timeline = $('<div class="amrp-room-timeline"><div class="amrp-booking"><div class="amrp-setup"></div> <div class="amrp-breakdown"></div></div></div>').appendTo(room); 647 $('<div class="amrp-room-status"><button class="btn btn-info amrp-ava-btn">Select</button><div class="amrp-reason"></div></div>').appendTo(room); 648 $.each(b, function (index, booking) { 649 $('<div class="amrp-ex-booking" data-status="1"> </div>').data('booking', booking).attr('data-booking-id', booking.id).appendTo(timeline); 650 }); 651 if (val.sub_rooms && val.sub_rooms.length > 0) { 652 room.wrap('<div class="amrp-parent-room"></div>').attr('data-roomid', val.id); 653 room.parent().append('<div class="amrp-sub-room"></div>'); 654 } 655 var opt; 656 if(self.singleBranch){ 657 opt = $('<div class="amrp-room-opening-hours">Library hours</div>').appendTo(timeline); 658 }else{ 659 opt = $('<div class="amrp-room-opening-hours">Branch hours</div>').appendTo(timeline); 660 } 661 self._updateEl({ 662 start_time: self.openingHours.raw_open_time, 663 end_time: self.openingHours.raw_close_time 664 }, opt); 665 }); 666 $.each(self.rooms, function (index, val) { 667 $.each(val.childRooms, function (cIndex, child) { 668 $.each(val.bookings, function (bIndex, booking) { 669 self._addBooking(booking, child); 670 }); 671 }); 672 $.each(val.parentRooms, function (pIndex, parent) { 673 $.each(val.bookings, function (bIndex, booking) { 674 self._addBooking(booking, parent); 675 }); 676 }); 677 }); 678 $('>.amrp-parent-room', self.roomList).each(function (index, el) { 679 var subs = $('.amrp-sub-room', el); 680 var r = $('>.amrp-room', el).first().data('room'); 681 $.each(r.sub_rooms, function (index, val) { 682 $('>.amrp-room[data-roomid=' + val + ']', self.roomList).prependTo(subs); 683 }); 684 }); 685 $('.amrp-booking', self.roomList).each(function (index, el) { 686 self._updateEl(self.booking, $(el)); 687 }); 688 self._updateExBookings(self.roomList); 689 self._updateButtons(); 690 }, 691 _addBooking: function (booking, room_id) { 692 var timeline = $('[data-roomid=' + room_id + ']').find('.amrp-room-timeline').first(); 693 if ($('[data-booking-id=' + booking.id + ']', timeline).length === 0 && parseInt(booking.status, 10) !== 3 && parseInt(booking.status, 10) !== 2) { 694 $('<div class="amrp-ex-booking" data-status="' + booking.status + '"> </div>').data('booking', booking).attr('data-booking-id', booking.id).appendTo(timeline); 695 } 696 }, 697 _formatMinsAsString: function (mins) { 698 var min = parseInt(mins, 10); 699 if (min < 60) { 700 return mins + " minutes"; 701 } 702 var hours = Math.floor(min / 60); 703 var minutes = min % 60; 704 if (minutes > 0) { 705 if (hours > 1) { 706 return hours + ' hours ' + minutes + ' minutes'; 707 } else { 708 return hours + ' hour ' + minutes + ' minutes'; 709 } 710 } else { 711 if (hours > 1) { 712 return hours + ' hours'; 713 } else { 714 return hours + ' hour'; 715 } 716 } 717 }, 718 _updateButtons: function () { 719 $('.amrp-ava-btn', self.roomList).each(function (index, el) { 720 var reason = $('.amrp-reason', $(el).closest('.amrp-room')).text('').hide(); 721 var elementTime = self._getElTime($('.amrp-booking', self.roomList).first()); 722 var b = $(el).closest('.amrp-room').find('.amrp-ex-booking'); 723 var bookings = []; 724 for (var i = 0; i < b.length; i++) { 725 bookings.push($(b[i]).data('booking')); 726 } 727 var roomData = $(el).closest('.amrp-room').data('room'); 728 if (!roomData.restrictions.bookable) { 729 $(el).text('Please call').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 730 reason.text(self.settings.roomsNotBookableMessage.replace('{{branch_number}}', self.locations[roomData.location_id].tel)).show(); 731 return; 732 } 733 var min = parseInt(roomData.restrictions.minimum_booking_time, 10) || 0; 734 var max = parseInt(roomData.restrictions.maximum_booking_time, 10) || 0; 735 var near = parseInt(roomData.restrictions.nearest_booking_days, 10) || 0; 736 var far = parseInt(roomData.restrictions.furthest_booking_days, 10) || -1; 737 738 var day_start_buffer = parseInt(roomData.restrictions.day_start_buffer, 10) || 0; 739 var day_end_buffer = parseInt(roomData.restrictions.day_end_buffer, 10) || 0; 740 741 var open = moment(self.openingHours.raw_open_time); 742 var close = moment(self.openingHours.raw_close_time); 743 744 var roomOpens = open.clone().add(day_start_buffer, 'minutes'); 745 var roomCloses = close.clone().add(day_end_buffer * -1, 'minutes'); 746 747 if (self.settings.useSetupBreakdown) { 748 roomOpens.add(roomData.setup_time * -1, 'minutes'); 749 roomCloses.add(roomData.breakdown_time, 'minutes'); 750 751 elementTime.to.add(roomData.breakdown_time, 'minutes'); 752 elementTime.from.add(roomData.setup_time * -1, 'minutes'); 753 } 754 if (elementTime.from < roomOpens || elementTime.to > roomCloses) { 755 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 756 reason.text('The room is closed at this time.').show(); 757 return; 758 } 759 760 761 if (elementTime.from < open || elementTime.to > close) { 762 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 763 return; 764 } 765 var duration = moment.duration(elementTime.to.diff(elementTime.from)).asMinutes(); 766 if (max > 0 && duration > max) { 767 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 768 769 reason.text(self.settings.roomsMaxBookingMessage.replace('{{branch_number}}', self.locations[roomData.location_id].tel).replace('{{amount}}', self._formatMinsAsString(max))).show(); 770 return; 771 } 772 if (min > 0 && duration < min) { 773 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 774 reason.text(self.settings.roomsMinBookingMessage.replace('{{branch_number}}', self.locations[roomData.location_id].tel).replace('{{amount}}', self._formatMinsAsString(min))).show(); 775 return; 776 } 777 var when = Math.round(moment.duration(elementTime.to.diff(moment())).asDays()); 778 if (near > 0 && when < near) { 779 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 780 reason.text(self.settings.roomsNearBookingMessage.replace('{{branch_number}}', self.locations[roomData.location_id].tel).replace('{{amount}}', near)).show(); 781 return; 782 } 783 if (far > -1 && when > far) { 784 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 785 reason.text(self.settings.roomsFarBookingMessage.replace('{{branch_number}}', self.locations[roomData.location_id].tel).replace('{{amount}}', far)).show(); 786 return; 787 } 788 if (moment(self.booking.start_time).isBefore(moment())) { 789 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 790 return; 791 } 792 $(el).text($(el).closest('.amrp-room').hasClass('amrp-room-selected') ? 'Chosen' : 'Select').removeClass('btn-info btn-edit').addClass($(el).closest('.amrp-room').hasClass('amrp-room-selected') ? 'btn-primary' : 'btn-info').removeProp('disabled'); 793 794 $.each(bookings, function (index, val) { 795 var lStart = moment(val.start_time); 796 var lEnd = moment(val.end_time); 797 if (lStart < elementTime.to && lEnd > elementTime.from) { 798 $(el).text('Unavailable').removeClass('btn-info btn-edit').addClass('btn-edit').prop('disabled', true); 799 } 800 }); 801 }); 802 }, 803 _getElTime: function (el) { 804 var mmtMidnight = moment(self.booking.start_time).clone().startOf('day'); 805 var width = $('.amrp-room-timeline', self.roomList).width(); 806 var roomData = $(el).closest('.amrp-room').data('room'); 807 var x = (parseFloat(el.css('left')) || 0); 808 var w = el.width(); 809 var startMin = Math.floor(x / (width / 1440) / 5) * 5; 810 var endMin = startMin + (Math.ceil(w / (width / 1440) / 5) * 5); 811 var start = mmtMidnight.clone().add(startMin, 'minutes'); 812 var end = mmtMidnight.clone().add(endMin, 'minutes'); 813 return { 814 from: start, 815 to: end 816 }; 817 }, 818 _updateEl: function (time, el) { 819 if (!time) return; 820 var from = moment(time.start_time); 821 var to = moment(time.end_time); 822 var roomData = $(el).closest('.amrp-room').data('room'); 823 var mmtMidnight = from.clone().startOf('day'); 824 var start = from.clone().diff(mmtMidnight, 'minutes'); 825 var end = to.clone().diff(mmtMidnight, 'minutes'); 826 var width = $(el).parent().width(); 827 var x = Math.ceil(start * (width / 1440)); 828 var w = Math.floor(end * (width / 1440)) - x; 829 if (self.settings.useSetupBreakdown && roomData && roomData.breakdown_time) { 830 var bw = roomData.breakdown_time * (width / 1440); 831 $('.amrp-breakdown', el).css({ 832 width: bw + 'px', 833 right: (bw * -1) + 'px' 834 }); 835 } 836 if (self.settings.useSetupBreakdown && roomData && roomData.setup_time) { 837 var sw = roomData.setup_time * (width / 1440); 838 $('.amrp-setup', el).css({ 839 width: sw + 'px', 840 left: (sw * -1) + 'px' 841 }); 842 } 843 el.css({ 844 left: x + 'px' 845 });
846 el.width(w + 'px'); 847 }, 848 _updateExBookings: function (list) { 849 $('.amrp-ex-booking', list).each(function (index, el) { 850 var booking = $(this).data('booking'); 851 self._updateEl(booking, $(el)); 852 }); 853 }, 854 _reserveScreen: function () { 855 var customQuestions = self.customQuestions.empty(); 856 var summary = self.reserveRoomSummary.empty(); 857 $('<div class="amrp-room-name"></div>').html('<i class="am-locations"></i><b>' + self.booking.room.title + '</b>, ' + self.locations[self.booking.room.location_id].name).appendTo(summary); 858 var start = moment(self.booking.start_time); 859 var end = moment(self.booking.end_time); 860 $('<div class="amrp-room-time"></div>').html('<b>' + start.format('h:mma') + ' - ' + end.format('h:mma') + '</b> ' + start.format('MMMM DD, YYYY')).appendTo(summary); 861 if (self.booking.room.custom_fields && self.booking.room.custom_fields.fields && self.booking.room.custom_fields.fields.length > 0) { 862 $.each(self.booking.room.custom_fields.fields, function (index, val) { 863 var field = self._createField(val.name, val.type, val.title, val.required, false, val.helpText).data('fieldSettings', val).addClass('amrp-custom-field').appendTo(customQuestions); 864 if (val.type === 'select') { 865 var select = $('select', field); 866 if (!val.required) { 867 $('<option>Please choose...</option>').appendTo(select); 868 } 869 var options = val.options.trim().split(/\r?\n/); 870 for (var i = 0; i < options.length; i++) { 871 $('<option>' + options[i] + '</option>').appendTo(select); 872 } 873 } 874 }); 875 } 876 // 877 self.chooseScreen.hide(); 878 self.confirmScreen.hide(); 879 self.reserveScreen.show(); 880 self.screenHeader.show(); 881 }, 882 _confirmScreen: function () { 883 self.confirmScreen.show(); 884 self.screenHeader.show(); 885 self.chooseScreen.hide(); 886 self.reserveScreen.hide(); 887 self._updateFinalSummary(); 888 var roomDetails = $('.amrp-booking-room-details', self.confirmScreen).empty(); 889 var bookingOptions = $('.amrp-booking-options', self.confirmScreen).empty(); 890 var room = self.booking.room; 891 if (room.image && room.image.length > 0) { 892 $('<img/>').attr('src', '//' + self.settings.client + '.libnet.info/images/roombooking/' + self.settings.client + '/' + room.image).attr('alt', room.title).appendTo(roomDetails); 893 } 894 $('<div class="amrp-booking-room-desc"></div>').html(room.description).appendTo(roomDetails); 895 if (room.assets && room.assets.length > 0) { 896 var included = $('<div class="amrp-booking-room-included"><b>What\'s included?<b><br></div>').appendTo(roomDetails); 897 var includedList = $('<ul><ul>').appendTo(included); 898 $.each(room.assets, function (index, asset) { 899 var a = $('<li></li>').appendTo(includedList); 900 if (asset.qty > 1) { 901 $('<span class="amrp-booking-room-asset-qty">' + asset.qty + ' </span>').appendTo(a); 902 } 903 $('<span class="amrp-booking-room-asset-name">' + asset.name + '</span>').appendTo(a); 904 if (asset.description) { 905 $('<span class="amrp-booking-room-asset-description"> (' + asset.description + ') </span>').appendTo(a); 906 } 907 }); 908 } 909 var bookingPreview = $('<div class="amrp-booking-preview"></div>').appendTo(bookingOptions); 910 var markers = $('<div class="amrp-roomlist-markers"></div>').appendTo(bookingPreview); 911 var w = markers.width(); 912 for (var i = 3; i < 24; i += 3) { 913 var left = ((w / 24) * i); 914 $('<span class="l"></span>').css('left', left + 'px').appendTo(markers); 915 left -= 18; 916 $('<span class="t">' + moment(i + ':00', ["HH:mm"]).format("h:mma") + '</span>').css('left', left + 'px').appendTo(markers); 917 } 918 var b = room.bookings; 919 var roomRow = $('<div class="amrp-room"></div>').data('bookings', b).data('room', room).attr('data-roomid', room.id).appendTo(bookingPreview); 920 var timeline = $('<div class="amrp-room-timeline"><div class="amrp-booking"><div class="amrp-setup"></div> <div class="amrp-breakdown"></div></div></div>').appendTo(roomRow); 921 $.each(b, function (index, booking) { 922 $('<div class="amrp-ex-booking" data-status="1"> </div>').data('booking', booking).attr('data-booking-id', booking.id).appendTo(timeline); 923 }); 924 self._updateEl(self.booking, $('.amrp-booking', bookingPreview)); 925 self._updateExBookings(bookingPreview); 926 // self._updateButtons(); 927 928 if (room.layouts && room.layouts.length > 0) { 929 var layoutSelect = self._createField('layout_id', 'select', 'Layout', false).appendTo(bookingOptions).find('select'); 930 $('<option value="">Please choose a layout</option>').appendTo(layoutSelect); 931 $.each(room.layouts, function (index, layout) { 932 $('<option>' + layout.name + '</option>').val(layout.id).data('details', layout).appendTo(layoutSelect); 933 });
934 var layoutDetail = $('<div></div>').appendTo(bookingOptions); 935 layoutSelect.on('change', function (event) { 936 event.preventDefault(); 937 layoutDetail.empty(); 938 self.booking.layout = $(':selected', this).data('details'); 939 self._updateFinalSummary(); 940 if (self.booking.layout)layoutDetail.append(self._getLayoutDetailView(self.booking.layout)); 941 }); 942 } 943 944 var assets = $('<div class="amrp-booking-final-summary-assets"></div>').appendTo(bookingOptions); 945 $.getJSON(self.settings.apiServer + '/v2/' + self.settings.client + '/rooms/assets/' + room.location_id + '/' + room.id+'?start='+self.booking.start_time+'&end='+self.booking.end_time, function (json, textStatus) { 946 self.assets = []; 947 if (json.length > 0) { 948 $('<div class="amrp-booking-final-summary-subheading">Bookable resources</div>').appendTo(assets); 949 var assetList = $('<ul class="amrp-bookable-assets-list"></ul>').appendTo(assets); 950 $.each(json, function (index, val) { 951 if(parseInt(val.quantity)>0){ 952 self.assets[val.id] = val; 953 var li = $('<li><label><input type="checkbox"> ' + val.name + '</label></li>').data('details', val).appendTo(assetList); 954 if (parseInt(val.quantity) < parseInt(val.booking_max))val.booking_max = val.quantity; 955 if (parseInt(val.booking_max) > 1) { 956 $('<span> (' + val.booking_max + ' available)</span>').appendTo($('label', li)); 957 var s = $('<select></select>').appendTo(li); 958 for (var i = parseInt(val.booking_min); i <= parseInt(val.booking_max); i++) { 959 $('<option>' + i + '</option>').appendTo(s); 960 } 961 } 962 }else{ 963 var li = $('<li class="amnp-none-available"><label><input type="checkbox" disabled> ' + val.name + ' (none available at the chosen time)</label></li>').data('details', val).appendTo(assetList); 964 } 965 }); 966 } 967 }); 968 if (room.tc_link && room.tc_link.length > 0) { 969 $('<label><input class="agreed" type="checkbox"> I have read and agree to the room booking <a target="_blank" href="' + room.tc_link + '">terms and conditions</a></label>').appendTo(bookingOptions); 970 } else { 971 $('<label><input class="agreed" type="checkbox"> I have read and agree to the room booking terms and conditions</label>').appendTo(bookingOptions); 972 } 973 }, 974 _getLayoutDetailView: function (layout) { 975 var view = $('<div class="amrp-room-layout-details"></div>'); 976 $('<img>').attr('src', 'http://' + self.settings.client + '.libnet.info/images/roomlayouts/' + layout.image).appendTo(view); 977 $('<div class="amrp-room-layout-title"></div>').text(layout.name).appendTo(view); 978 $('<div class="amrp-room-layout-capacity"><span>Capacity:</span> ' + layout.capacity + '</div>').appendTo(view); 979 if (self.settings.useSetupBreakdown) { 980 if (parseInt(layout.setup_time, 10) > 0)$('<div class="amrp-room-layout-capacity"><span>Setup:</span> ' + layout.setup_time + '</div>').appendTo(view); 981 if (parseInt(layout.breakdown_time, 10) > 0)$('<div class="amrp-room-layout-capacity"><span>Breakdown:</span> ' + layout.breakdown_time + '</div>').appendTo(view); 982 } 983 $('<div class="amrp-room-layout-description"></div>').text(layout.description).appendTo(view); 984 return view; 985 986 }, 987 _updateBookedAssets: function () { 988 self.booking.assets = []; 989 self._updateFinalSummary(); 990 $('.amrp-bookable-assets-list li', self.confirmScreen).each(function (index, el) { 991 if ($(this).find('input').is(':checked')) { 992 var details = $(this).data('details'); 993 var qty = parseInt(details.booking_max) > 1 ? $(this).find('select').val() : 1; 994 self.booking.assets.push({ 995 id: details.id, 996 qty: parseInt(qty) 997 }); 998 self._updateFinalSummary(); 999 } 1000 }); 1001 }, 1002 _updateFinalSummary: function () { 1003 var finalSummary = $('.amrp-booking-final-summary', self.confirmScreen).empty(); 1004 $('<div class="amrp-booking-final-summary-heading">Your reservation</div>').appendTo(finalSummary); 1005 $('<div class="amrp-booking-final-summary-subheading">Contact:</div>').appendTo(finalSummary); 1006 finalSummary.append('<div>' + self.booking.contact.first_name + ' ' + self.booking.contact.last_name + '</div>'); 1007 if (self.booking.contact.phone) finalSummary.append('<div>' + self.booking.contact.phone + '</div>'); 1008 if (self.booking.contact.email) finalSummary.append('<div>' + self.booking.contact.email + '</div>'); 1009 if (self.booking.contact.group_name) { 1010 $('<div class="amrp-booking-final-summary-subheading">Group name:</div>').appendTo(finalSummary); 1011 finalSummary.append('<div>' + self.booking.contact.group_name + '</div>'); 1012 } 1013 if (self.booking.contact.booking_title) { 1014 $('<div class="amrp-booking-final-summary-subheading">Booking title:</div>').appendTo(finalSummary); 1015 finalSummary.append('<div>' + self.booking.contact.booking_title + '</div>'); 1016 } 1017 $('<div class="amrp-booking-final-summary-subheading">Where:</div>').appendTo(finalSummary); 1018 finalSummary.append('<div>' + self.booking.room.title + ', ' + self.locations[self.booking.room.location_id].name + '</div>'); 1019 $('<div class="amrp-booking-final-summary-subheading">
1019When:</div>').appendTo(finalSummary); 1020 var start = moment(self.booking.start_time); 1021 var end = moment(self.booking.end_time); 1022 finalSummary.append('<div>' + start.format('MMMM DD, YYYY') + '</div>'); 1023 finalSummary.append('<div>' + start.format('h:mma') + ' - ' + end.format('h:mma') + '</div>'); 1024 1025 if (self.booking.layout) { 1026 $('<div class="amrp-booking-final-summary-subheading">Layout:</div>').appendTo(finalSummary); 1027 finalSummary.append('<div>' + self.booking.layout.name + '</div>'); 1028 } 1029 1030 if (self.booking.assets && self.booking.assets.length > 0) { 1031 $('<div class="amrp-booking-final-summary-subheading">Bookable resources:</div>').appendTo(finalSummary); 1032 $.each(self.booking.assets, function (index, val) { 1033 var asset = self.assets[val.id]; 1034 var r = $('<div></div>').text(asset.name).appendTo(finalSummary); 1035 if (parseInt(asset.booking_max) > 1) { 1036 r.append(' (' + val.qty + ')'); 1037 } 1038 }); 1039 } 1040 } 1041 }); 1042 $.fn[pluginName] = function (options) { 1043 return this.each(function () { 1044 if (!$.data(this, "plugin_" + pluginName)) { 1045 $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 1046 } 1047 }); 1048 }; 1049})(jQuery, window, document);
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.