blinks.org.uk

Lately I’ve have taken a little bit of time out from Art-Thing and have been working on a smaller side project called www.blinks.org.uk

I’ve been using this as a bit of a test bed for various aspects of Art-Thing but it is also a fun little project in its own right. AND even better it should be ready very soon, it is a directory of UK businesses and services with a pretty flat structure based on tagging and regions. Fast, easy to use and fun (if a business directory can be fun).

The site is almost ready to launch and the whole process from the first ideas until now has been very quick – it is built in CakePHP 1.2 and jQuery which make coding a pleasure again. It’s also fun to do a bit of design for a change instead of just the stuff under the hood.

Here is a sneak preview:

blinks.org.uk

If you own or manage a business in the UK why not sign up for FREE with blinks.org.uk and see how it can help your business.

blinks.org.uk is a brand new directory of businesses and services based in the UK.

Every entry in the directory is approved by a real person and businesses have to provide their actual address so the directory is completely spam free and only contains quality listings.

  • Link back to your website (great for SEO)
  • Add a description of your business or service
  • Add an image or company logo
  • Update your entry whenever you want
  • Add you business or service to multiple categories
  • Add tags (keywords) – that are right just for you
  • Automatically show your location on our map

Finding a business in the UK - made simple

CakePHP Calendar Helper

About six months ago I wrote a post about a Simple PHP calendar function I had written and how it was also really easy to use as a CakePHP helper.

Calendar Screenshot

I didn’t actually write the calendar specifically with Cake in mind, but I was working on a Cake site at the same time and I had a flash of inspiration. I was working on a project that needed a calendar, so I looked through all my old code but all the Calendars I had were all tied up in a terrible mess with bits of logic and SQL queries and layout all rolled into one. I looked on Google and still couldn’t find anything really easy to use – I wanted something I could just drop into place.

I suddenly realised that the way to do it was to stop trying to put any decision making into the calendar at all. The calendar only needs to display the right layout for the month and manage back and forward links. I decided to just dump the data in an array where the index corresponded to the day number (1 to 31) – the idea being that you can put anything in the array – plain text, html, javascript hooks for ajax etc.

It was in part influenced by some work I was doing using the The Yahoo! User Interface Library (YUI)
but I am very dubious about the whole notion of creating embedded calendars solely through Javascript when it could far more easily be done server side. (There is clearly a place for Javascript pop up calendars e.g. date pickers – I’m particularly fond of Marc Grabanski and Keith Woods’ version jQuery UI Datepicker)

At the time I had just moved over to using CakePHP as the main vehicle for my development work and it was clearly a great fit with the MVC setup of CakePHP – the calendar is just a shell that shows whatever you pour into it.

This is the first time I have had to go back and revisit the code, I have fixed the bugs, added some comments and set up a working example. At the moment all the logic is just sitting in the controller – but I am working on a component to tidy everything up and make it nice and portable (watch this space).

Thanks to everybody who commented or emailed me about the first version in September.

Calendar Helper


