jquery.businessHours
jquery.businessHours copied to clipboard
Add multiple hours in one day
If an employee has a variable schedule in a day, enters at 9 and leaves at 13:00 then reenters at 15:00 and goes home at 19:00. Is this possible?
http://jsfiddle.net/b8pfm3zu/
Sadly the dev who added that functionality didn't code the ability to initialise the plugin from the new modified json object. So its one way and basically useless.
If you manage to get it working would be great if you could share the code
Are there any news about this functionality. I am also interested because splitting business hours is necessary most of the time. Unfortunately I am more into PHP than in Jquery, so its for me a little bit to difficult to get it working.
Hi all, I've quickly added the ability to do two time-sets on my fork here https://github.com/danalaw/jquery.businessHours
@danalaw i couldn't found it :(
any news?
Hello All, I hope it may help someone. Thanks @danalaw, I used your code and improved it a bit, Thanks @Astoroth for the PHP part
@juergenweb I believe it might help you
Fiddle http://jsfiddle.net/hossam_abdelmajeed/no4vs6ru/7/
JS code:
(function($) {
$.fn.businessHours = function(opts) {
var defaults = {
preInit: function(){},
postInit: function() {
$('.operationTimeFrom, .operationTimeTill').timepicker({
'timeFormat': 'H:i',
'step': 15
});
$('.operationTimeFrom, .operationTimeTill').on('changeTime hideTimepicker', function() {
var $that = $(this);
if ($that.val() && /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test( $that.val() )) {
$that.parent().removeClass('has-error');
} else {
$that.parent().addClass('has-error');
}
});
$('.operationTimeFrom, .operationTimeTill').on('timeFormatError timeRangeError', function() {
var $that = $(this);
$that.parent().addClass('has-error');
$that.focus();
});
},
checkedColorClass: "WorkingDayState",
uncheckedColorClass: "RestDayState",
colorBoxValContainerClass: "colorBoxContainer",
weekdays: ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
operationTime: [
{isActive: ""},
{isActive: ""},
{isActive: ""},
{isActive: ""},
{isActive: ""},
{isActive: ""},
{isActive: ""}
],
defaultOperationTimeFrom: '',
defaultOperationTimeTill: '',
defaultActive: false,
//labelOn: "Working day",
//labelOff: "Day off",
//labelTimeFrom: "from:",
//labelTimeTill: "till:",
containerTmpl: '<div class="clean"/>',
dayTmpl: '<div class="dayContainer">' +
'<div data-original-title="" class="colorBox"><input type="checkbox" class="invisible operationState"/></div>' +
'<div class="weekday"></div>' +
'<div class="operationDayTimeContainer">' +
'<div class="operationTime"><input type="text" name="startTime" class="mini-time operationTimeFrom" value=""/></div>' +
'<div class="operationTime"><input type="text" name="endTime" class="mini-time operationTimeTill" value=""/></div>' +
'<div class="operationTime"><input type="text" name="startTime_1" class="mini-time operationTimeFrom" value=""/></div>' +
'<div class="operationTime"><input type="text" name="endTime_1" class="mini-time operationTimeTill" value=""/></div>' +
'</div></div>'
};
var container = $(this);
var methods = {
getValueOrDefault: function(val, defaultVal) {
return (jQuery.type(val) === "undefined" || val == null) ? defaultVal : val;
},
init: function(opts) {
this.options = $.extend(defaults, opts);
container.html("");
if(typeof this.options.preInit === "function") {
this.options.preInit();
}
this.initView(this.options);
if(typeof this.options.postInit === "function") {
//$('.operationTimeFrom, .operationTimeTill').timepicker(options.timepickerOptions);
this.options.postInit();
}
return {
serialize: function() {
var data = [];
container.find(".operationState").each(function(num, item) {
var isWorkingDay = $(item).prop("checked");
var dayContainer = $(item).parents(".dayContainer");
data.push({
isActive: isWorkingDay,
timeFrom: isWorkingDay ? dayContainer.find("[name='startTime']").val() : null,
timeTill: isWorkingDay ? dayContainer.find("[name='endTime']").val() : null,
timeFrom_1: isWorkingDay ? dayContainer.find("[name='startTime_1']").val() : null,
timeTill_1: isWorkingDay ? dayContainer.find("[name='endTime_1']").val() : null
});
});
return data;
},
serializeObject: function() {
var data = [];
container.find(".operationState").each(function(num, item) {
var isWorkingDay = $(item).prop("checked"),
dayContainer = $(item).parents(".dayContainer"),
dayName = dayContainer.find('.weekday').text().toLowerCase();
data[dayName + '_1_open'] = isWorkingDay ? dayContainer.find("[name='startTime']").val() : null;
data[dayName + '_1_close'] = isWorkingDay ? dayContainer.find("[name='endTime']").val() : null;
// generally remove all unwanted error classes
container.find('.operationTime').removeClass('has-error');
// Validation Start
if (data[dayName + '_1_open'] && !data[dayName + '_1_close']) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="endTime"]').parent()
.addClass('has-error');
return false;
}
if (data[dayName + '_1_close'] && !data[dayName + '_1_open']) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="startTime"]').parent()
.addClass('has-error');
return false;
}
// Ignore the null value as it will be a day off
if (!/^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(data[dayName + '_1_close']) && data[dayName + '_1_close'] !== null ) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="endTime"]').parent()
.addClass('has-error');
return false;
}
// Ignore the null value as it will be a day off
if (!/^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(data[dayName + '_1_open']) && data[dayName + '_1_open'] !== null) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="startTime"]').parent()
.addClass('has-error');
return false;
}
// if the hidden class cannot be seen then add the secondary times as well
if (!dayContainer.find('.operationTime.hidden').length) {
data[dayName + '_2_open'] = isWorkingDay ? dayContainer.find("[name='startTime_1']").val() : null;
data[dayName + '_2_close'] = isWorkingDay ? dayContainer.find("[name='endTime_1']").val() : null;
if (data[dayName + '_2_open'] && !data[dayName + '_2_close']) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="endTime_1"]').parent()
.addClass('has-error');
return false;
}
if (data[dayName + '_2_close'] && !data[dayName + '_2_open']) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="startTime_1"]').parent()
.addClass('has-error');
return false;
}
// Ignore the null value as it will be a day off
if (!/^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(data[dayName + '_2_close']) && data[dayName + '_2_close'] !== null ) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="endTime_1"]').parent()
.addClass('has-error');
return false;
}
// Ignore the null value as it will be a day off
if (!/^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(data[dayName + '_2_open']) && data[dayName + '_2_open'] !== null) {
data = [];
// time to show some errors to the user
container.find('[data-weekday="'+ dayName +'"]').parent()
.find('[name="startTime_1"]').parent()
.addClass('has-error');
return false;
}
}
// Validation End
});
return $.extend({}, data);
}
};
},
initView: function(options) {
var stateClasses = [options.checkedColorClass, options.uncheckedColorClass];
var subContainer = container.append($(options.containerTmpl));
var $this = this;
for(var i = 0; i < options.weekdays.length; i++) {
subContainer.append(options.dayTmpl);
}
$.each(options.weekdays, function(pos, weekday) {
// populate form
var day = options.operationTime[pos];
var operationDayNode = container.find(".dayContainer").eq(pos);
operationDayNode.find('.weekday').html(weekday);
operationDayNode.attr('id', 'bhday' + pos); /* ----- Added for PHP (not used yet)------ */
// this used to get a specific node using jquery
operationDayNode.find('.weekday').attr('data-weekday', weekday.toLowerCase());
var isWorkingDay = $this.getValueOrDefault(day.isActive, options.defaultActive);
operationDayNode.find('.operationState').prop('checked', isWorkingDay);
operationDayNode.find('.operationState').attr('id', 'checkbox' + pos); /* ----- Added for PHP (not used yet) ------ */
var timeFrom = $this.getValueOrDefault(day.timeFrom, options.defaultOperationTimeFrom);
operationDayNode.find('[name="startTime"]').val(timeFrom);
operationDayNode.find('[name="startTime"]').attr('id', 'start_1_' + pos); /* /* ----- Added for PHP ------ */
var endTime = $this.getValueOrDefault(day.timeTill, options.defaultOperationTimeTill);
operationDayNode.find('[name="endTime"]').val(endTime);
operationDayNode.find('[name="endTime"]').attr('id', 'end_1_' + pos); /* ----- Added for PHP ------ */
//check if second period has valus
if(day.timeFrom_1){
var btnNewSlot = operationDayNode.find('.addTimeSlot');
$secondTimeSlot = btnNewSlot.parent().find('[name="startTime_1"], [name="endTime_1"]').parent();
$secondTimeSlot.toggleClass('hidden');
if ($secondTimeSlot.is(':visible')) {
btnNewSlot.html('<span class="fa fa-minus-square"></span> Remove');
} else {
btnNewSlot.html('<span class="fa fa-plus-square"></span> Add');
}
}
var timeFrom = $this.getValueOrDefault(day.timeFrom_1, options.defaultOperationTimeFrom);
operationDayNode.find('[name="startTime_1"]').val(timeFrom);
operationDayNode.find('[name="startTime_1"]').attr('id', 'start_2_' + pos); /* /* ----- Added for PHP ------ */
var endTime = $this.getValueOrDefault(day.timeTill_1, options.defaultOperationTimeTill);
operationDayNode.find('[name="endTime_1"]').val(endTime);
operationDayNode.find('[name="endTime_1"]').attr('id', 'end_2_' + pos); /* ----- Added for PHP ------ */
});
container.find(".operationState").change(function() {
var checkbox = $(this);
var boxClass = options.checkedColorClass;
var timeControlDisabled = false;
if(!checkbox.prop("checked")) {
// disabled
boxClass = options.uncheckedColorClass;
timeControlDisabled = true;
}
checkbox.parents(".colorBox").removeClass(stateClasses.join(' ')).addClass(boxClass);
checkbox.parents(".dayContainer").find(".operationTime").toggle(!timeControlDisabled);
}).trigger("change");
container.find(".colorBox").on("click", function() {
var checkbox = $(this).find(".operationState");
checkbox.prop("checked", !checkbox.prop('checked')).trigger("change");
});
// add time slot button click event will show the additional time slot
container.find('.addTimeSlot').on('click', function(e) {
e.preventDefault();
var $that = $(this);
//check if isWorkingDay
var dayChk = $that.parent().find(".operationState");
if(dayChk.prop("checked") === false){
// is dayOff, the we need to open the 1st slot
dayChk.prop('checked', true);
container.find(".operationState").change(function() {
var checkbox = $(this);
var boxClass = options.checkedColorClass;
var timeControlDisabled = false;
if(!checkbox.prop("checked")) {
// disabled
boxClass = options.uncheckedColorClass;
timeControlDisabled = true;
}
checkbox.parents(".colorBox").removeClass(stateClasses.join(' ')).addClass(boxClass);
checkbox.parents(".dayContainer").find(".operationTime").toggle(!timeControlDisabled);
}).trigger("change");
} else {
$secondTimeSlot = $that.parent().find('[name="startTime_1"], [name="endTime_1"]').parent();
$secondTimeSlot.toggleClass('hidden');
if ($secondTimeSlot.is(':visible')) {
$that.html('<span class="fa fa-minus-square"></span> Remove');
} else {
$that.html('<span class="fa fa-plus-square"></span> Add');
//clear second period values
$that.parent().find('[name="startTime_1"]').val('');
$that.parent().find('[name="endTime_1"]').val('');
}
}
});
}
};
return methods.init(opts);
};
})(jQuery);
window.sahan = $("#businessHoursContainer").businessHours({
dayTmpl:'<div class="dayContainer" style="width: 80px;">' +
'<div data-original-title="" class="colorBox"><input type="checkbox" class="invisible operationState"></div>' +
'<div class="weekday"></div>' +
'<div class="operationDayTimeContainer">' +
'<div class="operationTime input-group"><span class="input-group-addon"><i class="fa fa-sun-o"></i></span><input type="text" name="startTime" class="mini-time form-control operationTimeFrom" value=""></div>' +
'<div class="operationTime input-group"><span class="input-group-addon"><i class="fa fa-moon-o"></i></span><input type="text" name="endTime" class="mini-time form-control operationTimeTill" value=""></div>' +
'<div class="operationTime input-group hidden" style="display: table;"><span class="input-group-addon"><i class="fa fa-sun-o"></i></span><input type="text" name="startTime_1" class="mini-time form-control operationTimeFrom" value=""></div>' +
'<div class="operationTime input-group hidden" style="display: table;"><span class="input-group-addon"><i class="fa fa-moon-o"></i></span><input type="text" name="endTime_1" class="mini-time form-control operationTimeTill" value=""></div>' +
'</div><a class="btn btn-default btn-sm addTimeSlot"><span class="fa fa-plus-square"></span> Add</a></div>'
});
$(document).ready(function(){
var optsTimes =
[{"isActive":false,"timeFrom":null,"timeTill":null},
{"isActive":false,"timeFrom":null,"timeTill":null},
{"isActive":false,"timeFrom":null,"timeTill":null},
{"isActive":true,"timeFrom":"7:15","timeTill":"18:00"},
{"isActive":true,"timeFrom":"9:00","timeTill":"18:00","timeFrom_1":"19:00","timeTill_1":"21:00"},
{"isActive":false,"timeFrom":null,"timeTill":null},
{"isActive":false,"timeFrom":null,"timeTill":null}];
$("#businessHoursContainer").businessHours({operationTime: optsTimes,
dayTmpl:'<div class="dayContainer" style="width: 80px;">' +
'<div data-original-title="" class="colorBox"><input type="checkbox" class="invisible operationState"></div>' +
'<div class="weekday"></div>' +
'<div class="operationDayTimeContainer">' +
'<div class="operationTime input-group"><span class="input-group-addon"><i class="fa fa-sun-o"></i></span><input type="text" name="startTime" class="mini-time form-control operationTimeFrom" value=""></div>' +
'<div class="operationTime input-group"><span class="input-group-addon"><i class="fa fa-moon-o"></i></span><input type="text" name="endTime" class="mini-time form-control operationTimeTill" value=""></div>' +
'<div class="operationTime input-group hidden" style="display: table;"><span class="input-group-addon"><i class="fa fa-sun-o"></i></span><input type="text" name="startTime_1" class="mini-time form-control operationTimeFrom" value=""></div>' +
'<div class="operationTime input-group hidden" style="display: table;"><span class="input-group-addon"><i class="fa fa-moon-o"></i></span><input type="text" name="endTime_1" class="mini-time form-control operationTimeTill" value=""></div>' +
'</div><a class="btn btn-default btn-sm addTimeSlot"><span class="fa fa-plus-square"></span> Add</a></div>'
});
});
$(document).on('click','#submit_wh',function(){
/* ----- Added for PHP ------ */
var container = $('#businessHoursContainer');
container.find(".operationState").each(function()
{
var i = $(this).attr('id').replace(/\D/g,'');
//if($(this).is(':checked')) var checked = 1; else var checked = 0;
var startTime_1 = $("#start_1_" + i).val();
var endTime_1 = $("#end_1_" + i).val();
//if(){
var startTime_2 = $("#start_2_" + i).val();
var endTime_2 = $("#end_2_" + i).val();
//}
console.log('#' + i + ' - Start_1: ' + startTime_1 + ' End_1: '+ endTime_1 + ' - Start_2: ' + startTime_2 + ' End_2: '+ endTime_2);
// this is being replaced by a js ajax function to send the information to the PHP server!
});
/* ----- Added for PHP ------ */
});
Wow, that looks really cool!!
Thanks Hossam for sharing it with us!!