What’s better than riding bikes with the one you love?

Riding the same bike of course! We (mostly I) had been lusting after a certain recumbent tandem for sale locally, but the $2950 asking price was way out of our budget. Even if I had, through some miracle of haggling, gotten the price down another $500 or more, it still would’ve been about $2450 more than we could afford ;)

Luckily for what’s left of my finances, I happened across an ad for this:

The Norco "Cape Cod"

The Norco

So we rode out to the sellers home and had a look, took it for test spin (half attached fenders and all) and pretty much fell in love. The next day I rode the bus out, bought it, and pedalled it back to Recyclistas. A few hours of tuning up and swapping out a few components, and we now have this:

New bars, grips, saddle etc

New bars, grips, saddle etc

Before we ever rode it we did what every good bike nerd does, and read everything we could find on the internet about riding a tandem. After learning about the proper method and quite a few good tips from Sheldon Brown, we felt like we knew what we were doing. So far, there haven’t been any major accidents, and we can start and stop and turn with relative ease. We’re hoping to get to the point where we can use it for our camping trips. A few upgrades here and there and it will be at least weekend worthy.

Bike camping: Victoria to Salt Spring and back

After more than a year of procrastination the lovely Ms. Wallace and I finally got prepared -mentally and physically- to go on our epic journey: an overnight camping trip by bicycle.

We’d been working our way up to doing it by doing long(ish) day trips to Cordova Bay when it suited our mood, and that was getting progressively easier. As evidenced below:

Our bikes on the beach at Cordova Bay

Our bikes on the beach at Cordova Bay

So on the day of our journey we loaded up the bikes with panniers, tents, sleeping bags and pillows, and set off at 10am sharp (aka - 10:15ish). After some mental adjustments to compensate for the extra weight we got into a good pace and pedalled our way up to the Swartz Bay ferry terminal 40km from our house. We arrived at the ferry terminal with enough time to free Willy before the 13:00 ferry to Fulford.

not the most original, but incredibly funny when you don't know how tired you are...

not the most original, but still makes us laugh

We had a rest and stretched out a bit on the deck of the ferry, soaking up the hot sun and deciding that the mere 15km from Fulford to our campground near Ganges would be no problem. Brimming with confidence we planned out what to do after we set up camp and were ready to party in the village. Of course, there were a couple things we didn’t count on:

1. The highway on Salt Spring was not built with any thought given to cyclists, or pedestrians, or any form of transport that couldn’t deal with long steep hills by simply pressing the gas pedal down a little further.

2. It was very very hot. Over the 30 degree mark kind of hot. We should have realized this when we were sunning ourselves on the top deck of the ferry (which is a chilly place to be on all but the hottest of days) but we were feeling quite proud of ourselves…

So leaving Fulford there is a steep hill, we weren’t discouraged yet though, it’s a harbour, so of course it’s lower than everything else. By 5kms we had taken to walking up the longer hills, and by 7km our spirits were thoroughly destroyed. Some shuffling of luggage got us over a few more hills until the very last one, which we again took in the pedestrian style. Totally exhausted we set off to coast for as long as the downhill lasted, quite unsure that we would make it to Ganges intact.

I couldn’t find a map that properly depicts the descent into Ganges, but it was long and steep enough to convince me that the very small wobble in my front wheel deserves to be straightened out. Nothing is quite as exhilarating as trying to slow down a bike that’s the same age as you, carrying your body weight in gear, on a steep hill at high speed, when the front wheel goes “WAPWAPWAPWAPWAP” every time you use the brake…

So. We made it to Ganges dazed but unscathed (which is pretty normal in Ganges) and after a hellish 15 minutes of wandering back and forth across the busiest intersection in town, we descended upon the El Zocalo Cafe. We were rewarded with veggie gorditos, some cool drinks and a grilled veggie quesadilla. One nice thing about Salt Spring Island being a rich yuppie hideaway, is the fantastic food. For a place that appears on the surface to be yet another Mexican Restaurant, El Zocalo is really a step above. A short nap in the shade of a tree and we were ready to go find our campground.

Arriving, getting set up

Arriving, getting set up