';
	
	$str .= '';
	
	$str .= '';
	
	$str .= $this->Html->link(__(‘prev’, true), array($prev_year, $prev_month));
	
	$str .= '' . ucfirst($month) . ' ' . $year . '';
	
	$str .= $this->Html->link(__(‘next’, true), array($next_year, $next_month));


	
	$str .= '';
	
	$str .= '';
	
		for($i = 0; $i < 7;$i++) {
				$str .= '' . $day_list[$i] . '';
		}
		
	$str .= '';
	
	$str .= '';
	
	$str .= '';
		
	while($day <= $days_in_month) {
		$str .= '';
			
		for($i = 0; $i < 7; $i ++) {
		
			$cell = ' ';
			
			if(isset($data[$day])) {
				$cell = $data[$day];
			}
				
			$class = '';
			
			if($i > 4) {
				$class = ' class="cell-weekend" ';
			}
			
			if($day == $today) {
				$class = ' class="cell-today" ';
			}
		
                        $first_day_in_month = strtolower($first_day_in_month);
			if(($first_day_in_month == $day_list[$i] || $day > 1) && ($day <= $days_in_month)) {
				$str .= '
' . $day . '
' . $cell . '
'; $day++; } else { $str .= ' '; } } $str .= ''; } $str .= ''; $str .= ''; return $str; } } ?>

Calendar Controller

The controller is responsible for creating the data array containing the calendar ‘events’ and then passing this on to the view from where the calendar is called.


Event->recursive = 0;
		
		$month_list = array('january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december');
		$day_list = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
		$base_url = $this->webroot . 'events/calendar'; // NOT not used in the current helper version but used in the data array
		$view_base_url = $this->webroot. 'events';
		
		$data = null;
	
		if(!$year || !$month) {
			$year = date('Y');
			$month = date('M');
			$month_num = date('n');
			$item = null;
		}
			
		$flag = 0;
				
		for($i = 0; $i < 12; $i++) { // check the month is valid if set
			if(strtolower($month) == $month_list[$i]) {
				if(intval($year) != 0) {
					$flag = 1;
					$month_num = $i + 1;
					$month_name = $month_list[$i];
					break;
				}
			}
		}
					
		if($flag == 0) { // if no date set, then use the default values
			$year = date('Y');
			$month = date('M');
			$month_name = date('F');
			$month_num = date('m');
		}
		
		$fields = array('id', 'name', 'DAY(event_date) AS event_day');
		
		$var = $this->Event->findAll('MONTH(Event.event_date) = ' . $month_num . ' AND YEAR(Event.event_date) = ' . $year, $fields, 'Event.event_date ASC');
		
		/**
		* loop through the returned data and build an array of 'events' that is passes to the view
		* array key is the day of month 
		*
		*/
		
		foreach($var as $v) {
		
			if(isset($v[0]['event_day'])) {

				$day = $v[0]['event_day'];
				
				if(isset($data[$day])) {
					$data[$day] .= '
' . $v['Event']['name'] . ''; } else { $data[$day] = '' . $v['Event']['name'] . ''; } } } $this->set('year', $year); $this->set('month', $month); $this->set('base_url', $base_url); $this->set('data', $data); } } ?>

Event Model


 array(
			'rule' => array('minLength', 2),
			'message' => 'Name must be at least 2 characters long',
			'required' => true 
										),
		'notes' => array(
			'rule' => array('minLength', 2),
			'message' => 'Please add some notes',
			'required' => true 
										),	
	);

}
?>

Calendar View


calendar($year, $month, $data, $base_url); ?>

events SQL


CREATE TABLE `events` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL,
  `event_date` datetime default NULL,
  `notes` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

CSS


/* calendar CSS */
 
table.calendar {width: auto; border: 1px solid #cccccc; border-collapse: collapse; margin: 0px; padding: 0px; background-color: #ffffff;}
table.calendar th {background-color: #eeeeee; text-transform: none; color: #444444; padding: 4px; text-align: center; border: 1px solid #eeeeee;}
 
table.calendar th.cell-prev {text-align: left;}
table.calendar th.cell-next {text-align: right;}
table.calendar th.cell-header {width: 70px; border-bottom: 1px solid #cccccc;}
table.calendar td.cell-today {background-color: #e2e8f6;} /* today in the current month */
table.calendar td.cell-weekend {background-color: #F3F5EB;}
table.calendar td {border: 1px solid #cccccc;}
 
table.calendar td div.cell-number {text-align: right; font-size: 8px; color: #444444; display: block;}
table.calendar td div {display: block; font-size: 10px; text-align: left;}
table.calendar thead th {border: 1px solid #cccccc;}

To Do List

I’m feeling a little less time poor at the moment and want to do a bit of work on this. If anybody has any comments or suggestions, please let me know. At the moment my plans are as follows (in no particular order).

  • add support for internationalisation
  • put the checking date checking (and possibly data array construction into a component)
  • add built in AJAX support (haven’t decided on jQuery or Prototype yet though)
  • look at using Cake 1.2 routes as part of date checking using regular expressions (how easy would it be to combine this with the internationalisation?)

Examples & Downloads

Check out the Working Calendar Helper Example