The Small Calendar – jQuery + PHP in practise

On the Grafish Design’s Blog I noticed The Small Calendar. That is a small calendar that lets you check your chosen dates for the day of the week. Calendar posted there is a printing version (available for download in 30 languages). This calendar is different from the standard that has only one block from the days of the month. I decided to create a small calendar on-line using PHP a little of jQuery, plus of course CSS.

Target

The calendar in original version looks like this:

The Small Calendar

The Small Calendar - Grafish Design's Blog


source: Grafish Design’s Blog – The small calendar 2010 (en) 1 .

Scheduled my version will have:

  1. Looks like the original
  2. Choicing year, other than present
  3. Multilingualism
  4. The possibility of highlighting column of dates
  5. The possibility of highlighting rows months
  6. The possibility of highlighting days of the week selected dates
  7. The possibility of moving dates block after clickin on the row of the month

Generating the calendar: PHP

To generate the calendar we will use a simple class which will generate us a few things. First, we create a list of months, for each of them we will check the number of days, check for the first day of the week of the month. Then on this basis, we will create an array that will contain the abbreviations of months (in the chosen language), for a selected year, for each attribute the number of days months and adequately sorted abbreviations days of the week.

The class is very simple, we can even call it imitation of a class or set of functions packed into a class.

Methods list:

  1. public __construct – 2 optional arguments: year, array with the language translation | constructor
  2. public setLanguage – 1 argument: array with the translation | setting the language
  3. public getdatesTable – 0 arguments | makes days array
  4. public getCalendar – 0 arguments | gets the array with the calendar
  5. private generateMonths – 0 arguments | makes months array
  6. private generateDayNames – 0 arguments | makes days of week in correct order

Code of the calss

The server-side part is so simple that it requires no description. Constructor can take 2 parameters: a year and a array with a translation. Both parameters are optional, the default is the current year and the Polish language.

SetLanguage method sets the language. Another, getDatesTable generates an array of day months (1-31), denoting respectively the number of days by months. getCalendar inovokes two other methods: generateMonths – generates an array of months, along with important data, and generateDayNames – abridgment for days of week names.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php
/**
 * VokielSmallCalendar class
 * @author Vokiel | http://blog.vokiel.com
 */
class VokielSmallCalendar {
	/**
	 * Selected year
	 * @var int	$year
	 */
	private $year;
	/**
	 * Shortcuts names for months
	 * @var	array $monthsShort
	 */
	private $monthsShort = array();
	/**
	 * Shortcuts names for week days
	 * @var	array	$daysShort 
	 */
	private $daysShort = array(); 
	/**
	 * Generated months table for the calendar
	 * @var array $months
	 */
	private $months = array();
 
	/**
	 * Construct, 
	 * @param	int	$year
	 * @param	array	$lang
	 */
	public function __construct($year=0,$lang=null){
		$this->year = ($year)? (int)$year : date('Y');
		if (!is_array($lang) || !is_array($lang['months']) || !is_array($lang['days'])){
			$lang = null;
		}
		$this->setLanguage($lang);
	}//end of __construct
 
	/**
	 * Setting the monts shortcuts names and days shorcuts names.
	 * Polish is default language.
	 * @param	array	$lang	Monts and days array starting from 1 = January and 1 = Monday
	 */
	public function setLanguage($lang=null){
		$this->monthsShort = (is_array($lang['months']))? $lang['months'] : array(1=>'Sty',2=>'Lut',3=>'Mar',4=>'Kwi',5=>'Maj',6=>'Cze',7=>'Lip',8=>'Sie',9=>'Wrz',10=>'Paź',11=>'Lis',12=>'Gru');	
        $this->daysShort = (is_array($lang['days']))? $lang['days'] : array(1=>'Pon',2=>'Wt',3=>'Śr',4=>'Czw',5=>'Pt',6=>'Sob',7=>'Nie');
	}//end of setLanguage method
 
