...with a wheelset.
http://www.crankbrothers.com/wheel_cobalt.php
Those have to be the sexiest MTB wheels I have ever seen. Oh, and the technical aspects are pretty insane as well.
...with a wheelset.
http://www.crankbrothers.com/wheel_cobalt.php
Those have to be the sexiest MTB wheels I have ever seen. Oh, and the technical aspects are pretty insane as well.
Yesterday was the end of a good 3-day weekend which included race #4 of the DINO series; race #3 for me. It was the furthest south of any race of the series. And the course showed it.
If you've followed any of the weather that southern Indiana has been having, you know it's been very wet. And yesterday was no exception. At least half the course was wet not including the numerous water crossings. And since the lower classes run last, the course was as beat up as it was going to get all weekend.
Normally I wouldn't care if there was a little mud but, for me, it was a bit excessive. The mud wasn't a problem until my pedals got clogged up and I couldn't get clipped in. This was especially problematic on climbs or when I changed gears. Guess it's time for some Eggbeaters (http://www.crankbrothers.com/eggbeater.php). Also, since the Indiana soil contains a lot of clay, the course was very slippery around the water crossings. The tree roots, log crossings and bridges became especially treacherous.
Weather related track conditions aside, I would definitely recommend this course to any rider of moderate skill or higher. With drier conditions the course would have been perfect.
Notes on the race...
Things I need to work on: push-ups and crunches. After I got through the first lap, when I started to do a climb my lower back would start to scream. I attribute this to a lack of core strength. I know this because the couple of times I hunkered down and clenched my abs, my back hurt a LOT less.
Positives I can take away from this race: my legs are definitely getting stronger. The moderate climbs on the course, that I didn't slide out on, were perfect for me. I was able to stay in the saddle for most of them with only a slight (leg) burn. I also finished the race. It took me longer that I would have liked (sorry, Dana!) and I came in last, but as least I finished (http://www.dinoseries.com/2008race4-BeginnerMen.htm).
Here's hoping for drier conditions in New Castle.
Race #2 is finished and the standings are up (http://www.dinoseries.com/2008race2-BeginnerMen.htm) - 30th out of 32. Not very good I'm afraid.
The trails at Brown County State Park (http://www.in.gov/dnr/parklake/6725.htm) are a lot of fun but require a lot of stamina. That's because they have long downhill stretches that can be blazingly fast but require climbs that are at least as long. And since I'm not able to do longer rides (right now), I suffered tremendously.
The course started with us riding on about a mile of the paved North entrance to the park. Sounds easy right? Well, there's a section of this road that has to have at least a 30 degree incline! I did well enough on this section to not be last in my group and stay in the saddle but it took everything I had. In later climbs I had to hike to make it to the top.
Also, this was the first time I crashed during a race. Nothing bad, just a cut on my knee and some scrapes and scratches on my arm. I was going around a hill at a good rate of speed and my front tire got caught in the soft stuff. This normally wouldn't have been a big deal but it was right in front of a tree. Basically, my bike stopped and I kept going. Amazingly enough, I didn't have a bent wheel.
And to prove that I was actually there, a photo of me is up on the DINO site (http://www.dinoseries.com/photos/dinophotos.html). Click on the "2008 MTB Race 2" box, then click on the pause button - it'll make it easier to navigate. Now click on the "next" button till you get to the last page. There will be 3 photos. Click on the last one to load it. That's me on the bike! I just got finished saying bye to the wife and kids and am riding up towards the starting gate.
'Til next time...
It was a great day weather wise, if a bit too windy. The trails at Winona are pretty amazing. Nothing but single-track through mostly forest. I will definitely be doing this race again, hopefully doing a bit better next time.
I even had a cheering section. Right where the race ends, there's an opening so spectators can cheer you on. Dana and the kids were there, yelling "go daddy!" I decided to wave and almost crashed.
And if you're wondering, my bike didn't fail me this time. She's got a new chain and shifters that are well-lubed.
I can't wait for the next race!
PS. I just wanted to thank Erik again for getting us the Burley. It makes things like this possible and Jonas fell asleep in it!
So I've finally begun riding my bike to work; today marks the 4th straight workday. It feels good to be back on the bike even though I'm totally out of shape. I'm also hoping to do some racing this summer as well.
I guess I should mention that I attempted a race this past weekend at the DINO Series (http://www.dinoseries.com/mtb.html) Spring Tune-up. Suffice it to say that I did so poorly that I didn't even end up on the results list (http://www.dinoseries.com/2008-bike-tuneup-BeginnerMen.htm). I think the reason I'm not listed (#511) as a DNF is that I didn't even complete a single lap.
Not that anyone should be surprised. I had several things going against me. For one, I'm completely out of shape. Over the winter I was on the bike less than 10 miles. Second, my bike was in pretty rough shape. I couldn't shift the rear derailleur between more than a couple of gears and to top it all off my chain broke.
So I will continue to ride when I can from now on. We met the parents of one of my daughters schoolmates and apparently there are trails near where we live. Maybe this weekend I'll try them out. Lord knows I need the exercise.
Oh, and I can't wait for this idiot to get out of office...
I just ran into a little issue with the JSP EL. When you're accessing a property, say 'admin', the EL will choose the boolean type (isAdmin) over the string type (getAdmin). I know I shouldn't have named them that way but I wanted to at least document this behavior.
Anyways, follow all the steps from my previous post through step 4;
we'll be making a change to step 5.
First create a file called cvswrap.bat. All it needs to contain is the
following:
@echo off
setlocal enableextensions enabledelayedexpansion
%COMSPEC% /c %CVS_EXE% server
endlocal
From now on we won't be using the :local: connection method anymore to
connect to CVS, we'll be using :ext:. Basically, your CVS Root should
look something like:
:ext:username@localhost:/location/of/repo
username can be anything you like since it wont be passed to CVS
anyways. In the Checkout dialog the only other thing left is to have
NetBeans use an External Shell. Just put in the location of your
cvswrap.bat file and you're on your way.
YMMV
It's not a good sign when you see code like this in the project you were hired to maintain:
// Initialize the user history collection in case the // user changes his or her password during this session. user.getUserHistories( ).size( );
This is wrong on so many levels I don't even know where to start...
Just read about this on the Register. Should keep you toes warm on those cold winter days...
...and it runs Java too!
Since I've been working on the MS side of the fence for about 6 months now I thought I'd share some of the things I've seen.
MVC is pretty foreign to about 99% of .NET developers which I find rather insane. Good thing there are smart people like and Hammett, Ayende and JP. Of course there are good people working at MS. But to make this type of stuff work they have to create these huge frameworks and tools (Web Client Software Factory - it's open source though :).
Oh, and don't get me started with Visual Studio...
Not that anybody is listening, but I hope to blog a bit more often.
At work I'm working on rewriting a desktop app into a web app and of course it has to use Ajax to keep the feel. This app has several screens that contain data tables that can be filtered using a separate form field.
I first started building these tables by using the DOM completely, but that gets to be a little slooooow in IE, even on my 2gb dual-core laptop. To make things quicker, I would only load the data a page at a time and append new data if the user scrolled to the bottom. But that too was slow.
So I decided to start over. If you've taken a look at the LiveGrid widget from Rico you know what I want to do. Problem with the LiveGrid is that the table isn't selectable.
To start things off, you create the table (It's just a basic HTML table, I didn't have a week to figure out the CSS :).
<div> <table id="datatable"> <thead> <tr><th>col1</th><th>col2</th></tr> </thead> <tbody> <tr tabindex="0"><td id="row0col0">col1</td><td id="row0col1">col2</td></tr> ... <tr tabindex="0"><td id="rowNcol0">col1</td><td id="rowNcol1">col2</td></tr> </tbody> </table> <div id="scrollbar"> <div id="dataHeight"></div> </div> </div>
That's the basic table. The sample has only two columns to save space. Of note is the scrollbar and dataHeight divs. This is the scrollbar that will drive the table.
Here's some CSS for style:
div, table, tr, td, th, tbody, thead { padding: 0px; margin: 0px; border: none; } table { width: 500px; float: left; border-collapse: collapse; border-width: 1px 0px 0px 1px; border-style: solid; } th { background-color: #ddd; border-width: 0px 1px 1px 0px; border-style: solid; } td { border-width: 0px 1px 1px 0px; border-style: solid; } #scrollbar { width: 20px; overflow: auto; position: relative; left: -4px; } #dataHeight { width: 1px; height: 100000px; } .datarow { } .datarowfocus { background-color: highlight; color: highlighttext; }
Ok, no big deal so far. To make this table work, you need to have a couple of javascript libraries, Dojo and Behaviour. The code was built using Dojo 0.2.2 so I'm only going to assume it will work 0.3.1.
Here's the code:
var tableRules = { '#scrollbar' : function(element) { element.onscroll = function() { // TODO make an ajax call to get new data for table generateContent(Math.round(element.scrollTop/20)); } }, '#datatable tr' : function(element) { element.onfocus = function() { dojo.html.setClass(element, "datarowfocus"); var index = 0; var counter = 0; for (var i = 0; i < element.parentNode.childNodes.length; i++) { // have to check the nodeType - firefox sees text nodes between // table elements (tr, td, etc.), ie does not if (element.parentNode.childNodes[i].nodeType == dojo.dom.ELEMENT_NODE) { if (element == element.parentNode.childNodes[i]) { index = counter; } counter++; } } selectedIndex = index; }, element.onblur = function() { dojo.html.setClass(element, "datarow"); }, element.onkeydown = function(event) { if (!event) var event = window.event; // IE var scrollBar = dojo.byId("scrollbar"); var singleRowSize = dojo.style.getContentBoxHeight(element); var pageSize = singleRowSize * 13; if (event.keyCode == 38) { if (selectedIndex == 0) { scrollBar.scrollTop -= singleRowSize; } else { dojo.dom.prevElement(element).focus(); } } else if (event.keyCode == 40) { if (selectedIndex == 14) { scrollBar.scrollTop += singleRowSize; } else { dojo.dom.nextElement(element).focus(); } } else if (event.keyCode == 33) { // pgUp scrollBar.scrollTop -= pageSize; } else if (event.keyCode == 34) { // pgDown scrollBar.scrollTop += pageSize; } } }, '#datatable td' : function(element) { element.onfocus = function() { element.parentNode.focus(); } } } Behaviour.register(tableRules); var selectedIndex = -1; function generateContent(row) { // this section takes the result of the ajax call and fills the table for (var rows = 0; rows < 15; rows++) { for (var cols = 0; cols < 2; cols++) { var element = dojo.byId("row" + rows + "col" + cols); element.innerHTML = "row" + (rows + row) + "col" + cols; // TODO implement empty rows when no data found } } // this is needed for ie because the table row will lose focus when you // click on the scrollbar to scroll - firefox keeps the focus on the table row if (dojo.render.html.ie && (selectedIndex >= 0)) { dojo.byId("datatable").childNodes[1].childNodes[selectedIndex].focus(); } } dojo.addOnLoad(function() { // load data generateContent(0); // set the scrollbar div to the same height as the table var scrollbarHeight = dojo.style.getMarginBoxHeight(dojo.byId("datatable")); dojo.style.setMarginBoxHeight(dojo.byId("scrollbar"), scrollbarHeight); });
There wasn't anything special about the javascript code that you couldn't replace Dojo or Behaviour with your favorite javascript library. You may have noticed that there's isn't any Ajax calls in the code, but hopefully with the comments you can see where it could be implemented.
Here's the complete file.
Enjoy!