3
votes

I have a calendar which is an HTML construction using a PHP/MySQL database source. The calendar is output as a month at a time with a list out of booked dates, past dates and future dates and the current day. My aim is for customers to use the calendar to select the START and the END date of their holiday.

I currently use PHP 5.5 and HTML5, CSS 3 and JQuery 1.11.0. My current code is in a JSFiddle at https://jsfiddle.net/rs7mcoo9/4/

What the Calendar currently does:

My calendar currently has each day in the month a DIV tag which contains two pieces of custom date - a date value as a timestamp and a date value as a human text. When an available date is clicked the date is coloured Green and the date text is shown - via JQuery - in the booking form field.

What I Want the Calendar to do:

What I am looking for is something where the first date of the calendar is clicked and the date is displayed in the booking form as happens already, but then when the second date is clicked on the calendar then each date between the two shows a CSS rule of green days, give a clear and concise definition to the user what dates they have selected, so for example if the 1st is clicked and then the 4th is clicked, then the 1st,2nd,3rd and 4th calendar divs are shaded to show these would be the selected ones.

I envisage this problem can be solved with using JQuery to change the CSS setting of the various selected dates on the calendar but my issue is that I can't find a neat way of selecting the correct dates that would need to be changed upon mouse hovering over a later date once the first start date has been set.

How Have I tried to solve my problem

I have looked at the http://multidatespickr.sourceforge.net/ and http://stefangabos.ro/jquery/zebra-datepicker/ date picking UIs but these do not do what I want, they make the user have to click each individual day they require rather than selecting all the dates between a START and END date.

I have also looked at some other SO questions such as p:calender multiple date selection but these have not helped me get a grip on how to start this functionality.

Working Example

I have a working example of my current setup at: https://jsfiddle.net/rs7mcoo9/4/ . Please note in this setup that the date clearance buttons "clear" do not function.

Each date that is available for booking has two custom values set into its DIV:

    <td class="provbook" title='Sunday, September 13, 2015 (available - click to book)'>
<div data-value='13th September 2015' data-core='20150913'>13</div>
</td>

The date-core value is set as YMD so should be easy to work out dates after/before numerically. My current JQuery is:

$(document).ready(function() {
        $("#mailbox").css("display","block");

        $('td > div').on('click', function() {
            $('#mailbox').show(360);
            $(this).toggleClass( "dateChoice" )
            var dateValueOutput = $(this).attr('data-value');
            var dataCore =  parseInt($(this).attr('data-core'));
            var checkDataA = parseInt($('#coreDateA').val());
            if (isNaN(checkDataA)) {
                checkDataA = 0;
                $('#coreDateA').val();
            }
            var checkDataB = parseInt($('#coreDateB').val());
            if (isNaN(checkDataB)) {
                checkDataB = 0;
                $('#coreDateB').val();
            }
            if (dataCore < checkDataA || checkDataA == 0 ) {

                $('#bookDatesa').val(dateValueOutput);
                $('#coreDateA').val(dataCore);
            }
            else {
                $('#bookDates').val(dateValueOutput);
                $('#coreDateB').val(dataCore);
            }
            /** If input box is empty then also clear hidden field **/
            /** change CSS of selected boxes, for start/finish **/
            /** so If css colour is set, change to clear etx. **/
        });
    });

Next Steps

I would like to use JQuery to achieve the interactivity I would like, I need some help to getting a start to how to get my JQuery/javascript to approach this issue. How can I achieve my aims, with my somewhat perfunctory knowledge of JQuery, specifically I'm looking for the syntax to use so that any DIV date-core value that is equal or above the primary date (var checkDataA) and less than the 2nd date selected, and for these chosen cells / DIVS to apply a custom CSS class.

Many thanks for any help!!

UPDATE

Basically I would like a way to have CSS rules applied to all the DIV tags which fall between to (date) values whereby the values are recorded in data-core within the DIV element. So If someone clicks on the 13th day of a month (20151013) and the 18th Day of a month (20151018) then the DIVs which contain data-core values between these two dates all get extra CSS rules applied to them via Javascript.