	/**
	 * Generating the dates table (numbers from 1 to 31)
	 * @return	string	$datesTable	Generated HTML table
	 */
	public function getDatesTable(){
		$datesTable = '<table><tbody><tr>';
		for ($i=1;$i<32;$i++){
			$class = '';
			if ($i>=28){
				if ($i == $this->months[2]['daysCount'] || $i>29){
					$class = 'class="days_'.$i.'"';
				}
			}
			$datesTable .= '<td '.$class.'>'.$i.'</td>';
			if ($i%7==0){
				$datesTable .= '</tr><tr>';
			}
		}
		$datesTable .= '</tr></tbody></table>';
		return $datesTable;
	}//end of getdatesTable method
 
	/**
	 * Getting the calendar
	 * @return	array	$this->months Array with months shortcuts names and sorted week days shortcuts names	 
	 */
	public function getCalendar(){
		$this->generateMonths();
		$this->generateDayNames();
		return $this->months;
	}//end of getCalendar method
 
	/**
	 * Generating months table
	 */
	private function generateMonths(){
		for ($i=1;$i<13;$i++){
			$time = mktime(0,0,0,$i,1,$this->year);
			$this->months[$i]['weekDay'] = date('N',$time);
			$this->months[$i]['montShort'] = $this->monthsShort[$i];
			$this->months[$i]['daysCount'] = date('t',$time);
		}
	}//end of generateMonths method
 
	/**
	 * Generating week day names shortcuts
	 */
	private function generateDayNames(){
		foreach ($this->months as $month => $dayStart){
			$dayStart = $dayStart['weekDay'];
			for ($i=0;$i<7;$i++){
				$day = ($dayStart+$i>7)? (-(7-$dayStart-$i)) : ($dayStart+$i);
				$this->months[$month]['weekdays'][] = $this->daysShort[$day];
				unset($this->months[$month]['weekDay']);
			}
		}
	}//end of generateDayNames method
 
}// end of VokielSmallCalendar class
?>

Handling of the calendar: JavaScript

In this section we will do some javascripting work (using jQuery) with the calendar in order to give it functionality, dynamism and usability. According to our assumptions we need to create some functions that will respond to moving mouse over the calendar fields.

JavaScript code

First function is to highlight the columns of the tables in response to the mouseover of the months. Next part of this function removes hilight after the pointer leaves an element. This is some kind of rollover.

Next section is responsible for the animation after clicking on the month. Block with a list of the days chanes position, moving just under a month selected (clicked).

