Yii, CJuiDatePicker how to block certain days of the Month - php

So I have this widget on my Yii _form.php page.
Is it possible to do things like blocking a certain day of the month? Or maybe blocking all the Mondays of the Month, disallowing users to select any Monday.
UPDATES based on hamed's answer
<script type="text/javascript">
function disableSpecificDays(date) {
//date is an instance of Date
var weekDay = date.getDay(); // Get the weekday as a number (0-6)
if(weekDay == 1){ //weekDay == 1 means Monday
return false;
}
else {
return true;
}
}
</script>
And on the view side,
<?php $form->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $model,
'attribute' => 'date',
'value' => $model->date,
'options' => array(
'showAnim'=>'fadeIn',
'showButtonPanel' => true,
'minDate'=>'0',
'changeYear' => true,
'dateFormat' => 'yy-mm-dd',
'beforeShowDay' => 'disableSpecificDays',
),
));
?>
But for some reason, it blocks EVERYTHING on the date picker. Nothing can be chosen at all. At which point did I do wrong? Please advise.

jqueryUi datepicker has beforeShowDay event. You can use this event in this way:
$this->widget('zii.widgets.jui.CJuiDatePicker',array(
...
'options'=>array(
'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop'
'showOtherMonths'=>true,// Show Other month in jquery
'selectOtherMonths'=>true,// Select Other month in jquery,
'beforeShowDay' => 'disableSpecificDays', //changed ':' to '=>' AND added quote in between function name.
),
'htmlOptions'=>array(
'style'=>''
),
));
?>
Now, you need to define disableSpecificDays function inside <script> tag:
function disableSpecificDays(date) {
//date is an instance of Date
var weekDay = date.getDay(); // Get the weekday as a number (0-6)
var monthDay = date.getDate() //Get the day as a number (1-31)
if(monthDay == 12 || monthDay == 13 || weekDay == 1) //weekDay == 1 means Monday
return false;
else return true;
}
This will disable 12th an 13th days in each month and also disable Mondays.
Here are the two useful link:
jqueryUi datePicker api
javascript Date methods

I know this is an old entry but i found that for Yii 1, putting the return value inside brackets [] does the job. So the JS function should be:
<script type="text/javascript">
//DON'T SHOW SUNDAYS
function disableSpecificDays(date) {
//date is an instance of Date
var weekDay = date.getDay(); // Get the weekday as a number (0-6)
var monthDay = date.getDate();
if(weekDay == 0){
return [false];
}
else {
return [true];
}
}
</script>