The Garden Faire campground was really nice. It was quiet, the spots were reasonably private, and it really was only a 10 minute walk into town via some gorgeous paths. The campground manager mentioned that the pool across the road had a $5 drop-in fee, showers and a hot tub. We walked our bikes up to our spot and set up the tent. After determining that we had forgotten towels or bathroom supplies of any sort, we headed back down the office to look at the pool schedule. As luck would have it, the pool had already been closed 15 minutes. So we went back up to our spot, and stared at the trees for a while

After a sufficient grieving period, we unpacked some more. After that we stared at the neighbouring property where one lucky teenager was doing dirt jumps on mountain bike that probably cost the same my upcoming semesters tuition. Finally, we had recovered our senses enough to realize that we should really head into to town. As I mentioned the walk through the trees there is gorgeous:

The Mouat Park trail system is very nice.

The Mouat Park trail system is all that and a bag of chips.

Upon hearing the live music available at the local hot spot, we decided to walk around town a bit more. After walking around town a bit more we got bored and wandered back over by the music. Upon hearing the next band to be playing, we decided to get some munchies and wine and go back to our tent.

The snack spread.

The snack spread.

It turns out this was an excellent idea. Despite our best intentions, we never played any card games. After the hummus, chips, cheese, olives, chocolate and wine we went to bed. No sooner had we climbed into the tent than we noticed the faint yet unmistakeable sound of a live band butchering The Cure’s Close to Me. Rather than being an annoyance, it instead turned into a game of Name That Tune - Early 90’s Rock Radio edition. I don’t remember them all, but I do remember a Weezer song, and the grand finale of Teen Spirit before I fell asleep. It was all worth it when I woke up to see this though:

Good morning

Good morning

Since we were up early enough, we headed to the pool for the early bird swim. A rinse, soak, stolen squirt of Bronners Magic Soap (hooray for hi/yuppies!) and a final rinse and we were ready to face the world. After a quick stop to hang up our swimsuits to dry, we headed into town and found the place to be much more interesting when well rested. We ate breakfast at a lovely and wide open cafe/bakery called Barb’s Buns, picked up a few essentials at pharmasave, and waited for the thrift store to open. The thrift store gods smiled on me today, as I scored not only this awesome tank top:

It was only a dollar, and lot more comfortable than the long sleeves I had on.

It was only a dollar, and lot more comfortable than the long sleeves I had on.

… but under my arm there is a Colnago cycling jersey that doesn’t stink and only cost $7. I was pretty stoked to try that out on the way home.

Speaking of the way home, it was decided that cycling back to Fulford was a ridiculous idea that only a true masochist would consider and that we would instead take the bus. The bus may seem small and cute, but it moved us over the demon hills faster than my pride could say “hey you! be a man!”

The ferry ride back was uneventful, and we arrived in Sidney a little after 16:00, ready to ride the 40km back home. Actually, the ride home was uneventful as well, other than a couple times when Erin really put the hammer down and made me doubt I’d ever catch up to her.

We got home safe and sound much to joy/chagrin of our cats, and after a few more pictures it’s bed time.

Tent up, shoulders slouched

Tent up, shoulders slouched

This smile may have something to do with being exhausted

This smile may have something to do with being exhausted

Headed to town, hair still wet from the pool

Headed to town, hair still wet from the pool

Erin and her bike

Erin and her bike

Me not realizing that Erin has stopped

Me not realizing that Erin has stopped

A cool little windmill near Fulford Harbour

A cool little windmill near Fulford Harbour

And good night :)

jquery datepicker helper for cakephp

Here is a helper to insert a (much) nicer datepicker for datetime fields in cakephp. Depends on jquery, the jquery ui datepicker plugin, and the jquery time entry plugin.

First, the helper function:

/**
 Jquery DatePickerHelper
 */
 
class JqDatePickerHelper extends FormHelper {
 
	var $helpers = array('Javascript','Html');
 
	function beforeRender(){
		$view = ClassRegistry::getObject('View');
		$view->addScript($this->Javascript->link('ui/ui.datepicker'));
		$view->addScript($this->Javascript->link('jquery.timeentry.min'));
		$view->addScript($this->Javascript->link('date_picker_helper'));
		$view->addScript($this->Html->css('datepicker'));
		$view->addScript($this->Html->css('jquery.timeentry'));
	}
 