Many thanks

2

2 Answers

2
votes

After you have changed the value of coreDateA & coreDateB then after that you can change all the elements class in between using each function and one conditional statement . Just add this code at the end of your click function

var i=$("#coreDateA").val();
var j=$("#coreDateB").val()||i;
$("[data-core]").each(function(){
    var timestamp=parseInt($(this).attr("data-core"));
    var flagClass=$(this).hasClass("dateChoice");
    if(timestamp>=i&&timestamp<=j){
        if(!flagClass)
            $(this).addClass("dateChoice");
    }
    else if(flagClass)
         $(this).removeClass("dateChoice");
});    

DEMO

$(document).ready(function() {
        $("#mailbox").css("display","block");

        $('td > div').on('click', function() {
            $('#mailbox').show(360);
            $(this).toggleClass( "dateChoice" )
            var dateValueOutput = $(this).attr('data-value');
            var dataCore =  parseInt($(this).attr('data-core'));
            var checkDataA = parseInt($('#coreDateA').val());
            if (isNaN(checkDataA)) {
                checkDataA = 0;
            }
            var checkDataB = parseInt($('#coreDateB').val());
            if (isNaN(checkDataB)) {
                checkDataB = 0;
            }
            if (dataCore < checkDataA || checkDataA == 0 ) {

                $('#bookDatesa').val(dateValueOutput);
                $('#coreDateA').val(dataCore);
            }
            else {
                $('#bookDates').val(dateValueOutput);
                $('#coreDateB').val(dataCore);
            }
            var i=$("#coreDateA").val();
            var j=$("#coreDateB").val()||i;
            $("[data-core]").each(function(){
	            var timestamp=parseInt($(this).attr("data-core"));
                var flagClass=$(this).hasClass("dateChoice");
                if(timestamp>=i&&timestamp<=j){
                    if(!flagClass)
                        $(this).addClass("dateChoice");
                }
	            else if(flagClass)
                    $(this).removeClass("dateChoice");
             });    
			
			
        });
    });
.provbook {
	font-weight: bold !important;
	color:#009 !important;
}
.provbook:hover {
	cursor: pointer;
	background-color:#11cc33;
}
.dateChoice, .dateChoice:hover, .dateChoice:focus {
	background-color:#11dd11 !important;
	color:#006 !important;
}
.tariffTable {
	min-width:320px;
	width:80%;
	margin: 0 auto 1em auto;
	border: 1px solid #AAA;
	background-color: #FFF;
	font-size: 0.9em;
	line-height: 1.3em;
	border-collapse: collapse;
}
.calendar {
	padding: 0;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 0.9em;
	min-width: 320px;
	width:80%;
	max-width:600px;
	margin: 0 auto;
	border: 1px solid #AAA;

}
.calendar caption {
	margin: 0;
	padding: .3em 0;
	border-top:#006 1px none;
	border-right:#AAA 1px solid;
	border-left: #AAA 1px solid;
	font-weight: bold;
	background-color: #FFF;
	color: #000;
	font-size: 1.05em;
}
.calendar th {
	border-bottom: 1px solid #ccc;
	font-weight: normal;
	background: #fff;
	text-align: center;
}
.calendar td {
	border: 1px solid #fff;
	padding: .1em .3em ;
	width: 1em;
	text-align: center;
}
/*.calendar a {
	color: #000;
	text-decoration: none;
}*/

.calendar td.today {
	background: #CCC !important;
	font-weight: normal;
	color:#333;
	}
/*
.calendar td.selected {
	border: 1px dotted #ff7800;
	}
	*/
.calendar td.highlighted {
	background-color: #C6B6AE;
	font-weight: normal;
	color:#000;
}
.calendar td.passed {
	font-style: italic;
	font-weight: normal;
	color:#333;
}
.highlightedExample {
	background-color: #C6B6AE;
	padding:0.15em 0.5em;
}
/*
.calendar td:hover, .calendar td.today:hover,
.calendar td.selected:hover, .calendar td.highlighted:hover {
	border: 1px solid #009999;
	}
	*/

