Gravity Wiz // Gravity Forms // Date Range Display
<?php
/**
* Gravity Wiz // Gravity Forms // Date Range Display
*
* Display a group of color-coded date ranges on a calendar based on a GF selected date.
*
* @version 1.0
* @author David Smith <david@gravitywiz.com>
* @license GPL-2.0+
* @link http://gravitywiz.com/...
*/
class GW_Date_Range_Display {
protected static $is_script_output = false;
public function __construct( $args = array() ) {
// set our default arguments, parse against the provided arguments, and store for use throughout the class
$this->_args = wp_parse_args( $args, array(
'selected_date' => false, // '1987-01-13'
'target_id' => false, // '#date-range-display'
'form_id' => false, // 123
'source_field_id' => false, // 12,
'sequential' => false,
'start_from_last' => false,
'ranges' => array()
) );
// do version check in the init to make sure if GF is going to be loaded, it is already loaded
add_action( 'init', array( $this, 'init' ) );
}
function init() {
// make sure we're running the required minimum version of Gravity Forms
if( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) ) {
return;
}
// time for hooks
add_action( 'gform_enqueue_scripts', array( $this, 'enqueue_form_scripts' ) );
add_filter( 'gform_pre_render', array( $this, 'load_form_script' ) );
add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ) );
}
function enqueue_form_scripts( $form ) {
if( $this->is_applicable_form( $form ) ) {
wp_enqueue_script( 'gform_conditional_logic' );
}
}
function load_form_script( $form ) {
if( $this->is_applicable_form( $form ) && ! self::$is_script_output ) {
$this->output_script();
}
return $form;
}
function output_script() {
?>
<script type="text/javascript">
( function( $ ) {
window.GWDateRangeDisplay = function( args ) {
var self = this;
// copy all args to current object: (list expected props)
for( prop in args ) {
if( args.hasOwnProperty( prop ) )
self[prop] = args[prop];
}
self.init = function() {
self.$dateField = $( '#input_' + self.formId + '_' + self.sourceFieldId );
self.$calendarElem = $( self.targetId );
self.$calendarElem.datepicker( {
numberOfMonths: 1,
dayNamesMin: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
beforeShowDay: function( date ) {
var cssClass = '';
for( var i = 0; i < self.ranges.length; i++ ) {
if( ! self.isRangeActive( self.ranges[i] ) ) {
continue;
}
var baseDate = self.sequential && endDate ? endDate : self.getSelectedDate(),
startDate = self.addDaysToDate( new Date( baseDate ), self.ranges[i].start ),
endDate = self.addDaysToDate( new Date( baseDate ), self.ranges[i].end ),
inRange = date >= startDate && date <= endDate;
if( inRange && ! self.isWeekend( date ) ) {
cssClass = 'range' + ( i + 1 );
}
}
return [ true, cssClass, '' ];
}
} ).addClass( 'gw-date-range-display' );
self.$dateField.on( 'change', function() {
GWDateRangeDisplay.refresh();
} );
self.bindConditionalLogic();
GWDateRangeDisplay.refresh();
};
GWDateRangeDisplay.refresh = function( date ) {
if( typeof date == 'undefined' ) {
date = self.getSelectedDate();
}
self.$calendarElem.datepicker( 'setDate', date );
self.$calendarElem.datepicker( 'option', 'numberOfMonths', self.getMonthDisplayCount( date ) );
self.buildCalendarKey();
};
self.getSelectedDate = function() {
var dateValue = self.$dateField.val(),
selectedDate = dateValue ? new Date( dateValue ) : new Date(),
maxRange = self.getMaxRange( selectedDate ),
startingDate = selectedDate,
dayCount = 0;
if( self.startFromLast ) {
while( maxRange.end > maxRange.start ) {
if( ! self.isWeekend( maxRange.end ) ) {
dayCount++;
}
maxRange.end.setDate( maxRange.end.getDate() - 1 );
}
startingDate = self.subtractDaysFromDate( startingDate, dayCount );
} else {
if( self.isWeekend( startingDate ) ) {
startingDate = self.addDaysToDate( startingDate, 1 );
}
}
startingDate.setHours( 0, 0, 0, 0 );
return startingDate;
};
self.addDaysToDate = function( fromDate, days ) {
var count = 0;
while( count < days ) {
fromDate.setDate( fromDate.getDate() + 1 );
if ( ! self.isWeekend( fromDate ) ) {
count++;
}
}
return fromDate;
};
self.subtractDaysFromDate = function( fromDate, days ) {
while( days > 0 ) {
fromDate.setDate( fromDate.getDate() - 1 );
if ( ! self.isWeekend( fromDate ) ) {
days--;
}
}
return fromDate;
};
self.isWeekend = function( date ) {
return date.getDay() === 0 || date.getDay() === 6;
};
self.getMaxRange = function( selectedDate ) {
var earliestDate, latestDate, maxRange;
for( var i = 0; i < self.ranges.length; i++ ) {
if( ! self.isRangeActive( self.ranges[i] ) ) {
continue;
}
var baseDate = self.sequential && endDate ? endDate : selectedDate,
startDate = self.addDaysToDate( new Date( baseDate ), self.ranges[i].start ),
endDate = self.addDaysToDate( new Date( baseDate ), self.ranges[i].end );
if( ! earliestDate || earliestDate >= startDate ) {
earliestDate = startDate;
}
if( ! latestDate || latestDate <= endDate ) {
latestDate = endDate;
}
}
maxRange = {
start: earliestDate,
end: latestDate
};
return maxRange;
};
self.getMonthDisplayCount = function( selectedDate ) {
var maxRange = self.getMaxRange( selectedDate ),
startMonth = maxRange.start.getMonth(),
endMonth = maxRange.end.getMonth();
if( endMonth < startMonth ) {
endMonth += 11;
}
return ( endMonth - startMonth ) + 1;
};
self.buildCalendarKey = function() {
var markup = '',
styles = '';
for( var i = 0; i < self.ranges.length; i++ ) {
var properIndex = i + 1;
// always add style
styles += '.gw-date-range-display td.range' + properIndex + ', .gw-date-range-display .gwdrd-range-key.range' + properIndex + ':before { background-color: ' + self.ranges[i].color + ' !important; }';
// only add markup for active ranges
if( self.isRangeActive( self.ranges[i] ) ) {
markup += '<li class="gwdrd-range-key range' + properIndex + '">' + self.ranges[i].label + '</li>';
}
}
var $keyElem = $( '.gwdrd-range-keys' ),
$styleElem = $( '#gwdrd-styles' );
if( $keyElem.length <= 0 ) {
$keyElem = $( '<ul class="gwdrd-range-keys"></ul>' );
self.$calendarElem.prepend( $keyElem );
}
$keyElem.html( markup );
if( $styleElem.length <= 0 ) {
$styleElem = $( '<style type="text/css">' + styles + '</style>' );
$( 'head' ).append( $styleElem );
}
};
self.isRangeActive = function( range ) {
var hasConditionalLogic = typeof range.conditionalLogic != 'undefined';
return ( hasConditionalLogic && gf_get_field_action( self.formId, range.conditionalLogic ) == 'show' ) || ! hasConditionalLogic;
};
self.bindConditionalLogic = function() {
var boundFields = [];
for( var i = 0; i < self.ranges.length; i++ ) {
var range = self.ranges[i];
if( ! range['conditionalLogic'] ) {
continue;
}
for( var j = 0; j < range.conditionalLogic.rules.length; j++ ) {
var rule = range.conditionalLogic.rules[j];
if( $.inArray( rule.fieldId, boundFields ) == -1 ) {
$( 'li#field_' + self.formId + '_' + rule.fieldId ).find( 'input, select, textarea' ).change( function() {
GWDateRangeDisplay.refresh();
} );
boundFields.push( rule.fieldId );
}
}
}
};
self.init();
}
} )( jQuery );
</script>
<style type="text/css">
.gw-date-range-display .ui-datepicker {
width: 100% !important;
border: 0;
box-shadow: 0 0 0;
}
.gw-date-range-display .ui-datepicker-prev,
.gw-date-range-display .ui-datepicker-next {
display: none;
}
.gw-date-range-display .ui-datepicker-multi .ui-datepicker-group {
float: none;
margin: 0 0 1rem;
width: 100%;
}
.gw-date-range-display .ui-datepicker .ui-datepicker-header {
border: 0;
padding: 0;
background: transparent;
color: #000;
text-shadow: none;
filter: none;
}
.gw-date-range-display .ui-datepicker .ui-datepicker-title {
margin: 0;
text-align: left;
font-size: 12px;
text-shadow: none !important;
background: transparent;
filter: none;
}
.gw-date-range-display .ui-datepicker-multi .ui-datepicker-group table {
width: 100%;
margin: 0;
}
.gw-date-range-display .ui-datepicker thead {
background: transparent;
}
.gw-date-range-display .ui-datepicker th {
border: 1px solid #919191;
font-size: 10px;
text-transform: uppercase;
font-weight: normal;
border-bottom: 1px solid #000;
text-shadow: none;
color: #FFF;
background: rgba(0,0,0,.5);
filter: none !important;
}
.gw-date-range-display .ui-datepicker-calendar tbody td,
.gw-date-range-display .ui-state-disabled {
border: 1px solid #919191;
border-width: 0 1px 1px 0;
background: rgba(255,255,255,.35);
font-size: 12px;
height: 34px;
width: 14%;
padding-top:4px !important;
padding-bottom:4px !important;
text-align: center;
}
.gw-date-range-display .ui-datepicker-calendar tbody td:first-child {
border-left: 1px solid #919191;;
}
.gw-date-range-display .ui-state-default,
.gw-date-range-display .ui-widget-content .ui-state-default,
.gw-date-range-display .ui-widget-header .ui-state-default {
background: transparent;
border: 0;
text-align: center;
box-shadow: 0 0 0;
color: #000;
text-shadow: none;
cursor: default;
filter: none !important;
}
body .gform_wrapper form div.gform_body ul.gform_fields li.gfield.gfield_html ul li.gwdrd-range-key {
list-style: none !important;
line-height: 22px;
margin: 0 0 12px;
text-transform: uppercase;
font-size: 11px;
}
body .gform_wrapper form div.gform_body ul.gform_fields li.gfield.gfield_html ul li.gwdrd-range-key:before {
content: '';
display: block;
float: left;
width: 20px;
height: 20px;
border: 1px solid #000;
margin-right: 8px;
}
.ui-datepicker-title {
font-size:1.75em !important;
line-height: 1.35em;
color: #adcfdf;
padding-top:10px;
padding-left:3px;
padding-bottom:5px;
border: 0px !important;
}
.gwdrd-range-keys {
background:rgba(255,255,255,.15);
padding:15px 15px 10px 15px !important;
}
.gw-date-range-display .ui-datepicker .ui-datepicker-header {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
text-shadow: none;
filter: none;
}
</style>
<?php
self::$is_script_output = true;
}
function add_init_script( $form ) {
if( ! $this->is_applicable_form( $form ) ) {
return;
}
$args = array(
'formId' => $this->_args['form_id'],
'sourceFieldId' => $this->_args['source_field_id'],
'targetId' => $this->_args['target_id'],
'sequential' => $this->_args['sequential'],
'startFromLast' => $this->_args['start_from_last'],
'ranges' => $this->_args['ranges']
);
$script = 'new GWDateRangeDisplay( ' . json_encode( $args ) . ' );';
$slug = implode( '_', array( 'gw_date_range_display', $this->_args['form_id'], $this->_args['source_field_id'] ) );
GFFormDisplay::add_init_script( $this->_args['form_id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );
}
function is_applicable_form( $form ) {
$form_id = isset( $form['id'] ) ? $form['id'] : $form;
return $form_id == $this->_args['form_id'];
}
}
# Configuration
new GW_Date_Range_Display( array(
'target_id' => '#gw-display-calendar',
'form_id' => 812,
'source_field_id' => 12,
'sequential' => true,
'start_from_last' => true,
'ranges' => array(
array(
'label' => 'Final Approvals Due',
'color' => '#ED1D24',
'start' => 0,
'end' => 0
),
array(
'label' => __( 'Translating' ),
'color' => '#b4f1fa',
'start' => 1,
'end' => 10,
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 14,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#b2df97',
'label' => __( 'Printing' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 13,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#d1edbf',
'label' => __( 'Shipping' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 13,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 1,
'color' => '#ffdf2e',
'label' => __( 'In-Hand Due Date' )
)
)
) );
# Configuration
new GW_Date_Range_Display( array(
'target_id' => '#gw-guess-calendar',
'form_id' => 5,
'source_field_id' => 1,
'sequential' => true,
'start_from_last' => true,
'ranges' => array(
array(
'label' => 'Final Approvals Due',
'color' => '#ED1D24',
'start' => 0,
'end' => 0
),
array(
'label' => __( 'Translating' ),
'color' => '#b4f1fa',
'start' => 1,
'end' => 10,
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 8,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#b2df97',
'label' => __( 'Printing' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 7,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#d1edbf',
'label' => __( 'Shipping' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 7,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 1,
'color' => '#ffdf2e',
'label' => __( 'In-Hand Due Date' )
)
)
) );
new GW_Date_Range_Display( array(
'target_id' => '#gw-guess-calendar',
'form_id' => 10,
'source_field_id' => 1,
'sequential' => true,
'start_from_last' => true,
'ranges' => array(
array(
'label' => 'Final Approvals Due',
'color' => '#ED1D24',
'start' => 0,
'end' => 0
),
array(
'label' => __( 'Translating' ),
'color' => '#b4f1fa',
'start' => 1,
'end' => 10,
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 8,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#b2df97',
'label' => __( 'Printing' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 7,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 5,
'color' => '#d1edbf',
'label' => __( 'Shipping' ),
'conditionalLogic' => array(
'actionType' => 'show',
'logicType' => 'all',
'rules' => array(
array(
'fieldId' => 7,
'operator' => 'is',
'value' => 'Yes'
)
)
)
),
array(
'start' => 1,
'end' => 1,
'color' => '#ffdf2e',
'label' => __( 'In-Hand Due Date' )
)
)
) );