	function picker($field){
		$model = $this->model();
		$this->setEntity($field);
		$inputId = Inflector::camelize($model.'_'.$field);
		$output = $this->input($field, array('timeFormat' => '24', 'minYear' => date('Y'), 'maxYear' => date('Y') + 1));
		$html = '<div class="input datetime half '.$field.'">'
			. '<label>'.Inflector::humanize($model.'_'.$field).'</label>'
			. '<div id="'.$inputId.'Date" >'
			. '<label>Date</label>'
			. '</div>'
			. '<div style="float:left">'
			. '<label for="'.$field.'IgnoredTime">Time</label>'
			. '<input type="text" autocomplete="off" name="ignoremetime" id="'.$inputId.'Time" />'
			. '</div>';
 
		$onSelectExtraJs = ($field != 'start') ? "" : 
		"
		if(datePickerHelper.startsAfterEnd('#$inputId')){
			$('#".str_replace('Start','End',$inputId)."Date').datepicker('setDate', datePicker._getDate())
		}
		$('#".str_replace('Start','End',$inputId)."Date').datepicker('change',{minDate: datePicker._getDate()})";
 
		$extraConfiguration = ($field != 'end') ? '' :
		",
		beforeShow: function(input,datePicker){
			return {minDate: $('#".str_replace('End','Start',$inputId)."Date').datepicker('getDate')}
		}";
 
		$output .= $this->Javascript->codeBlock("
		$(function(){
			$('#{$inputId}Month').parent().css('display','none').after('$html')
			$('#{$inputId}Time').timeEntry({spinnerImage: ''})
			.change(function(){
				datePickerHelper.setHiddenTime(datePickerHelper.visible.getDateObject('#{$inputId}'),'#$inputId')
			})
			.timeEntry('setTime', datePickerHelper.getHiddenDateTime('#$inputId'))
 
			$('#{$inputId}Date').datepicker({
				mandatory: true,
				changeMonth: false,
				changeYear: false,
				yearRange: '00:01',
				minDate: new Date(),
				defaultDate: datePickerHelper.getHiddenDateTime('#$inputId'),
				onSelect: function(dateText,datePicker){ 
					datePickerHelper.setHiddenDate(datePicker._getDate(),'#$inputId')
					$onSelectExtraJs
				}
				$extraConfiguration
			})
		})
		");
		return $output;
	}
 
}

Not the prettiest implementation, but gets the job done. There’s some extra logic in there to make creating date-time ranges easier, by naming the fields ’start’ and ‘end’.

Next, the javascript file (to be placed in app/webroot/js/date_picker_helper.js)

datePickerHelper = {
	getHiddenDateTime: function(id){
		var year = parseInt($(id+'Year').val())
		var month = parseInt($(id+'Month').val())
		var day = parseInt($(id+'Day').val())
		var hour = parseInt($(id+'Hour').val())
		var minute = parseInt($(id+'Min').val())
		return new Date(year, month - 1, day, hour, minute, 0)
	},
	setHiddenDate: function(dateObject,id){
		$(id+'Year').val(dateObject.getFullYear())
		$(id+'Month').val(dateObject.getMonth() + 1)
		$(id+'Day').val(dateObject.getDate())
	},
	setHiddenTime: function(dateObject,id){
		$(id+'Hour').val(dateObject.getHours())
		$(id+'Min').val(dateObject.getMinutes())
	},
	startsAfterEnd: function(id){
		var start = this.visible.getDateObject(id)
		var end = this.visible.getDateObject(id.replace('Start','End'))
		if(start.getFullYear() > end.getFullYear()){
			return true
		} else {
			if(start.getFullYear() == end.getFullYear()){
				if(start.getMonth() > end.getMonth()){
					return true
				} else {
					if(start.getMonth() == end.getMonth()){
						if(start.getDate() > end.getDate()){
							return true
						} else {
							if(start.getDate() == end.getDate()){
								if(start.getHours() > end.getHours()){
									return true
								} else {
									if(start.getHours() == end.getHours()){
										if(start.getMinutes() > end.getMinutes()){
											return true
										}
									}
								}
							}
						}
					}
				}
			}
		}
		return false
	},
	visible: {
		getTime: function(id){
			var time = $(id).val()
			var hours = parseInt(time.substr(0,2),10)
			var minutes = parseInt(time.substr(3,2),10)
			var meridian = time.substr(5,2)
			if(meridian == 'PM'){
				if(hours < 12){
					hours = hours + 12
				}
			} else if(hours == 12) {
				hours = 0
			}
			return {hours: hours, minutes: minutes}
		},
		getDateObject: function(id){
			var visibleDate = $(id+'Date').datepicker('getDate')
			if(visibleDate == null) {
				visibleDate = new Date()
			}
			var visibleTime = this.getTime(id+'Time')
			visibleDate.setHours(visibleTime['hours'])
			visibleDate.setMinutes(visibleTime['minutes'])
			return visibleDate
		}
	}
}

So include like any helper, and in your forms do

echo $jqDatePicker->picker('datetime')

or whatever your database fieldname is.

if you’ve got troubles, comment here or find me in #cakephp on irc.freenode.net

Hint: cyclists are faster than you think

I was in an accident today, a pretty common type of bike/car accident that’s known as a “left cross

I was booking it (doing 40kmh or more) down a fairly busy street, and the oncoming car had slowed down and was signalling left. I was approaching the intersection to ride straight through when at the last possible moment, the car decides it’s going to proceed through intersection. I tried to slow down/stop and get around the back of the car but I couldn’t quite make it and clipped the rear passenger fender. I ended up going over the car and landing on my head and right shoulder. If I hadn’t been wearing a helmet I’d definitely be suffering from a severe concussion or worse right now. That bears repeating so…

Always wear a helmet!

Anyways… I’m picking myself up off the pavement while a very nice lady tells me she saw the whole thing and I had the presence of mind to ask her to get the license plate number. Luckily the driver didn’t flee the scene and she actually came with me to the police station to file the report. She was a sweet old grandmother who really shouldn’t be allowed/required to drive a half ton of steel around, but that’s yet another post. After that it was off to the hospital to wait for a few hours while they establish that nothing is broken, and yes I will be sore for a while. I’d be a lot less worried if I wasn’t planned on packing up the majority of life over the next few days and moving it to Victoria, but if I am a conscientious recuperator this weekend it should work out all right.

To get back to the point, when driving (or cycling) in traffic, always be sure to gauge the speed of other traffic. As Irma (yes, her name was Irma) said: “I saw you coming but I didn’t realize how fast you were going, I thought I had plenty of time”

sometimes I ramble

I wish I were so eloquent in daily conversation…

but I keep switching destinations and never arrive.

ssh -X and screen

This is to serve as a warning and reminder for the next time me or anybody else runs into this problem:

I was trying to get X11 apps from a remote server to display properly on my laptop today and they couldn’t find the display. It was necessary to restart my screen session after logging in with ’ssh -X’

Unfortunately, this tunnel gets lost every time I disconnect and reconnect, so I’m stuck detaching from my screen session to launch X11 apps…

Cha cha cha cha changes

It’s exciting times indeed. I’ve recently been accepted in to a university program that claims to combine my two biggest interests, music and computers. That the university offering this program also happens to be in the most beautiful part of the country is a big plus as well. Getting prepared to move out to the coast is pretty intimidating, but luckily for me I’m not going alone.

All this change is bringing on the self-reflection, especially regarding my attitudes towards university. I’ve often said I don’t have a lot of interest in post-secondary education (I had little enough in plain old secondary). The idea of paying money to have someone teach me how to program seemed especially bizarre when all the necessary reference material is freely available online anyways. For the most part I still feel that way, and this blog by Amy Hoy really struck a chord.

Lately I’ve been moonlighting doing web-design/development (as well as a couple of specialized internal applications) . I’ve gotten a very positive response to my work, and a couple more references to more work from every job I do. It’s the kind of thing that I would have been overjoyed to devote myself to a couple of years ago… so what’s changed?

The truth is I’ve gotten smarter, and the one thing I continually learn is just how much I don’t know. I feel like there’s a lot of things that I just don’t have the time to learn in-depth, and that makes it hard to be satisfied with the work I’m doing. I know it’s folly to think I’ll ever be 100% satisfied, it’s just my nature to strive for perfection in the things I create, but I know I’m way below my potential right now. The one big draw of going to university now is that I can focus on learning as my primary activity, not the thing I do after work.

Mister Mirror

The one conviction that you’ve ever held: that you’re faultless and deserving and they can go to hell. To make it all right you’ve got to prove them all wrong by sharing selfish insights in your stupid little songs…

Turn it on: show them why they’re wrong. There’s no need to question how you’ve got it all figured out.

Nina Simone

Preston Reed