This is bit legacy issue, but this is the code I made pass:
...
'options'=>array(
'beforeShowDay'=> 'js:function(date){
var weekDay = date.getDay();
var monthDay = date.getDate()
if(monthDay == 27 || weekDay == 1) { //Disable all Mondays & 27th of the each month
return [false];
} else {
return [true];
}',
...

Related

Time loop for WooCommerce checkout select option from date picker input field

Input field one - delivery date has a datepicker attached. This fills in the required date by client. This field determines the delivery time options that are populated in the select field next to it.
However the options are based on some rules
Time slots are 30 mins intervals from 11am to 4pm.
If the date chosen = today, delivery start time = current time + one hour.
if date is future, delivery is from 11am to 4pm. 30 mins intervals
I need help making the array for the woocommerce options basing on the parameters above from the chosen date. Thanks.
Sample code: First I update the select field options on selecting the date in the using the date picker. Using the code below.
add_action( 'wp_footer', 'woocommerce_update_on_date_select', 21 );
function woocommerce_update_on_date_select() {
if (is_checkout()) {
?>
<script type="text/javascript">
$(document).ready(function() {
function updateCart() {
var d = $("#billing_country").val(),
e = $("#billing_state").val(),
f = $("input#billing_postcode").val(),
g = $("#billing_city").val(),
h = $("input#billing_address_1").val(),
i = $("input#billing_address_2").val(),
j = d,
k = e,
l = f,
m = g,
n = h,
o = i;
$("#ship-to-different-address").find("input").is(":checked") && (j = $("#shipping_country").val(), k = $("#shipping_state").val(), l = $("input#shipping_postcode").val(), m = $("#shipping_city").val(), n = $("input#shipping_address_1").val(), o = $("input#shipping_address_2").val());
var p = {
security: wc_checkout_params.update_order_review_nonce,
payment_method: $("#order_review").find('input[name="payment_method"]:checked').val(),
country: d,
state: e,
postcode: f,
city: g,
address: h,
address_2: i,
s_country: j,
s_state: k,
s_postcode: l,
s_city: m,
s_address: n,
s_address_2: o,
post_data: $("form.checkout").serialize()
};
var c = {update_shipping_method: !0};
if (!1 !== c.update_shipping_method) {
var q = {};
$('select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]').each(function() {
q[$(this).dat$("index")] = $(this).val()
}), p.shipping_method = q
}
$.ajax({
type: "POST",
url: wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%", "update_order_review"),
data: p,
success: function(c) {
var d = $('.woocommerce-checkout input[name="payment_method"]:checked').attr("id");
if ("true" === c.reload) return void window.location.reload();
$(".woocommerce-NoticeGroup-updateOrderReview").remove();
var e = $("#terms").prop("checked");
if (c && c.fragments && $.each(c.fragments, function(b, c) {
$(b).replaceWith(c)
}), e && $("#terms").prop("checked", !0), "failure" === c.result) {
var f = $("form.checkout");
$(".woocommerce-error, .woocommerce-message").remove(), c.messages ? f.prepend('<div class="woocommerce-NoticeGroup-updateOrderReview">' + c.messages + "</div>") : f.prepend(c), f.find(".input-text, select, input:checkbox").blur(), $("html, body").animate({
scrollTop: $("form.checkout").offset().top - 100
}, 1e3)
}
}
});
}
$('#billing_delivery_date').attr('readonly', true);
$('#billing_serving').on('change', function(){
updateCart();
});
$( "#billing_delivery_date" ).on('change', function() {
updateCart();
});
});
</script>
<?php
}
}
Then using the date chosen from date-picker, I try to make the array to send to the select field in the form.
add_filter( 'woocommerce_checkout_fields' , 'brown_remove_billing_postcode_checkout' );
function brown_remove_billing_postcode_checkout( $fields ) {
$error = '';
if (isset($_POST['post_data'])) {
parse_str( $_POST['post_data'], $post_data );
} else {
$post_data = $_POST;
}
$billing_delivery_date = $post_data['billing_delivery_date'];
if ( $billing_delivery_date = !NULL ) {
$date = new DateTime();
$date->setTimezone(new DateTimeZone('Africa/Kampala'));
$order_day = $date->format('Y-m-d H:i:s');
$date = new DateTime(date('Y-m-d', strtotime(str_replace('/' , '-', $billing_delivery_date))));
//If the date picked is greater than the current date
if (strtotime($order_day) > strtotime($date) {
//Make an array of values from 11am to 4pm to pass to $fields['billing']['billing_serving'] options array
} elseif ($order_day == $date) {
//If the Make an array of values from 11am to 4pm to pass to $fields['billing']['billing_serving'] options array
//Get the current time + one hour. Append hour intervals from next top of the hour until 4pm.
}
}
// Add New Fields
$fields['billing']['billing_serving'] = array(
'label' => __('Delivery Time', 'woocommerce'),
'placeholder' => _x('Time for your delivery', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-last'),
'clear' => false,
'autocomplete' => false,
'type' => 'select',
'options' => array(
//Generated array goes here.
'11am' => __('11:00am', 'woocommerce' ),
'1130am' => __('11:30am', 'woocommerce' ),
'12noon' => __('12:00pm', 'woocommerce' ),
'1230pm' => __('12:30pm', 'woocommerce' ),
'1pm' => __('1:00pm', 'woocommerce' ),
'130pm' => __('1:30pm', 'woocommerce' ),
'2pm' => __('2:00pm', 'woocommerce' ),
'230pm' => __('2:30pm', 'woocommerce' ),
'3pm' => __('3:00pm', 'woocommerce' ),
'330pm' => __('3:30pm', 'woocommerce' ),
'4pm' => __('4:00pm', 'woocommerce' )
)
);
return $fields;
}
As the code for the Delivery date was missing, I have made it enabling jQuery-ui datepicker (and you should use your own CSS).
I haven't use your jQuery code, because my approach is quiet different and I was a bit loosed in your code. My PHP code is also quiet different. The select field <options> is almost empty in php, because javascript build it dynamically.
Here php code is passing to Javascript/jQuery some data:
for the delivery starting date.
for the select option key/value pairs (available time slots + default time slots).
Here jQuery/Javascript is located in the same hooked function just after the custom checkout fields codeā€¦
The html for <option> tags in the "delivery time select field are built dynamically by jQuery depending on the Start date and the current time.
All your requirement are respected:
Time slots are 30 mins intervals from 11am to 4pm.
If selected date is today we add an offset of +1 hour to the time slots
If selected date is not today, we got the default time slots (11 available)
Now you should disable your related code to try this one:
// Enable available jQuery datepicker script in Wordpress
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {
// Only on front-end and checkout page
if( is_admin() || ! is_checkout() ) return;
// Load available datepicker jQuery-ui plugin script
wp_enqueue_script( 'jquery-ui-datepicker' );
}
// Add and display custom checkout fields + jQuery script
add_filter( 'woocommerce_checkout_fields' , 'brown_remove_billing_postcode_checkout' );
function brown_remove_billing_postcode_checkout( $fields ) {
// Your Settings
$start_hour = 11; // start time (in hours)
$end_hour = 16; // end time (in hours)
$offset = 1; // One hour before slot time (can be a float number like 1.5)
date_default_timezone_set ('Africa/Kampala'); // The timezone
// Initializing variables
$hour = 3600; // 1 hour in seconds
$day = $hour * 24; // 1 day in seconds
$now = strtotime("now"); // Now time
$real_now = $now + ($offset * $hour); // Now time + offset
$today_date = date("Y-m-d"); // today date
$tomorrow_date = date("Y-m-d", strtotime("+1 day")); // tomorow date
$today_time = strtotime($today_date); // Today time at 00:00 in seconds
$tomorrow_time = strtotime($tomorrow_date); // Tomorrow time at 00:00 in seconds
$start_time = $today_time + ( $start_hour * $hour ); // Start datetime in seconds
$end_time = $today_time + ( $end_hour * $hour ); // End datetime in seconds
$today_slots = $default_slots = $option_days = array();
// Add Delivery day field (with jquery-ui datepicker enabled)
$fields['billing']['billing_delivery_day'] = array(
'label' => __('Delivery Day', 'woocommerce'),
'placeholder' => _x('Date for your delivery', 'placeholder', 'woocommerce'),
'required' => true,
'id' => 'datepicker', // Enable jQuery datepicker for this field
'class' => array('form-row-first'),
'clear' => false,
'autocomplete' => false,
'type' => 'text'
);
// Add Delivery hour slots
$fields['billing']['billing_delivery_hour'] = array(
'label' => __('Delivery Time', 'woocommerce'),
'required' => true,
'class' => array('form-row-last'),
'clear' => false,
'autocomplete' => false,
'type' => 'select',
'options' => array( '' => __('Select time for your delivery') ),
);
// Making the delivery hour slots <option> arrays for Javascript
for($i = $start_time; $i <= $end_time; $i += 1800 ){ // 1800 seconds is half an hour
$key = date('H:i', $i);
$value = date('h:ia', $i);
// Today available hour slots array
if($real_now < $i)
$today_slots[$key] = $value;
// Default hour slots array
$default_slots[$key] = $value;
}
// The correct start date and time (today or tomorow) for Javascript
$date = $real_now < $end_time ? $today_date : $tomorrow_date;
$dtime = $real_now < $end_time ? date("Y-m-d\TH:i:s", $today_time) : date("Y-m-d\TH:i:s", $tomorrow_time);
?>
<script>
jQuery(function($){
var offsetDate = 15, // Number of days enabled in the datepicker (optional and disabled in the datepicker code)
startingDate = new Date('<?php echo $dtime; ?>'), // Starting day (dynamic)
endingDate = new Date('<?php echo $dtime; ?>'), // End date (calculated below)
todaySlots = <?php echo json_encode($today_slots); ?>,
defaultSlots = <?php echo json_encode($default_slots); ?>,
sDay = 'input[name ="billing_delivery_day"]',
sHour = 'select[name ="billing_delivery_hour"]',
defaultOption = $(sHour+' > option').text(),
todaySlotsLength = Object.keys(todaySlots).length;
// ------ 1). Dates and Date picker ------ //
// Set the default field start date
$(sDay).val('<?php echo $date; ?>');
$('#datepicker_field').addClass('woocommerce-validated');
// Max date calculation (optional and diasabeld in the datepicker code)
endingDate.setDate(startingDate.getDate()+offsetDate);
// Jquery-ui datepicker
$("#datepicker").datepicker({
dateFormat: "yy-mm-dd",
minDate: startingDate,
// maxDate: endingDate, // optional, can be enabled.
setDate: startingDate,
});
// ------ 2). HOUR slots select field (dynamic <option>) ------ //
// Build the <option> html html in the select field dynamically
function dynamic_select_options_buid( slotsType ){
$.each( slotsType, function( index, value ){
$(sHour).append('<option value="'+index+'">'+value+'</option>');
});
}
// Replace and Build the <option> html in the select field dynamically
function dynamic_select_options_replace( slotsType ){
$(sHour+' > option').remove();
$(sHour).append('<option value="">'+defaultOption+'</option>');
dynamic_select_options_buid( slotsType );
}
console.log(defaultOption);
console.log(todaySlotsLength);
if(todaySlotsLength != 0 && todaySlotsLength < 11 ){
// Loaded at start
dynamic_select_options_buid( todaySlots );
// Live date selection event
$(sDay).change( function(){
console.log('day changed: '+$(this).val());
if( $(this).val() != '<?php echo $date; ?>' )
dynamic_select_options_replace( defaultSlots );
else
dynamic_select_options_replace( todaySlots );
})
} else {
dynamic_select_options_buid( defaultSlots );
}
});
</script>
<?
return $fields;
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.

disable date in jquery datepicker after some time

I've created a datepicker for one of my client.
They are in a flower delivery business and they offer same day delivery for order which is placed before 12 noon. so I created a following code for that. The basic overview of its functionality is:
-> Disable current date if the time is greater than 12:00 (noon) so that customer can not put order for same day delivery.
But somehow recently one order can at 6PM for same day delivery. Which is an issue.
This is what I did so far:
<?php
// This is how i check for current date and time and if the delivery cut off time is passed add that date to disabled dates array. so customer can not put order of the current date.
current_day = date( "w" );
$todays_cut_off_time = get_option("weekday_cut_off_time_$current_day");
$todays_cut_off_time = strtotime($todays_cut_off_time);
$current_time = date( 'H:i', current_time( 'timestamp', 0 ) );
$current_time = strtotime($current_time);
if($todays_cut_off_time < $current_time)
{
$disabled_dates_array[] = date("m/d/Y");
}
?>
<script>
jQuery( document ).ready(function() {
var disableddates = <?php echo $disabled_delivery_dates; ?>; //contains list of disabled dates by admin.
exceptions = <?php echo $holiday_exception_dates; ?>; //contains dates those are exceptional
function DisableSpecificDates(date) {
var m = date.getMonth() + 1;
if(m <= 9)
m = '0'+m;
var d = date.getDate();
if(d <= 9)
d = '0'+d;
var y = date.getFullYear();
// First convert the date in to the mm-dd-yyyy format
// Take note that we will increment the month count by 1
var currentdate = m + '/' + d + '/' + y ;
// We will now check if the date belongs to exceptions array
for (var i = 0; i < exceptions.length; i++) {
// Now check if the current date is in disabled dates array.
if (jQuery.inArray(currentdate, exceptions) != -1 ) {
return [true];
}
}
// We will now check if the date belongs to disableddates array
for (var i = 0; i < disableddates.length; i++) {
// Now check if the current date is in disabled dates array.
if (jQuery.inArray(currentdate, disableddates) != -1 ) {
return [false];
}
}
// In case the date is not present in disabled array, we will now check if it is a weekend.
// We will use the noWeekends function
//var weekenddate = jQuery.datepicker.noWeekends(date);
var day = date.getDay();
return [(<?php echo $disabled_week_day; ?>), ''];
}
function FindMinDate(date){
return 0;
}
jQuery( "#delivery_date" ).datepicker({
dateFormat: 'mm-dd-yy',
minDate: 0,
beforeShowDay: DisableSpecificDates
});
});
</script>
Can somebody please guide me in the right direction to get this done. Thanks in advance.

implement a function for holidays in a year?

I have a list of holidays like:
var holiDays =[[2013,01,01,'New Years Day'],[2013-05-27, 'Memorial Day']]
and showing on the celender but this list is hard coded so i want a function in php so that all holidays list visible year wise.
$(function() {
$("#id_holiday_date").datepicker({
beforeShowDay: setHoliDays
});
// set holidays function which is configured in beforeShowDay
function setHoliDays(date) {
for (i = 0; i < holiDays.length; i++) {
if (date.getFullYear() == holiDays[i][0]
&& date.getMonth() == holiDays[i][1] - 1
&& date.getDate() == holiDays[i][2]) {
return [true, 'holiday', holiDays[i][3]];
}
}
return [true, ''];
}
});
this function work properly in date picker.this date picker takes date from hardcoded array.
I want a function like that:
function calculateHolidays($year = '') {
$holiDays = Array();
$year = ($year != '') ? $year : date('Y'); //Default Current Year
$newYear = "$year-01-01";
$temp = "$year-05-00 last monday";
$memorialDay = strtotime($temp);//last Monday of May for Current Year
thanks in advance
I'd take a look at PEAR date holidays if I were you.
Here is one way to do it - if you want to find all the brackets [] for a given year:
function display_holidays($year,$list){
echo "<ul>";
$list=str_replace(array('[[',']]','],['),array('[',']',']|['),$list);
$list=explode("|",$list);
foreach($list as $item){
// find the items with the correct year
if(strstr($item,"[".$year)){
echo "<li>".$item."</li>";
}
}
echo "</ul>";
}
Usage example:
$list="[[2012,01,01,'New Years Day'],[2013,05,27, 'Memorial Day']]";
$year=2013;
display_holidays($year,$list);
the outcome will be:
<ul>
<li>[2013,05,27, 'Memorial Day']</li>
</ul>
ps: but please explain in more detail what you want to achieve.

Datetimepicker form validation

I've been trying to create a validation for my form. I've been looking around on how to disable weekends in date time picker as well as holidays. I am using this Jquery script from Trentrichardson http://trentrichardson.com/examples/timepicker/
I am sort of new in JS and am about to pull out my hair as I cannot find a way to make this code work:
$(document).ready(function(){
$('.timepicker').datetimepicker({ beforeShowDay: $.datepicker.noWeekends });
var natDays = [
[2, 26, 'ph'], [2, 6, 'ph'], [2, 17, 'ph']
];
function noWeekendsOrHolidays(date) {
var noWeekend = $.datepicker.noWeekends(date);
if (noWeekend[0]) {
return nationalDays(date);
} else {
return noWeekend;
}
}
function nationalDays(date) {
for (i = 0; i < natDays.length; i++) {
if (date.getMonth() == natDays[i][0] - 1
&& date.getDate() == natDays[i][1]) {
return [false, natDays[i][2] + '_day'];
}
}
return [true, ''];
}
});
I found this code yesterday, which is the correct answer(Can the jQuery UI Datepicker be made to disable Saturdays and Sundays (and holidays)?), but I can't get it to work. It doesn't show the holidays but weekends have been disabled(working).
Any ideas?
Checking whether a date is a Saturday or Sunday should not require a separate function:
if (date.getDay() % 6) {
// date is not a weekend
} else {
// date is a weekend
}
Checking for public holidays (which can be much more difficult given that dates change from year to year and place to place) can be easy too. Create a list of the dates in a set format (ISO8601 is convenient), then you can just test against current date:
// You may have a function like this already
// d is a javascript Date object
function dateToISO(d) {
function z(n){return (n<10? '0':'')+n}
return d.getFullYear() + '-' +
z(d.getMonth() + 1) + '-' +
z(d.getDate());
}
// s is a date string in ISO8601 format
function isPublicHoliday(s) {
var holidays = '2012-12-25 2012-12-26'; // list holidays
var m = holidays.match(s);
return !!(m && m.length);
}
isPublicHoliday(dateToISO(date)); // true for 2012-12-25
Of course you will want to implement the above differently, but it gives you the gist of it. Presumably the date picker returns a date object, or a formatted string that you can test. Testing against a string is very fast and saves a lot of hassle with arrays and functions. Very easy to maintain too, since the dates are quite human readable.

Jquery datepicker beforeShowDay browser inconsistency and update issues

I'm having a bit of an issue with jQuery UI Datepicker where I am trying to highlight free days in a given month as determined by an ajax call.
The problem is two-fold -
The beforeShowDay only appears to be executing correctly in Chrome, not FF or IE, the free-day class is simply not being added in those browsers.
Even in Chrome, when scrolling to the previous month, the free day class is not added until returning to that month, in other words the free days are not highlighted on the first view of that month. This does not appear to be an issue moving forward a month though.
javascript
// declare freeDays global
var freeDays = [];
// perform initial json request for free days
fetchFreeDays();
$(document).ready(function()
{
// fairly standard configuration, importantly containing beforeShowDay and onChangeMonthYear custom methods
$("#datepicker").datepicker({
changeMonth: true,
changeYear: true,
showOtherMonths: true,
selectOtherMonths: true,
dateFormat: 'DD, d MM, yy',
altField: '#date_due',
altFormat: 'yy-mm-dd',
beforeShowDay: highlightDays,
onChangeMonthYear: fetchFreeDays,
firstDay: 1 // rows starts on Monday
});
});
// query for free days in datepicker
function fetchFreeDays(year, month)
{
var start_date = '';
// if a month and year were supplied, build a start_date in yyyy-mm-dd format
if (year != undefined && month != undefined) {
start_date = year +'-';
start_date += month +'-';
start_date += '01';
}
$.getJSON("ajax.todos.php?start_date="+ start_date, function(data){
$.each(data, function(index, value) {
freeDays.push(value.freeDate); // add this date to the freeDays array
});
});
}
// runs for every day displayed in datepicker, adds class and tooltip if matched to days in freeDays array
function highlightDays(date)
{
for (var i = 0; i < freeDays.length; i++) {
if (new Date(freeDays[i]).toString() == date.toString()) {
return [true, 'free-day', 'no to-do items due']; // [0] = true | false if this day is selectable, [1] = class to add, [2] = tooltip to display
}
}
return [true, ''];
}
php
// ajax.todos.php
$i = 0; // counter prevents infinite loop
$cutoff = '61'; // limit on timespan (in days)
$result = array();
// if date is provided, use it, otherwise default to today
$start_date = (!empty($start_date)) ? mysql_real_escape_string($start_date) : date('Y-m-d');
$check_date = $start_date;
$end_date = date('Y-m-d', strtotime("$start_date +$cutoff days")); // never retrieve more than 2 months
while ($check_date != $end_date)
{
// check if any incomplete todos exist on this date
if (mysql_result(mysql_query("SELECT COUNT(id) FROM " . DB_TODOS . " WHERE date_due = '$check_date'"), 0) == 0)
{
$result[] = array('freeDate' => $check_date);
}
// +1 day to the check date
$check_date = date('Y-m-d', strtotime("$check_date +1 day"));
// break from loop if its looking like an infinite loop
$i++;
if ($i > $cutoff) break;
}
header('Content-type: application/json');
echo json_encode($result);
css
/* override free days background in jquery ui datepicker */
.free-day {
background: #2e9500;
}
.free-day a {
opacity: 0.7;
}
I wrote a tutorial about this a couple of months ago which is might have some extra info, which is here.
The problem is that fetchFreeDays() is asynchronous, so it is possible that $("#datepicker").datepicker() finished executeing before you have populated your freeDays array, therefore you don't see anything when the page first renders.
Try putting $("#datepicker").datepicker() inside your $.getJSONs callback function.

Categories