SendYear function is to indicate the PHP script the user chosen year. Next actions are already rather cosmetic: accepting only the integers in the field of the year, automatically sending the form by pressing enter, clear the box by pressing the Esc key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
$(document).ready(function(){
	/**
	 * Actions after moving cursor over chosen month
	 * Hilights column in dates table and chosen month
	 */
	$('li:not(.daysTable) span').mouseenter(function(){
		var $this = $(this);
		var spanNr = $this.parent('li').children('span').index($this); /* nr dnia tygodnia (od zera) */
 
		$this.parent('li').addClass('hover');
 
		var tab = $this.closest('ul').find('li.daysTable table tr');
		tab.each(function(){
			$(this).find('td:eq('+spanNr+')').addClass('hover');
		});
	}).mouseleave(function(){
		var $this = $(this);
		var spanNr = $this.parent('li').children('span').index($this); /* nr dnia tygodnia (od zera) */
 
		$this.parent('li').removeClass('hover');
 
		var tab = $this.closest('ul').find('li.daysTable table tr');
		tab.each(function(){
			$(this).find('td:eq('+spanNr+')').removeClass('hover');
		});
	});
	/**
	 * Clicking on chosen month
	 * Moves table with dates just after the clicked month
	 */
	$('li:not(.datesTable)').click(function(e){
		e.preventDefault();
		var $this = $(this);
		var dt = $this.parent('ul').children('li.datesTable');
		dt.slideUp(1000,function(){
			$this.after(dt);	
		}).delay(50).slideDown('normal');
 
	});
	/**
	 * Action after moving cursor over chosen day in the table of days (1-31)
	 * Hilights days over all months
	 */
	$('li.datesTable table tr td').mouseenter(function(){
		var $this = $(this);
		var tdNr = $this.parent('tr').children('td').index($this); /* nr dnia miesiaca (od zera) */
		var sp = $this.closest('ul').children('li:not(.datesTable)');
		sp.each(function(){
			$(this).find('span:eq('+tdNr+')').addClass('hover');
		});
 
		var tab = $this.closest('table tbody').children('tr');
		tab.each(function(){
			$(this).find('td:eq('+tdNr+')').addClass('hover');
		});
	}).mouseleave(function(){
		var $this = $(this);
		var tdNr = $this.parent('tr').children('td').index($this); /* nr dnia miesiaca (od zera) */
		var sp = $this.closest('ul').children('li:not(.s)');
		sp.each(function(){
			$(this).find('span:eq('+tdNr+')').removeClass('hover');
		});
 
		var tab = $this.closest('table tbody').children('tr');
		tab.each(function(){
			$(this).find('td:eq('+tdNr+')').removeClass('hover');
		});
	});
	/**
	 * Function for sending new typed year
	 */
	function sendYear(){
		var y = parseInt($('#year').val());
		if (y>1901 && y<2038){
			location.href = '?year='+y;
		}else{
			$('#year').addClass('error');
		}
	}
	/**
	 * Accept button clicked - sending new date
	 */
	$('#accept').click(function(e){
		e.preventDefault();
		sendYear();
	});
	/**
	 * Accept only numbers
	 */
	$('#year').keyup(function(e){
		$(this).val($(this).val().replace(/\D/g,'')); 
	});
	/**
	 * Checking key code on year field (esc, enter keys only)
	 */
	$('#year').keydown(function(e){
		if (e.keyCode==13){ /* enter - send new year */
			sendYear();
		}else if (e.keyCode==27){ /* esc - clear form */
			$(this).val("");
		}
	});
	/**
	 * Remove 'error' clas after focusing year field 
	 */
	$('#year').focus(function(){
		$(this).removeClass('error');
	});
	/**
	 * Changing language
	 */
	$('#lang').change(function(){
		var url = new String(document.location); 
		url.toLowerCase();
		if (url.indexOf('year') > -1) {
			if (url.indexOf('lang') > -1){
				url = url.replace(/lang(.*)/gi,'');
			}
			document.location = url + '&lang=' + $(this).find(':selected').val();
		}else{
			document.location =  '?lang=' + $(this).find(':selected').val();
		}
	});
});

CSS styling

CSS styles do not require extensive discussion. It is important to highlight only a few tags that make it possible to match the appearance of a specific timetable for their needs. Colors for the rows of months, in which the number of days equal to 30, 31 and 28 or 29 are marked with those classes:
.days_31, .days_30, .days_29 or .days_28

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* reset css */
@CHARSET "UTF-8";
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	vertical-align: baseline;
	background: transparent;
	font-family: "Trebuchet MS", Tahoma, Verdana, Arial, sans-serif;
	font-size: 14px;
	overflow: auto;
}
 
