2015-07-20 22:41:24 +03:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
* Easy!Appointments - Open Source Web Scheduler
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2015-07-20 22:41:24 +03:00
|
|
|
* @package EasyAppointments
|
|
|
|
* @author A.Tselegidis <alextselegidis@gmail.com>
|
|
|
|
* @copyright Copyright (c) 2013 - 2015, Alex Tselegidis
|
2015-10-09 00:12:59 +03:00
|
|
|
* @license http://opensource.org/licenses/GPL-3.0 - GPLv3
|
2015-07-20 22:41:24 +03:00
|
|
|
* @link http://easyappointments.org
|
|
|
|
* @since v1.0.0
|
|
|
|
* ---------------------------------------------------------------------------- */
|
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2015-10-09 00:12:59 +03:00
|
|
|
* This namespace contains functions that implement the book appointment page
|
|
|
|
* functionality. Once the initialize() method is called the page is fully
|
2013-06-28 17:23:17 +03:00
|
|
|
* functional and can serve the appointment booking process.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-06-13 19:25:34 +03:00
|
|
|
* @namespace FrontendBook
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
2013-06-12 18:31:16 +03:00
|
|
|
var FrontendBook = {
|
2013-06-03 17:42:19 +03:00
|
|
|
/**
|
|
|
|
* Determines the functionality of the page.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-09-13 16:21:03 +03:00
|
|
|
* @type {bool}
|
2013-06-03 17:42:19 +03:00
|
|
|
*/
|
2015-10-09 00:12:59 +03:00
|
|
|
manageMode: false,
|
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
|
|
|
* This method initializes the book appointment page.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
|
|
|
* @param {bool} bindEventHandlers (OPTIONAL) Determines whether the default
|
2013-06-28 17:23:17 +03:00
|
|
|
* event handlers will be binded to the dom elements.
|
2015-10-09 00:12:59 +03:00
|
|
|
* @param {bool} manageMode (OPTIONAL) Determines whether the customer is going
|
2013-06-28 17:23:17 +03:00
|
|
|
* to make changes to an existing appointment rather than booking a new one.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
initialize: function(bindEventHandlers, manageMode) {
|
2013-06-03 17:42:19 +03:00
|
|
|
if (bindEventHandlers === undefined) {
|
|
|
|
bindEventHandlers = true; // Default Value
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
if (manageMode === undefined) {
|
2013-06-08 12:54:45 +03:00
|
|
|
manageMode = false; // Default Value
|
2013-05-20 20:21:58 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.manageMode = manageMode;
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-20 20:21:58 +03:00
|
|
|
// Initialize page's components (tooltips, datepickers etc).
|
2013-04-20 20:20:16 +03:00
|
|
|
$('.book-step').qtip({
|
|
|
|
position: {
|
|
|
|
my: 'top center',
|
|
|
|
at: 'bottom center'
|
|
|
|
},
|
|
|
|
style: {
|
|
|
|
classes: 'qtip-green qtip-shadow custom-qtip'
|
|
|
|
}
|
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
$('#select-date').datepicker({
|
2013-07-02 20:18:19 +03:00
|
|
|
dateFormat: 'dd-mm-yy',
|
2013-10-17 18:31:43 +03:00
|
|
|
firstDay: 1, // Monday
|
2013-07-02 20:18:19 +03:00
|
|
|
minDate: 0,
|
|
|
|
defaultDate: Date.today(),
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-12-20 19:44:44 +02:00
|
|
|
dayNames: [EALang['sunday'], EALang['monday'], EALang['tuesday'], EALang['wednesday'], EALang['thursday'], EALang['friday'], EALang['saturday']],
|
2015-10-09 00:12:59 +03:00
|
|
|
dayNamesShort: [EALang['sunday'].substr(0,3), EALang['monday'].substr(0,3),
|
|
|
|
EALang['tuesday'].substr(0,3), EALang['wednesday'].substr(0,3),
|
2013-12-20 19:44:44 +02:00
|
|
|
EALang['thursday'].substr(0,3), EALang['friday'].substr(0,3),
|
|
|
|
EALang['saturday'].substr(0,3)],
|
2015-10-09 00:12:59 +03:00
|
|
|
dayNamesMin: [EALang['sunday'].substr(0,2), EALang['monday'].substr(0,2),
|
|
|
|
EALang['tuesday'].substr(0,2), EALang['wednesday'].substr(0,2),
|
2013-12-20 19:44:44 +02:00
|
|
|
EALang['thursday'].substr(0,2), EALang['friday'].substr(0,2),
|
|
|
|
EALang['saturday'].substr(0,2)],
|
|
|
|
monthNames: [EALang['january'], EALang['february'], EALang['march'], EALang['april'],
|
|
|
|
EALang['may'], EALang['june'], EALang['july'], EALang['august'], EALang['september'],
|
|
|
|
EALang['october'], EALang['november'], EALang['december']],
|
|
|
|
prevText: EALang['previous'],
|
|
|
|
nextText: EALang['next'],
|
|
|
|
currentText: EALang['now'],
|
|
|
|
closeText: EALang['close'],
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-07-02 20:18:19 +03:00
|
|
|
onSelect: function(dateText, instance) {
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.getAvailableHours(dateText);
|
|
|
|
FrontendBook.updateConfirmFrame();
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
|
|
|
});
|
2013-12-20 19:44:44 +02:00
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-20 20:21:58 +03:00
|
|
|
// Bind the event handlers (might not be necessary every time
|
|
|
|
// we use this class).
|
|
|
|
if (bindEventHandlers) {
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.bindEventHandlers();
|
2013-05-20 20:21:58 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
// If the manage mode is true, the appointments data should be
|
|
|
|
// loaded by default.
|
2013-06-12 18:31:16 +03:00
|
|
|
if (FrontendBook.manageMode) {
|
|
|
|
FrontendBook.applyAppointmentData(GlobalVariables.appointmentData,
|
2013-06-03 17:42:19 +03:00
|
|
|
GlobalVariables.providerData, GlobalVariables.customerData);
|
|
|
|
} else {
|
|
|
|
$('#select-service').trigger('change'); // Load the available hours.
|
|
|
|
}
|
2013-04-20 20:20:16 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2015-10-09 00:12:59 +03:00
|
|
|
* This method binds the necessary event handlers for the book
|
2013-06-03 17:42:19 +03:00
|
|
|
* appointments page.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
bindEventHandlers: function() {
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Selected Provider "Changed"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-06-03 17:42:19 +03:00
|
|
|
* Whenever the provider changes the available appointment
|
|
|
|
* date - time periods must be updated.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
|
|
|
$('#select-provider').change(function() {
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.getAvailableHours(Date.today().toString('dd-MM-yyyy'));
|
|
|
|
FrontendBook.updateConfirmFrame();
|
2013-04-20 20:20:16 +03:00
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Selected Service "Changed"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
|
|
|
* When the user clicks on a service, its available providers should
|
|
|
|
* become visible.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
|
|
|
$('#select-service').change(function() {
|
|
|
|
var currServiceId = $('#select-service').val();
|
|
|
|
$('#select-provider').empty();
|
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
$.each(GlobalVariables.availableProviders, function(indexProvider, provider) {
|
2013-04-20 20:20:16 +03:00
|
|
|
$.each(provider['services'], function(indexService, serviceId) {
|
2013-06-03 17:42:19 +03:00
|
|
|
// If the current provider is able to provide the selected service,
|
2015-10-09 00:12:59 +03:00
|
|
|
// add him to the listbox.
|
|
|
|
if (serviceId == currServiceId) {
|
|
|
|
var optionHtml = '<option value="' + provider['id'] + '">'
|
|
|
|
+ provider['first_name'] + ' ' + provider['last_name']
|
2013-06-03 17:42:19 +03:00
|
|
|
+ '</option>';
|
2013-04-20 20:20:16 +03:00
|
|
|
$('#select-provider').append(optionHtml);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-10-28 00:49:05 +03:00
|
|
|
// Add the "Any Provider" entry.
|
2015-12-01 01:10:16 +02:00
|
|
|
if ($('#select-provider option').length >= 1) {
|
2015-12-11 00:35:33 +02:00
|
|
|
$('#select-provider').append(new Option('- ' +EALang['any_provider'] + ' -', 'any-provider'));
|
2015-10-28 00:49:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-29 15:57:09 +02:00
|
|
|
FrontendBook.getAvailableHours($('#select-date').val());
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.updateConfirmFrame();
|
2013-09-13 16:21:03 +03:00
|
|
|
FrontendBook.updateServiceDescription($('#select-service').val(), $('#service-description'));
|
2013-04-20 20:20:16 +03:00
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Next Step Button "Clicked"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
|
|
|
* This handler is triggered every time the user pressed the
|
|
|
|
* "next" button on the book wizard. Some special tasks might
|
2013-05-20 20:21:58 +03:00
|
|
|
* be perfomed, depending the current wizard step.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
|
|
|
$('.button-next').click(function() {
|
2015-12-11 00:29:15 +02:00
|
|
|
// If we are on the first step and there is not provider selected do not continue
|
|
|
|
// with the next step.
|
|
|
|
if ($(this).attr('data-step_index') === '1' && $('#select-provider').val() == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
// If we are on the 2nd tab then the user should have an appointment hour
|
2013-06-28 17:23:17 +03:00
|
|
|
// selected.
|
2013-05-20 20:21:58 +03:00
|
|
|
if ($(this).attr('data-step_index') === '2') {
|
|
|
|
if ($('.selected-hour').length == 0) {
|
|
|
|
if ($('#select-hour-prompt').length == 0) {
|
2013-06-03 17:42:19 +03:00
|
|
|
$('#available-hours').append('<br><br>'
|
2015-05-31 17:06:09 +03:00
|
|
|
+ '<span id="select-hour-prompt" class="text-danger">'
|
2015-10-09 00:12:59 +03:00
|
|
|
+ EALang['appointment_hour_missing']
|
2015-05-31 17:06:09 +03:00
|
|
|
+ '</span>');
|
2013-05-20 20:21:58 +03:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
|
|
|
// If we are on the 3rd tab then we will need to validate the user's
|
2013-05-20 20:21:58 +03:00
|
|
|
// input before proceeding to the next step.
|
|
|
|
if ($(this).attr('data-step_index') === '3') {
|
2013-06-12 18:31:16 +03:00
|
|
|
if (!FrontendBook.validateCustomerForm()) {
|
2013-05-20 20:21:58 +03:00
|
|
|
return; // Validation failed, do not continue.
|
2013-04-20 20:20:16 +03:00
|
|
|
} else {
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.updateConfirmFrame();
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-20 20:21:58 +03:00
|
|
|
// Display the next step tab (uses jquery animation effect).
|
2013-04-20 20:20:16 +03:00
|
|
|
var nextTabIndex = parseInt($(this).attr('data-step_index')) + 1;
|
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
$(this).parents().eq(1).hide('fade', function() {
|
2013-04-20 20:20:16 +03:00
|
|
|
$('.active-step').removeClass('active-step');
|
|
|
|
$('#step-' + nextTabIndex).addClass('active-step');
|
2013-06-03 17:42:19 +03:00
|
|
|
$('#wizard-frame-' + nextTabIndex).show('fade');
|
2013-04-20 20:20:16 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Back Step Button "Clicked"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
|
|
|
* This handler is triggered every time the user pressed the
|
2013-05-20 20:21:58 +03:00
|
|
|
* "back" button on the book wizard.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
|
|
|
$('.button-back').click(function() {
|
|
|
|
var prevTabIndex = parseInt($(this).attr('data-step_index')) - 1;
|
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
$(this).parents().eq(1).hide('fade', function() {
|
2013-04-20 20:20:16 +03:00
|
|
|
$('.active-step').removeClass('active-step');
|
|
|
|
$('#step-' + prevTabIndex).addClass('active-step');
|
2013-06-03 17:42:19 +03:00
|
|
|
$('#wizard-frame-' + prevTabIndex).show('fade');
|
2013-04-20 20:20:16 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Available Hour "Click"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-05-20 20:21:58 +03:00
|
|
|
* Triggered whenever the user clicks on an available hour
|
|
|
|
* for his appointment.
|
2013-04-20 20:20:16 +03:00
|
|
|
*/
|
|
|
|
$('#available-hours').on('click', '.available-hour', function() {
|
|
|
|
$('.selected-hour').removeClass('selected-hour');
|
|
|
|
$(this).addClass('selected-hour');
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.updateConfirmFrame();
|
2013-04-20 20:20:16 +03:00
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-12 18:31:16 +03:00
|
|
|
if (FrontendBook.manageMode) {
|
2013-06-10 18:51:23 +03:00
|
|
|
/**
|
|
|
|
* Event: Cancel Appointment Button "Click"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-06-10 18:51:23 +03:00
|
|
|
* When the user clicks the "Cancel" button this form is going to
|
|
|
|
* be submitted. We need the user to confirm this action because
|
2015-10-09 00:12:59 +03:00
|
|
|
* once the appointment is cancelled, it will be delete from the
|
2013-06-10 18:51:23 +03:00
|
|
|
* database.
|
|
|
|
*/
|
2014-01-04 00:26:10 +02:00
|
|
|
$('#cancel-appointment').click(function(event) {
|
2013-12-18 19:05:39 +02:00
|
|
|
var dialogButtons = {};
|
|
|
|
dialogButtons['OK'] = function() {
|
|
|
|
if ($('#cancel-reason').val() === '') {
|
|
|
|
$('#cancel-reason').css('border', '2px solid red');
|
|
|
|
return;
|
2013-06-10 18:51:23 +03:00
|
|
|
}
|
2013-12-18 19:05:39 +02:00
|
|
|
$('#cancel-appointment-form textarea').val($('#cancel-reason').val());
|
|
|
|
$('#cancel-appointment-form').submit();
|
|
|
|
};
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-12-20 19:44:44 +02:00
|
|
|
dialogButtons[EALang['cancel']] = function() {
|
2013-12-18 19:05:39 +02:00
|
|
|
$('#message_box').dialog('close');
|
2013-06-10 18:51:23 +03:00
|
|
|
};
|
2015-10-09 00:12:59 +03:00
|
|
|
|
|
|
|
GeneralFunctions.displayMessageBox(EALang['cancel_appointment_title'],
|
2013-12-20 19:44:44 +02:00
|
|
|
EALang['write_appointment_removal_reason'], dialogButtons);
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-10-27 19:41:37 +02:00
|
|
|
$('#message_box').append('<textarea id="cancel-reason" rows="3"></textarea>');
|
2015-04-26 17:19:54 +03:00
|
|
|
$('#cancel-reason').css('width', '100%');
|
2014-01-04 00:26:10 +02:00
|
|
|
return false;
|
2013-06-10 18:51:23 +03:00
|
|
|
});
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-28 17:23:17 +03:00
|
|
|
/**
|
2013-07-02 20:18:19 +03:00
|
|
|
* Event: Book Appointment Form "Submit"
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-06-28 17:23:17 +03:00
|
|
|
* Before the form is submitted to the server we need to make sure that
|
|
|
|
* in the meantime the selected appointment date/time wasn't reserved by
|
2015-10-09 00:12:59 +03:00
|
|
|
* another customer or event.
|
2013-06-28 17:23:17 +03:00
|
|
|
*/
|
2014-01-04 19:25:21 +02:00
|
|
|
$('#book-appointment-submit').click(function(event) {
|
2015-11-23 23:58:32 +02:00
|
|
|
FrontendBook.registerAppointment();
|
2013-06-28 17:23:17 +03:00
|
|
|
});
|
2015-10-22 00:29:20 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Event: Refresh captcha image.
|
|
|
|
*/
|
|
|
|
$('.captcha-title small').click(function(event) {
|
|
|
|
$('.captcha-image').attr('src', GlobalVariables.baseUrl + '/index.php/captcha?' + Date.now());
|
|
|
|
});
|
2013-04-20 20:20:16 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
/**
|
2015-10-09 00:12:59 +03:00
|
|
|
* This function makes an ajax call and returns the available
|
2013-04-20 20:20:16 +03:00
|
|
|
* hours for the selected service, provider and date.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-04-20 20:20:16 +03:00
|
|
|
* @param {string} selDate The selected date of which the available
|
|
|
|
* hours we need to receive.
|
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
getAvailableHours: function(selDate) {
|
2013-10-17 18:31:43 +03:00
|
|
|
$('#available-hours').empty();
|
2015-10-09 00:12:59 +03:00
|
|
|
|
|
|
|
// Find the selected service duration (it is going to
|
2013-10-19 13:34:32 +03:00
|
|
|
// be send within the "postData" object).
|
2013-05-20 20:21:58 +03:00
|
|
|
var selServiceDuration = 15; // Default value of duration (in minutes).
|
2013-06-03 17:42:19 +03:00
|
|
|
$.each(GlobalVariables.availableServices, function(index, service) {
|
2013-05-20 20:21:58 +03:00
|
|
|
if (service['id'] == $('#select-service').val()) {
|
2015-10-09 00:12:59 +03:00
|
|
|
selServiceDuration = service['duration'];
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
2013-05-20 20:21:58 +03:00
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
|
|
|
// If the manage mode is true then the appointment's start
|
2013-06-03 17:42:19 +03:00
|
|
|
// date should return as available too.
|
2015-10-09 00:12:59 +03:00
|
|
|
var appointmentId = (FrontendBook.manageMode)
|
2013-06-03 17:42:19 +03:00
|
|
|
? GlobalVariables.appointmentData['id'] : undefined;
|
2013-04-20 20:20:16 +03:00
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
// Make ajax post request and get the available hours.
|
|
|
|
var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_get_available_hours';
|
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
var postData = {
|
2015-05-28 00:06:48 +03:00
|
|
|
'csrfToken': GlobalVariables.csrfToken,
|
2013-07-02 20:18:19 +03:00
|
|
|
'service_id': $('#select-service').val(),
|
|
|
|
'provider_id': $('#select-provider').val(),
|
|
|
|
'selected_date': selDate,
|
|
|
|
'service_duration': selServiceDuration,
|
|
|
|
'manage_mode': FrontendBook.manageMode,
|
|
|
|
'appointment_id': appointmentId
|
2013-10-19 13:34:32 +03:00
|
|
|
};
|
2013-04-20 20:20:16 +03:00
|
|
|
|
2015-10-09 00:12:59 +03:00
|
|
|
$.post(postUrl, postData, function(response) {
|
2013-07-02 20:18:19 +03:00
|
|
|
///////////////////////////////////////////////////////////////
|
2013-12-25 03:22:37 +02:00
|
|
|
console.log('Get Available Hours JSON Response:', response);
|
2013-07-02 20:18:19 +03:00
|
|
|
///////////////////////////////////////////////////////////////
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-10-18 17:56:12 +03:00
|
|
|
if (!GeneralFunctions.handleAjaxExceptions(response)) return;
|
2013-04-20 20:20:16 +03:00
|
|
|
|
2013-07-02 20:18:19 +03:00
|
|
|
// The response contains the available hours for the selected provider and
|
2015-10-09 00:12:59 +03:00
|
|
|
// service. Fill the available hours div with response data.
|
2013-07-02 20:18:19 +03:00
|
|
|
if (response.length > 0) {
|
|
|
|
var currColumn = 1;
|
|
|
|
$('#available-hours').html('<div style="width:50px; float:left;"></div>');
|
2013-04-20 20:20:16 +03:00
|
|
|
|
2013-07-02 20:18:19 +03:00
|
|
|
$.each(response, function(index, availableHour) {
|
2015-07-08 01:50:25 +03:00
|
|
|
if ((currColumn * 10) < (index + 1)) {
|
2013-07-02 20:18:19 +03:00
|
|
|
currColumn++;
|
|
|
|
$('#available-hours').append('<div style="width:50px; float:left;"></div>');
|
2013-06-08 12:54:45 +03:00
|
|
|
}
|
2013-07-02 20:18:19 +03:00
|
|
|
|
|
|
|
$('#available-hours div:eq(' + (currColumn - 1) + ')').append(
|
|
|
|
'<span class="available-hour">' + availableHour + '</span><br/>');
|
|
|
|
});
|
|
|
|
|
|
|
|
if (FrontendBook.manageMode) {
|
|
|
|
// Set the appointment's start time as the default selection.
|
|
|
|
$('.available-hour').removeClass('selected-hour');
|
|
|
|
$('.available-hour').filter(function() {
|
|
|
|
return $(this).text() === Date.parseExact(
|
|
|
|
GlobalVariables.appointmentData['start_datetime'],
|
|
|
|
'yyyy-MM-dd HH:mm:ss').toString('HH:mm');
|
|
|
|
}).addClass('selected-hour');
|
2013-05-20 20:21:58 +03:00
|
|
|
} else {
|
2013-07-02 20:18:19 +03:00
|
|
|
// Set the first available hour as the default selection.
|
|
|
|
$('.available-hour:eq(0)').addClass('selected-hour');
|
2013-05-20 20:21:58 +03:00
|
|
|
}
|
2013-07-02 20:18:19 +03:00
|
|
|
|
|
|
|
FrontendBook.updateConfirmFrame();
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-07-02 20:18:19 +03:00
|
|
|
} else {
|
2013-12-20 19:44:44 +02:00
|
|
|
$('#available-hours').text(EALang['no_available_hours']);
|
2013-05-08 17:31:17 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
}, 'json').fail(GeneralFunctions.ajaxFailureHandler);
|
2013-04-20 20:20:16 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-06-29 00:54:12 +03:00
|
|
|
* This function validates the customer's data input. The user cannot contiue
|
|
|
|
* without passing all the validation checks.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-04-20 20:20:16 +03:00
|
|
|
* @return {bool} Returns the validation result.
|
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
validateCustomerForm: function() {
|
2013-06-29 00:54:12 +03:00
|
|
|
$('#wizard-frame-3 input').css('border', '');
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-29 00:54:12 +03:00
|
|
|
try {
|
2013-09-13 16:21:03 +03:00
|
|
|
// Validate required fields.
|
2013-06-29 00:54:12 +03:00
|
|
|
var missingRequiredField = false;
|
|
|
|
$('.required').each(function() {
|
|
|
|
if ($(this).val() == '') {
|
2015-04-09 22:50:16 +03:00
|
|
|
$(this).parents('.form-group').addClass('has-error');
|
|
|
|
// $(this).css('border', '2px solid red');
|
2013-06-29 00:54:12 +03:00
|
|
|
missingRequiredField = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (missingRequiredField) {
|
2013-12-20 19:44:44 +02:00
|
|
|
throw EALang['fields_are_required'];
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
// Validate email address.
|
2013-06-29 00:54:12 +03:00
|
|
|
if (!GeneralFunctions.validateEmail($('#email').val())) {
|
2015-04-09 22:50:16 +03:00
|
|
|
$('#email').parents('.form-group').addClass('has-error');
|
|
|
|
// $('#email').css('border', '2px solid red');
|
2013-12-20 19:44:44 +02:00
|
|
|
throw EALang['invalid_email'];
|
2013-06-29 00:54:12 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-29 00:54:12 +03:00
|
|
|
return true;
|
|
|
|
} catch(exc) {
|
|
|
|
$('#form-message').text(exc);
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-20 20:20:16 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Every time this function is executed, it updates the confirmation
|
2015-10-09 00:12:59 +03:00
|
|
|
* page with the latest customer settigns and input for the appointment
|
2013-04-20 20:20:16 +03:00
|
|
|
* booking.
|
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
updateConfirmFrame: function() {
|
2013-09-13 16:21:03 +03:00
|
|
|
// Appointment Details
|
2013-04-20 20:20:16 +03:00
|
|
|
var selectedDate = $('#select-date').datepicker('getDate');
|
2013-05-17 16:09:10 +03:00
|
|
|
if (selectedDate !== null) {
|
2015-12-02 00:25:59 +02:00
|
|
|
selectedDate = GeneralFunctions.formatDate(selectedDate, GlobalVariables.dateFormat);
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
var selServiceId = $('#select-service').val();
|
|
|
|
var servicePrice, serviceCurrency;
|
|
|
|
$.each(GlobalVariables.availableServices, function(index, service) {
|
|
|
|
if (service.id == selServiceId) {
|
|
|
|
servicePrice = '<br>' + service.price;
|
|
|
|
serviceCurrency = service.currency;
|
|
|
|
return false; // break loop
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-11-28 13:55:03 +02:00
|
|
|
|
|
|
|
var html =
|
2015-10-09 00:12:59 +03:00
|
|
|
'<h4>' + $('#select-service option:selected').text() + '</h4>' +
|
|
|
|
'<p>'
|
2015-11-28 13:55:03 +02:00
|
|
|
+ '<strong class="text-primary">'
|
2013-09-13 16:21:03 +03:00
|
|
|
+ $('#select-provider option:selected').text() + '<br>'
|
2015-11-28 13:55:03 +02:00
|
|
|
+ selectedDate + ' ' + $('.selected-hour').text()
|
2013-09-13 16:21:03 +03:00
|
|
|
+ servicePrice + ' ' + serviceCurrency
|
2015-11-28 13:55:03 +02:00
|
|
|
+ '</strong>' +
|
|
|
|
'</p>';
|
|
|
|
|
|
|
|
$('#appointment-details').html(html);
|
2013-04-20 20:20:16 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
// Customer Details
|
2015-11-28 13:55:03 +02:00
|
|
|
|
|
|
|
var firstname = GeneralFunctions.escapeHtml($('#first-name').val()),
|
|
|
|
lastname = GeneralFunctions.escapeHtml($('#last-name').val()),
|
|
|
|
phoneNumber = GeneralFunctions.escapeHtml($('#phone-number').val()),
|
|
|
|
email = GeneralFunctions.escapeHtml($('#email').val()),
|
|
|
|
address = GeneralFunctions.escapeHtml($('#address').val()),
|
|
|
|
city = GeneralFunctions.escapeHtml($('#city').val()),
|
|
|
|
zipCode = GeneralFunctions.escapeHtml($('#zip-code').val()),
|
|
|
|
|
|
|
|
html =
|
|
|
|
'<h4>' + firstname + ' ' + lastname + '</h4>' +
|
2015-10-09 00:12:59 +03:00
|
|
|
'<p>' +
|
2015-11-28 13:55:03 +02:00
|
|
|
EALang['phone'] + ': ' + phoneNumber +
|
|
|
|
'<br/>' +
|
|
|
|
EALang['email'] + ': ' + email +
|
|
|
|
'<br/>' +
|
|
|
|
EALang['address'] + ': ' + address +
|
|
|
|
'<br/>' +
|
|
|
|
EALang['city'] + ': ' + city +
|
|
|
|
'<br/>' +
|
|
|
|
EALang['zip_code'] + ': ' + zipCode +
|
|
|
|
'</p>';
|
|
|
|
|
|
|
|
$('#customer-details').html(html);
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
// Update appointment form data for submission to server when the user confirms
|
|
|
|
// the appointment.
|
2013-05-04 00:26:04 +03:00
|
|
|
var postData = new Object();
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-04 00:26:04 +03:00
|
|
|
postData['customer'] = {
|
2013-07-02 20:18:19 +03:00
|
|
|
'last_name': $('#last-name').val(),
|
|
|
|
'first_name': $('#first-name').val(),
|
|
|
|
'email': $('#email').val(),
|
|
|
|
'phone_number': $('#phone-number').val(),
|
|
|
|
'address': $('#address').val(),
|
|
|
|
'city': $('#city').val(),
|
|
|
|
'zip_code': $('#zip-code').val()
|
2013-05-04 00:26:04 +03:00
|
|
|
};
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-04 00:26:04 +03:00
|
|
|
postData['appointment'] = {
|
2015-10-09 00:12:59 +03:00
|
|
|
'start_datetime': $('#select-date').datepicker('getDate').toString('yyyy-MM-dd')
|
2013-07-02 20:18:19 +03:00
|
|
|
+ ' ' + $('.selected-hour').text() + ':00',
|
|
|
|
'end_datetime': FrontendBook.calcEndDatetime(),
|
|
|
|
'notes': $('#notes').val(),
|
2013-07-15 10:32:19 +03:00
|
|
|
'is_unavailable': false,
|
2013-07-02 20:18:19 +03:00
|
|
|
'id_users_provider': $('#select-provider').val(),
|
|
|
|
'id_services': $('#select-service').val()
|
2013-05-04 00:26:04 +03:00
|
|
|
};
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-12 18:31:16 +03:00
|
|
|
postData['manage_mode'] = FrontendBook.manageMode;
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-12 18:31:16 +03:00
|
|
|
if (FrontendBook.manageMode) {
|
2013-06-08 12:54:45 +03:00
|
|
|
postData['appointment']['id'] = GlobalVariables.appointmentData['id'];
|
|
|
|
postData['customer']['id'] = GlobalVariables.customerData['id'];
|
|
|
|
}
|
2015-05-28 00:26:36 +03:00
|
|
|
$('input[name="csrfToken"]').val(GlobalVariables.csrfToken);
|
2013-05-04 00:26:04 +03:00
|
|
|
$('input[name="post_data"]').val(JSON.stringify(postData));
|
2013-04-20 20:20:16 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method calculates the end datetime of the current appointment.
|
2013-04-20 20:20:16 +03:00
|
|
|
* End datetime is depending on the service and start datetime fieldss.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-04-20 20:20:16 +03:00
|
|
|
* @return {string} Returns the end datetime in string format.
|
|
|
|
*/
|
2013-07-02 20:18:19 +03:00
|
|
|
calcEndDatetime: function() {
|
2015-10-09 00:12:59 +03:00
|
|
|
// Find selected service duration.
|
2013-04-20 20:20:16 +03:00
|
|
|
var selServiceDuration = undefined;
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
$.each(GlobalVariables.availableServices, function(index, service) {
|
2013-05-20 20:21:58 +03:00
|
|
|
if (service.id == $('#select-service').val()) {
|
2013-04-20 20:20:16 +03:00
|
|
|
selServiceDuration = service.duration;
|
2015-10-09 00:12:59 +03:00
|
|
|
return false; // Stop searching ...
|
2013-04-20 20:20:16 +03:00
|
|
|
}
|
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-04-20 20:20:16 +03:00
|
|
|
// Add the duration to the start datetime.
|
2015-10-09 00:12:59 +03:00
|
|
|
var startDatetime = $('#select-date').datepicker('getDate').toString('dd-MM-yyyy')
|
2013-05-17 16:09:10 +03:00
|
|
|
+ ' ' + $('.selected-hour').text();
|
2013-05-20 20:21:58 +03:00
|
|
|
startDatetime = Date.parseExact(startDatetime, 'dd-MM-yyyy HH:mm');
|
2013-04-20 20:20:16 +03:00
|
|
|
var endDatetime = undefined;
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-17 16:09:10 +03:00
|
|
|
if (selServiceDuration !== undefined && startDatetime !== null) {
|
|
|
|
endDatetime = startDatetime.add({ 'minutes' : parseInt(selServiceDuration) });
|
2013-04-20 20:20:16 +03:00
|
|
|
} else {
|
|
|
|
endDatetime = new Date();
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-05-17 16:09:10 +03:00
|
|
|
return endDatetime.toString('yyyy-MM-dd HH:mm:ss');
|
2013-06-03 17:42:19 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
/**
|
2015-10-09 00:12:59 +03:00
|
|
|
* This method applies the appointment's data to the wizard so
|
2013-06-03 17:42:19 +03:00
|
|
|
* that the user can start making changes on an existing record.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-07-06 03:00:04 +03:00
|
|
|
* @param {object} appointment Selected appointment's data.
|
|
|
|
* @param {object} provider Selected provider's data.
|
|
|
|
* @param {object} customer Selected customer's data.
|
2013-06-03 17:42:19 +03:00
|
|
|
* @returns {bool} Returns the operation result.
|
|
|
|
*/
|
2013-07-06 03:00:04 +03:00
|
|
|
applyAppointmentData: function(appointment, provider, customer) {
|
2013-06-03 17:42:19 +03:00
|
|
|
try {
|
|
|
|
// Select Service & Provider
|
2013-07-06 03:00:04 +03:00
|
|
|
$('#select-service').val(appointment['id_services']).trigger('change');
|
|
|
|
$('#select-provider').val(appointment['id_users_provider']);
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
// Set Appointment Date
|
2015-10-09 00:12:59 +03:00
|
|
|
$('#select-date').datepicker('setDate',
|
2013-10-19 13:34:32 +03:00
|
|
|
Date.parseExact(appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss'));
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.getAvailableHours($('#select-date').val());
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
// Apply Customer's Data
|
2013-07-06 03:00:04 +03:00
|
|
|
$('#last-name').val(customer['last_name']);
|
|
|
|
$('#first-name').val(customer['first_name']);
|
|
|
|
$('#email').val(customer['email']);
|
|
|
|
$('#phone-number').val(customer['phone_number']);
|
|
|
|
$('#address').val(customer['address']);
|
|
|
|
$('#city').val(customer['city']);
|
|
|
|
$('#zip-code').val(customer['zip_code']);
|
2015-10-09 00:12:59 +03:00
|
|
|
var appointmentNotes = (appointment['notes'] !== null)
|
2013-07-06 03:00:04 +03:00
|
|
|
? appointment['notes'] : '';
|
2013-06-08 12:54:45 +03:00
|
|
|
$('#notes').val(appointmentNotes);
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-12 18:31:16 +03:00
|
|
|
FrontendBook.updateConfirmFrame();
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-06-03 17:42:19 +03:00
|
|
|
return true;
|
|
|
|
} catch(exc) {
|
2013-07-02 20:18:19 +03:00
|
|
|
console.log(exc); // log exception
|
2013-06-03 17:42:19 +03:00
|
|
|
return false;
|
|
|
|
}
|
2013-09-13 16:21:03 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
/**
|
2015-10-09 00:12:59 +03:00
|
|
|
* This method updates a div's html content with a brief description of the
|
|
|
|
* user selected service (only if available in db). This is usefull for the
|
2013-09-13 16:21:03 +03:00
|
|
|
* customers upon selecting the correct service.
|
2015-10-09 00:12:59 +03:00
|
|
|
*
|
2013-09-13 16:21:03 +03:00
|
|
|
* @param {int} serviceId The selected service record id.
|
2015-10-09 00:12:59 +03:00
|
|
|
* @param {object} $div The destination div jquery object (e.g. provide $('#div-id')
|
2013-09-13 16:21:03 +03:00
|
|
|
* object as value).
|
|
|
|
*/
|
|
|
|
updateServiceDescription: function(serviceId, $div) {
|
2015-10-09 00:12:59 +03:00
|
|
|
var html = '';
|
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
$.each(GlobalVariables.availableServices, function(index, service) {
|
|
|
|
if (service.id == serviceId) { // Just found the service.
|
2013-11-23 21:10:31 +02:00
|
|
|
html = '<strong>' + service.name + ' </strong>';
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
if (service.description != '' && service.description != null) {
|
2013-10-27 19:41:37 +02:00
|
|
|
html += '<br>' + service.description + '<br>';
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-10-27 19:41:37 +02:00
|
|
|
if (service.duration != '' && service.duration != null) {
|
2015-10-09 00:12:59 +03:00
|
|
|
html += '[' + EALang['duration'] + ' ' + service.duration
|
2013-12-20 19:44:44 +02:00
|
|
|
+ ' ' + EALang['minutes'] + '] ';
|
2013-09-13 16:21:03 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
if (service.price != '' && service.price != null) {
|
2013-12-20 19:44:44 +02:00
|
|
|
html += '[' + EALang['price'] + ' ' + service.price + ' ' + service.currency + ']';
|
2015-10-09 00:12:59 +03:00
|
|
|
}
|
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
html += '<br>';
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
$div.html(html);
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2013-09-13 16:21:03 +03:00
|
|
|
if (html != '') {
|
|
|
|
$div.show();
|
|
|
|
} else {
|
|
|
|
$div.hide();
|
|
|
|
}
|
2015-10-22 00:29:20 +03:00
|
|
|
},
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2015-10-22 00:29:20 +03:00
|
|
|
/**
|
|
|
|
* Register an appointment to the database.
|
|
|
|
*
|
|
|
|
* This method will make an ajax call to the appointments controller that will register
|
|
|
|
* the appointment to the database.
|
|
|
|
*/
|
|
|
|
registerAppointment: function() {
|
|
|
|
if ($('.captcha-text').val() === '') {
|
|
|
|
$('.captcha-text').css('border', '1px solid red');
|
|
|
|
return;
|
2015-10-22 00:44:12 +03:00
|
|
|
} else {
|
|
|
|
$('.captcha-text').css('border', '');
|
2015-10-22 00:29:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
var formData = jQuery.parseJSON($('input[name="post_data"]').val());
|
|
|
|
|
|
|
|
var postData = {
|
|
|
|
'csrfToken': GlobalVariables.csrfToken,
|
|
|
|
'post_data': formData,
|
|
|
|
'captcha': $('.captcha-text').val()
|
|
|
|
};
|
|
|
|
|
|
|
|
if (GlobalVariables.manageMode) {
|
|
|
|
postData.exclude_appointment_id = GlobalVariables.appointmentData.id;
|
|
|
|
}
|
|
|
|
|
2015-10-22 00:44:12 +03:00
|
|
|
var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_register_appointment',
|
|
|
|
$layer = $('<div/>');
|
2015-10-22 00:29:20 +03:00
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
url: postUrl,
|
|
|
|
method: 'post',
|
|
|
|
data: postData,
|
2015-10-22 00:44:12 +03:00
|
|
|
dataType: 'json',
|
|
|
|
beforeSend: function(jqxhr, settings) {
|
|
|
|
$layer
|
|
|
|
.appendTo('body')
|
|
|
|
.css({
|
|
|
|
'background': 'white',
|
|
|
|
'position': 'fixed',
|
|
|
|
'top': '0',
|
|
|
|
'left': '0',
|
|
|
|
'height': '100vh',
|
|
|
|
'width': '100vw',
|
|
|
|
'opacity': '0.5'
|
|
|
|
});
|
|
|
|
}
|
2015-10-22 00:29:20 +03:00
|
|
|
})
|
|
|
|
.done(function(response) {
|
2015-11-23 23:58:32 +02:00
|
|
|
if (!GeneralFunctions.handleAjaxExceptions(response)) {
|
2015-10-22 00:29:20 +03:00
|
|
|
$('.captcha-title small').trigger('click');
|
|
|
|
return false;
|
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
|
2015-10-22 00:44:12 +03:00
|
|
|
window.location.replace(GlobalVariables.baseUrl
|
|
|
|
+ '/index.php/appointments/book_success/' + response.appointment_id);
|
2015-10-22 00:29:20 +03:00
|
|
|
})
|
|
|
|
.fail(function(jqxhr, textStatus, errorThrown) {
|
|
|
|
$('.captcha-title small').trigger('click');
|
|
|
|
GeneralFunctions.ajaxFailureHandler(jqxhr, textStatus, errorThrown);
|
2015-10-22 00:44:12 +03:00
|
|
|
})
|
|
|
|
.always(function() {
|
|
|
|
$layer.remove();
|
|
|
|
})
|
2015-10-22 00:29:20 +03:00
|
|
|
}
|
2015-10-09 00:12:59 +03:00
|
|
|
};
|