table.calendar td.pad {
	color: #999;
	background: #fff;
}
table.calendar td.pad:hover {
	background: none;
	border: 0;
}

.tariffTable tr td {
	padding:0.2em;
}
.tariffTable th {
	font-size: 1em;
	font-weight: bold;
	color: #000;
	border-bottom:#AAA 1px solid;
	padding:0.4em 0.3em;
	text-align: left;
}
.tariffTable th:nth-child(n+3), .tariffTable tr td:nth-child(n+3) {
	text-align: center !important;
}
.tariffTable tr td {

}
.tariffTable tr:nth-child(even) {
	background-color: #DDD;
}
.tariffTable tr:nth-child(odd) {
	background-color: #EEE;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table class='calendar'>
<caption>September 2015</caption>
<col class='sunday' />
<col class='monday' />
<col class='tuesday' />
<col class='wednesday' />
<col class='thursday' />
<col class='friday' />
<col class='saturday' />
<thead>
<tr>
	<th title='Sunday'>S</th>
	<th title='Monday'>M</th>
	<th title='Tuesday'>T</th>
	<th title='Wednesday'>W</th>
	<th title='Thursday'>T</th>
	<th title='Friday'>F</th>
	<th title='Saturday'>S</th>
</tr>
</thead>
<tbody>
<tr>
	<td class='pad'>&nbsp;</td>
	<td class='pad'>&nbsp;</td>
	<td class="highlighted" title='Tuesday, September  1, 2015 (booked)'><div data-value='1st September 2015' data-core='20150901'>01</div></td>
	<td class="highlighted" title='Wednesday, September  2, 2015 (booked)'><div data-value='2nd September 2015' data-core='20150902'>02</div></td>
	<td class="highlighted" title='Thursday, September  3, 2015 (booked)'><div data-value='3rd September 2015' data-core='20150903'>03</div></td>
	<td class="highlighted" title='Friday, September  4, 2015 (booked)'><div data-value='4th September 2015' data-core='20150904'>04</div></td>
	<td class="highlighted" title='Saturday, September  5, 2015 (booked)'><div data-value='5th September 2015' data-core='20150905'>05</div></td>
</tr>
<tr>
	<td class="highlighted" title='Sunday, September  6, 2015 (booked)'><div data-value='6th September 2015' data-core='20150906'>06</div></td>
	<td class="highlighted" title='Monday, September  7, 2015 (booked)'><div data-value='7th September 2015' data-core='20150907'>07</div></td>
	<td class="highlighted" title='Tuesday, September  8, 2015 (booked)'><div data-value='8th September 2015' data-core='20150908'>08</div></td>
	<td class="highlighted" title='Wednesday, September  9, 2015 (booked)'><div data-value='9th September 2015' data-core='20150909'>09</div></td>
	<td class="highlighted" title='Thursday, September 10, 2015 (booked)'><div data-value='10th September 2015' data-core='20150910'>10</div></td>
	<td class="highlighted" title='Friday, September 11, 2015 (booked)'><div data-value='11th September 2015' data-core='20150911'>11</div></td>
	<td class="provbook" title='Saturday, September 12, 2015 (available - click to book)'><div data-value='12th September 2015' data-core='20150912'>12</div></td>
</tr>
<tr>
	<td class="provbook" title='Sunday, September 13, 2015 (available - click to book)'><div data-value='13th September 2015' data-core='20150913'>13</div></td>
	<td class="provbook" title='Monday, September 14, 2015 (available - click to book)'><div data-value='14th September 2015' data-core='20150914'>14</div></td>
	<td class="provbook" title='Tuesday, September 15, 2015 (available - click to book)'><div data-value='15th September 2015' data-core='20150915'>15</div></td>
	<td class="provbook" title='Wednesday, September 16, 2015 (available - click to book)'><div data-value='16th September 2015' data-core='20150916'>16</div></td>
	<td class="provbook" title='Thursday, September 17, 2015 (available - click to book)'><div data-value='17th September 2015' data-core='20150917'>17</div></td>
	<td class="provbook" title='Friday, September 18, 2015 (available - click to book)'><div data-value='18th September 2015' data-core='20150918'>18</div></td>
	<td class="provbook" title='Saturday, September 19, 2015 (available - click to book)'><div data-value='19th September 2015' data-core='20150919'>19</div></td>
</tr>
<tr>
	<td class="provbook" title='Sunday, September 20, 2015 (available - click to book)'><div data-value='20th September 2015' data-core='20150920'>20</div></td>
	<td class="provbook" title='Monday, September 21, 2015 (available - click to book)'><div data-value='21st September 2015' data-core='20150921'>21</div></td>
	<td class="provbook" title='Tuesday, September 22, 2015 (available - click to book)'><div data-value='22nd September 2015' data-core='20150922'>22</div></td>
	<td class="provbook" title='Wednesday, September 23, 2015 (available - click to book)'><div data-value='23rd September 2015' data-core='20150923'>23</div></td>
	<td class="provbook" title='Thursday, September 24, 2015 (available - click to book)'><div data-value='24th September 2015' data-core='20150924'>24</div></td>
	<td class="provbook" title='Friday, September 25, 2015 (available - click to book)'><div data-value='25th September 2015' data-core='20150925'>25</div></td>
	<td class="provbook" title='Saturday, September 26, 2015 (available - click to book)'><div data-value='26th September 2015' data-core='20150926'>26</div></td>
</tr>
<tr>
	<td class="provbook" title='Sunday, September 27, 2015 (available - click to book)'><div data-value='27th September 2015' data-core='20150927'>27</div></td>
	<td class="provbook" title='Monday, September 28, 2015 (available - click to book)'><div data-value='28th September 2015' data-core='20150928'>28</div></td>
	<td class="provbook" title='Tuesday, September 29, 2015 (available - click to book)'><div data-value='29th September 2015' data-core='20150929'>29</div></td>
	<td class="provbook" title='Wednesday, September 30, 2015 (available - click to book)'><div data-value='30th September 2015' data-core='20150930'>30</div></td>
	<td class='pad'>&nbsp;</td>
	<td class='pad'>&nbsp;</td>
	<td class='pad'>&nbsp;</td>
</tr>
</tbody>
</table>

 <div id='mailbox'>
             <form action='' method='post' enctype='multipart/form-data'
             lang='en' name='enqform'>
                 <br>From (<span id='clearFrom'>clear</span>):
            <input type='text' value='' name='datesa' id='bookDatesa' required>
            <input type='hidden' value='' name='coreDateA' id='coreDateA'>
            <input type='hidden' value='' name='coreDateB' id='coreDateB'>
 To (<span id='clearTo'>clear</span>):<br>
            <input type='text' value='' name='dates' id='bookDates' required>

             <input type='submit' value='Send Enquiry' name='submit'>
             </form>
             </div>
0
votes

Here is the code who select the interval selected:

var firstDate = $('#coreDateA').val();
var lastDate = $('#coreDateB').val();

if (firstDate && lastDate) {
  //date format is 20150918
  var firstDay = parseInt(firstDate.substring(6));
  var yearAndMonth = firstDate.substring(0,6);
  var lastDay = parseInt(lastDate.substring(6));

  //reset all selections
  $('td > div').removeClass('dateChoice'); 

  for (var i = firstDay; i <= lastDay; i++){
     $('div[data-core="' + yearAndMonth + i +'"]').addClass('dateChoice');
  }
}

This is the fiddle, where you can see working: https://jsfiddle.net/ozsq6wex/3/

Be aware though, if you want to select cross months, like start in September and finish in October, you will need a more complex logic to make it work