#vokiel_small_calendar {
    /* width: 327px; */
    width: 427px;
    margin: 0 auto;
    background: #fff;
    overflow: auto;
}
#vokiel_small_calendar ul {
	border: 1px solid silver;
	padding: 0px 2px;
}
#vokiel_small_calendar ul, #vokiel_small_calendar ul li {
    list-style: none;
    overflow: auto;
}
#vokiel_small_calendar ul li{
	margin: 2px 0px;
	padding: 2px 0px;
	text-align: right;
}
#vokiel_small_calendar ul li strong{
    text-align: center;
    display: block;
    float: left;
    width: 59px;
    clear: left;
    border-right: 1px solid #fff;
}
#vokiel_small_calendar ul li span{
    display: block;
    text-align: center;
    float: left;
    width: 40px;
    border-right: 1px solid #fff;
    cursor: pointer;
}
#vokiel_small_calendar .days_31 {
	background: #46A12A;
	color: #fff;
}
#vokiel_small_calendar .days_30 {
	background: #F29400;
	color: #fff;
}
#vokiel_small_calendar .days_28, #vokiel_small_calendar .days_29 {
	background: #EA609C;
	color: #fff;
}
#vokiel_small_calendar table {
	border-collapse: collapse;
	float: right;
}
#vokiel_small_calendar table, #vokiel_small_calendar table tbody, #vokiel_small_calendar table tr{
	width: 287px;
}
#vokiel_small_calendar table tr td{
	text-align: center;
	border-right: 1px solid #fff;
	cursor: default;
}
#vokiel_small_calendar ul li.hover, #vokiel_small_calendar ul li span.hover, #vokiel_small_calendar ul li table tbody tr td.hover {
	background-color: #59ACEF;
	color: #fff;
}
#vokiel_small_calendar ul li .giveYear {
	float: right; 
	width: 75px;
	text-align: center;
}
#vokiel_small_calendar ul li .giveYear #accept {
	width: 16px;
	height: 16px;
	vertical-align: middle;
}
#vokiel_small_calendar ul li .giveYear #year{
	width: 35px;
	border: 1px solid silver;
}
#vokiel_small_calendar ul li .giveYear #year.error {
	border: 1px solid red;
}
#vokiel_small_calendar ul li .giveYear p {
	font-size: 12px;
}
#vokiel_small_calendar ul li .giveYear small {
	font-size: 10px;
}
#vokiel_small_calendar ul li .giveYear #lang {
	margin-top: 10px;
}

Voila

This was written using PHP and JavaScript. That was the first idea, which was intended to integrate the calendar with important events. However, there is nothing wrong to rewrite the PHP part into JS. So we could obtain a calendar, which does not require server-side script.

In plans for an unspecified future I have a version without the participation of PHP, maybe packing this into an Opera widget, or desktop gadget in the Win 7

Źródła

  1. http://www.grafishdesign.it/blog/the-small-calendar-eng []
 

Przeczytaj także

Komentarze: 5

Dodaj komentarz »

 
 
 

Troszkę słaby silnik tego kalendarza skoro generuje dla lutego 31 dni. I troszkę “animacja” – toggle – średnio działająca.

 

Reply

 

Hi dear, good job!!
But in the demo didn’t run the language!! :S
I think this my idea could be very usefull if it will became a desktop widjet: are you able to do so?

 

Reply

 

@piotroo89 nie generuje 31 dni dla lutego. Jak się dobrze przyjrzysz, to luty jest tego samego koloru, co 28 w tabeli dni. Styczeń, marzec, maj itd są tego samego koloru co 31 w tabeli dni, a kwiecień, czerwiec – co 30 w tabeli dni. Kolorowanie wierszy nie jest przypadkowe. Kolory tła odpowiadają ilościom dni. Tabela dni jest uniwersalna dla wszystkich miesięcy.

Grafish Design yes, there is problem with the demo, tomorrow I will fix it, thx for info.
I’m going to do a desktop widget, an also english version of this post 😉

edit: language error fixed

 

Reply

 

Ok dear, I wait for the widget!! Give me this present!! 🙂
P.s.
Oh, dear, don’t forget to develope the calendar traslated in 32 languages, for all the users of the world! 😛
Ahahahhahahahahahaha!! 🙂

Bye!

 

Reply

 

[…] jak zaplanowałem na końcu wpisu The Small Calendar – jQuery + PHP w praktyce, postanowiłem stworzyć systemowy (windowsowy) gadżet z The Small Calendar. W tym wpisie postaram […]

 

Reply

 

Dodaj komentarz

 
(nie będzie publikowany)
 
 
Komentarz
 
 

Dozwolone tagi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
© 2009 - 2016 Vokiel.com
WordPress Theme by Arcsin modified by Vokiel