2011-04-28

4096 bytes is more than enough for everybody

Ever try to make an AJAX call from JavaScript, only to find out that your data is truncated at around the 4k mark? If so, you must be using Firefox 3. Although there is a workaround described here, it means you have to write extra, special code to check for a custom property to really get all the data.

You can test this problem using this QuirksMode page. The page notes other limits on Opera and the Macintosh version of IE, but on the current (v11) version of Opera, I was unable to duplicate it. I also don't have a Mac, so I couldn't verify it there, either. Only Firefox fails to copy the whole text block.

Apparently, this has been fixed in Firefox 4, but that's small consolation when you're tasked with supporting what people are actually using.

2011-04-21

Let me url that for you

Today's programming annoyance is brought to you by the .Net Framework.

If you add a style to an HtmlControl in code — for example, the list-style-image to a list item element — you might use something like the following:

control.Style.Add("list-style-image","none");

You might expect that the style element would contain "list-style-image: none;".

Apparently, you'd be wrong. The tag generated looks like this:

<li style="list-style-image: url(none);">

There is a workaround, but it depends on you being able to specify all list-style properties at once. Using the shortcut, this code:

control.Style.Add("list-style","none none");

will generate the expected HTML, unmangled (and set both the list-style-type and list-style-image properties).

Having list-style-image: url(none) may not make your page look broken, but it will result in a browser request for the file "none" and result in some excessive 404 logs on your server.

If you had an actual image and set it with control.Style.Add("list-style-image","url(imageName.jpg)"); the style would not suddenly get "double-wrapped" with the url() function. By wrapping your value with url() "just in case" you forgot it, Microsoft tries to protect you from yourself, and ultimately causes more headaches by preventing you from setting the style to a perfectly valid value.

2011-04-01

Hollywood's War on Christianity Now Using Aliens

I recently saw the movie Paul. It's a comedy about two young adult male British nerds who are realizing a longtime dream of coming to America to visit Comic-Con, followed by taking a tour of famous UFO sites in the US (like Roswell and Area 51). As they're traveling, they witness a car suddenly veer off the desert highway and crash. When they stop to investigate, they meet Paul, a rather foul-mouthed alien who has escaped government capture and is trying to get home.

The movie is pretty funny, with lots of nerd references — from Star Wars (the cantina theme being played in a trucker bar, a guy shooting out his CB radio as he murmurs "Boring conversation anyway") to Close Encounters (a spaceship landing at Devil's Tower, a large firework that plays the five-note theme) and Aliens (a character quotes "Get away from her, you b---", a line spoken by Sigourney Weaver in Aliens, to Sigourney Weaver's character in Paul). It is also full of bathroom and locker room humor that's so popular with the kids these days.

The part where it starts to dig at religion comes when, soon after meeting Paul, the Brits decide to pull their RV into an RV park. They are greeted by a young blonde girl, Ruth, who comments on how she'd like to travel someday but has never gone anywhere in her life yet. The conversation is interrupted by a gruff voice calling her back to the office/house for "PRAYERS!"

The next day, Ruth visits the Brits' RV, and she starts to reveal herself as what I like to call a "Strict Creationist" — someone who believes in the literal word of the Bible, that the Earth was created 4,000 years ago in a process that spanned six days, and that there is no possible way there could be "alien life" elsewhere, as we were all created in God's image. Paul, somewhat put out by this, emerges from his hiding place in the bathroom. After fainting (something of a running gag in the film), she awakens and tries to convince herself it was her imagination, until she sees Paul again. She then goes into a fit of hysterics.

Up to this point, it's not so bad. Hollywood loves its stereotypes, especially taken to extremes. An openly gay character will be extremely flamboyant; a character born in the Lone Star State will almost invariably be wearing a cowboy hat and calling every female "Darlin'". It's almost a foregone conclusion that an openly Christian character will end up being extreme fundamentalist.

To stop her fit and from denying his very existence, Paul does this "alien thing" where he gives Ruth all of his knowledge and experience, including memories of his galactic travels.

Here's where it starts to turn south.

Filled with this knowledge, Ruth decides that all of what she believed is wrong, decides there is no God, and she is free to swear and fornicate. She then spends the rest of the movie trying to swear (in a manner not completely unlike Captain Kirk trying to "fit in" to contemporary Earth in Star Trek IV). Paul does make a token effort at trying to settle her down and say his experience doesn't necessarily preclude the existence of God, but his comment is ignored.

Going from one extreme to another isn't completely out of place in a low-brow Hollywood comedy. But the telling scene comes at the end, when, in a very sober moment, Paul says he's sorry for destroying Ruth's faith. Her reply? "You didn't destroy me; you freed me."

That actually made me a little angry. This was not a comedic scene; it was said with all seriousness, like it was one of the morals of the story. Faith is confining, and a foul mouth and spread legs is freedom. The disdain for religion is reinforced when Ruth's father wishes him well by saying "God be with you", and Paul scoffs, "Yeah, whatever."

I know it's just a story, and I should really just relax. And, when it comes down to it, I do see fundamentalism to be rather confining. I believe God has created this whole universe and there are many wonders and possibilities we have yet to even discover; and refusing to acknowledge wonders God has created because you cling to your narrow interpretation of what you know of Him today is akin to wearing blinders. I just object to this assertion that immorality and atheism is automatically superior to religion. These things are never "free", whether you believe in God or not — not believing does not release you from the consequences. And I'm not just talking about "fire and damnation". Promiscuity can lead to unwanted pregnancies, diseases, lack of trust in relationships; foul language can lead to loss of respect.

But, I guess, if you really believe your existence is over and done in 80 years, even these "little" consequences don't mean much, either.…

2011-03-06

Bandwidth for February

We're getting closer. February's data usage clocked in at 213.98GB (196GB according to Comcast's meter). In addition to more and more shows on Netflix being delivered in HD, I did rebuild my laptop because of issues related to attempting to install the Internet Explorer 9 beta. Since I rebuilt and tried the IE9 beta again (to determine if my issues were in fact related to the new browser — they were), I ended up rebuilding twice. This meant downloading drivers twice. In addition to the software I downloaded for installation, I also had to download the games I had purchased on Steam, Games for Windows Live, and Impulse. (They were on a good enough sale for me to purchase them this way, but one of the reasons I dislike digital downloads is I am stuck with a long download process instead of just inserting a disc.)

February's usage may have been a little high due to an unusual circumstance (rebuilding a laptop and re-downloading software), but according to the online meter, I've already used 50GB for the first six days of March. (vnstat on my server is projecting a monthly usage of 244.46GB based on use so far.)

So I burned through a lot of monthly bandwidth. And I still haven't reinstalled everything.

On Comcast's data usage page is the following text:

Your Comcast High-Speed Internet service has a monthly data usage allowance of 250 gigabytes (GB). If you are wondering whether you are at risk of exceeding this 250GB threshold, you should know that the vast majority - around 99% - of Comcast customers use significantly less than 250GB per month.

I have to wonder if that is still true (since this was implemented back in 2008), and how long it will hold. I also wonder how long it'll be before I hit that cap myself. At least I know what to expect if and when that happens, from their FAQ:

What will happen if I exceed 250 GB of data usage in a month?

The vast majority - more than 99% - of our customers will not be impacted by a 250 GB monthly data usage threshold. If you exceed more than 250 GB, you may receive a call from the Customer Security Assurance ("CSA") team to notify you of excessive use. At that time, we will tell you exactly how much data you used. When we call you, we try to help you identify the source of excessive use and ask you to moderate your usage, which the vast majority of our customers do voluntarily. If you exceed 250GB again within six months of the first contact, your service will be subject to termination and you will not be eligible for either residential or commercial internet service for twelve (12) months. We know from experience that most customers curb their usage after our first call. If your account is terminated, after the twelve (12) month period expires, you may resume service by subscribing to a service plan appropriate to your needs.

Our practice for the past several years has been to call only our heaviest data users, and this practice remains the same now that the 250GB data usage threshold is in effect. We may change our practice but will, of course, provide notice to you of any change.

Will Comcast change? Well, there is this noncommittal statement in the FAQ:

Will Comcast ever revisit the 250 GB threshold and raise it in the future as bandwidth intensive activities become more and more popular?

We recognize that the Internet is constantly changing and we are committed to continuous improvement. We will continue to evaluate our policies to ensure we provide the best online experience possible. It seems reasonable to assume that this will change over time, as the Internet and our service offerings evolve, though we have not committed to doing so.

Considering Comcast's actions against Level 3 that are suspiciously harmful to Netflix, I would be surprised if they adjust their policy when most of my data usage does happen to be Netflix.

As much as I am loathe to suggest it, it may be time to look at Qwest's offerings.…

2011-01-18

Holding back features on the web

If I were to say there's a CSS 3 feature that all major browsers support except one, which browser would you guess is lacking?

The answer for today is Mozilla Firefox.

It has come up several times on my current project where we've needed to take a variable amount of information and stuff it into a limited space, where aesthetics demand we truncate the data instead of allowing an overflow or a word wrap. The typical way to do this is with an ellipsis, but at what point one should truncate the message is usually the result of guesswork. Checking to see if a string is over, say, 35 characters and cutting it off if it is may work in most cases; but because in a proportional font, the same number of characters can be different sizes depending on which actual characters are used, any fixed number will result in some data elements appearing too short, and a few appearing too long and wrapping or overflowing anyway.

Enter the text-overflow style. In a fixed div or span, setting style="text-overflow: ellipsis;" will cause the browser to truncate the contents with an ellipsis if, when, and where it is needed.

Except for Firefox. Since CSS 3 is still technically in "draft", the coders behind Firefox have decided not to implement text-overflow, despite it being on the bug list since 2005. Mozilla's own developer forum shows that Firefox is the only browser to not implement this to date.

Oddly enough, this is the second time Firefox has failed me recently (the first being a misbehaving feature that plays havoc with AJAX queries).

I found two solutions on the web. One is to use something called XUL binding. The procedure (described here) involves creating an XML document that describes the requested behavior, and then using a Mozilla-specific CSS directive to bind it to the element. Unfortunately, not only does this require another document, but it may conflict with the text-overflow style such that only one or the other will work, but not both. Also, following the comments in the bug, XUL appears to be going away with Firefox 4, and with text-overflow still not implemented, this workaround will work no longer.

The second solution uses the JavaScript library jQuery. The function (which I found at Devon Govett's blog), when applied to a web element, takes the text, recreates it in a clone of the element, starts truncating text as necessary until it finds text that fits in the element, and replaces the text in that element. It's not terribly efficient as it iteratively tests the text on each element, and if the element can change size you either have to update it manually or tell the script to constantly check the element and recompute; but it does do the job that Mozilla won't. Fortunately, we're already using jQuery, so adding an extension was a trivial task.

I don't know if it's some higher ground they're trying to take by not implementing "draft" features, but the fact remains, as an end user of browsers, to me, they appear to be stubbornly behind the curve.

2011-01-14

ASP.Net, Dynamic Controls, and ViewState, revisited

At my current job, we are encouraged to share tips and ideas with other developers. I thought it could be useful to demonstrate the problem of dynamic controls and ViewState and my solution (posted three years ago here), since it not only is a problem that could come up in our web development, but it provides a useful opportunity to review the page life cycle.

So I grabbed my sample code and opened it in Visual Studio 2010. The good news is, it still works as advertised. However, I wanted to demonstrate the problem along with the solution; so I removed all my "extra" code. I was rather startled to find that the old problem didn't manifest itself. When I typed in data to one control and clicked a button to add another, the first control retained all its data.

It seems that the .Net Framework got some improvements over the years. The first improvement is that it seems ASP.Net is far more consistent in naming controls that are added to the page at run-time. (Part of the original problem was, when a control was loaded on page load vs. later in an event handler, the dynamically-assigned ID would be different.) The second is, if a control is loaded later in the life cycle, it does actually go back to the ViewState and re-load any applicable data. (It used to be very unreliable in this regard.)

I did find that things were not all roses. If you add a bunch of controls and start removing controls from the middle of the list, control data would get lost. Also, if you delete controls in the middle of your list and re-add controls, the controls may get added in the middle of the list instead of the end.

The solution is much easier than it used to be:

  • Create a member variable to hold the list of IDs (or whatever data is required to recreate the control and its ID) — in this example, I'm using private List<string> _childControlIds to just store the IDs, since the control type and location is always the same constant.
  • Create a Page Load event handler that looks like this:
    private void Page_Load(object sender, EventArgs e) {
     if (!IsPostBack) {
      _childControlIds = new List<string>();
      addAField(null).InitializeNewControl(); //Optional - create a new control, and initialize its data
     } else {
      if (ViewState["ControlCount"] as string[] != null) {
       _childControlIds.AddRange((ViewState["ControlCount"]) as string[]);
      }
      foreach (string controlId in _childControlIds) {
       addAField(controlId); //Create an existing control with its already-established ID
      }
     }
    }
  • The addAField method looks like this:
    private CustomChildControl addAField(string fieldId) {
     CustomChildControl cc = (CustomChildControl)LoadControl("CustomChildControl.ascx");
     if (String.IsNullOrEmpty(fieldId)) {
      cc.ID = String.Format("CUST{0}", DateTime.Now.Ticks); //new control; create a unique ID
      _childControlIds.Add(cc.ID);
     } else {
      cc.ID = fieldId; //existing control; reuse ID
     } 
     this.CustomControlsPlaceHolder.Controls.Add(cc);
     cc.DeleteControlClick += new EventHandler(DeleteCustomControl);
     return cc;
    }
    Notes:
    1. It no longer appears to be necessary to add the control before setting its ID — the ViewState manager seems to pick it up just fine either way.
    2. The custom control in my example has its own delete control and fires an event, that this page subscribes to. Your implementation may vary.
  • The DeleteCustomControl method looks like this:
    private void DeleteCustomControl(object sender, EventArgs e) {
     CustomChildControl cc = sender as CustomChildControl;
     if (cc != null) {
      _childControlIds.Remove(cc.ID);
      this.CustomControlsPlaceHolder.Controls.Remove(cc);
     }
    }
  • The method to add a control (in my case, a button on the page) is simply:
    private void AddButton_Click(object sender, EventArgs e) {
     addAField(null).InitializeNewControl(); //Create a new control, and initialize its data
    }
  • And finally, a Page PreRenderComplete event handler (because it's late enough in the page lifecycle; PreRender itself may be sufficient for your needs) that sticks the control ID list in ViewState:
    private void Page_PreRenderComplete(object sender, EventArgs e) {
     ViewState["ControlCount"] = _childControlIds.ToArray();
    }

And that's it. Surprisingly simple.

I don't know at what point this changed (or if I even over-architected the original solution — a distinct possibility). This could be an improvement in .Net 3.5, or it could be something "fixed" in a service pack along the way. The only thing I can say for certain is this much simpler method works quite well in my admittedly simple example.

2011-01-01

2010 Bandwidth

I haven't been posting monthly bandwidth numbers, mostly to distract from the fact that the majority of my posts lately were the monthly bandwidth numbers, and that's just boring. But I haven't stopped keeping track.

2010 proved out what I expected. Since we got rid of paid TV, we have been relying on Netflix for the majority of our video entertainment. The use of this has increased over the year, as we've not only become more comfortable using the service, but the number of offerings of the service has increased as well. Add to this the fact that more videos are available in HD, and it's no wonder that my monthly data usage has only been going up.

There are also other items that account for the increase. A large number of file transfers to support our website design business accounts for some of this. Also, we bought a Blu-ray player that has the capability to stream YouTube videos, of which the kids have taken advantage as a substitute for more traditional Saturday morning cartoons.

The year-over-year view is rather dramatic:

The largest-use month in 2009 was surpassed by 75% of the months in 2010, and the second-highest month of 2009 was exceeded by all of them. Comcast's measurement was consistently lower than mine, although they were only 8% off in December. It was November when, finally, we reached the halfway point of a monthly cap.

The numbers are likely to only go further up. I don't see any change in this trend. Content providers are continuing to innovate and use the bandwidth we have. Netflix's increase in HD offerings is one example. Microsoft recently updated the Xbox to use a higher quality encoding for voice communication, which, although only provides a modest increase in bandwidth, is just another example.

All this still leaves me wondering, when will general use and content innovation use up this arbitrary data cap, and turn the number of "excessive" users from what was once claimed to be "a single percent" into the majority? I also wonder if Comcast's policy of punishing those who go over their monthly number will change before or after that happens — or, more cynically, how much revenue they'll collect from fines before they consider changing their policy.

2010-10-28

Thoughts on document reader software

A document reader program should be unobtrusive. When you get a document on your computer that it is supposed to handle, you should just have to double-click on the document, and your operating system should open the associated program. It should do this quickly, without a lot of fanfare. The document is the focus of the user's attention, not the program. There should be nearly no need to open the reader program on its own, without a document; although, a link to the program in an appropriate folder on the Start Menu isn't uncalled for, should such a need arise (e.g., if the user wants to manually check for updates or change default settings for the program, he shouldn't have to find an irrelevant document to open first).

To these points, I say:

Adobe, quit installing an icon to Acrobat Reader on my desktop, without asking, every time you do an update; get rid of the bloat that causes Reader to take half a minute to open a document (running a service or pre-loading half your program into memory when I haven't even opened a document yet is not an acceptable option); and when I say "disable the splash screen", do not ignore that setting or re-enable it and think I won't notice.

Yes, I'm aware of alternatives, such as Foxit Reader, that aren't nearly as bad; unfortunately, I have to keep Acrobat around for those forms and bills that alternatives aren't able to process.

2010-10-24

IntelliMouse Explorer 1.0 in Windows 7

I have an old IntelliMouse Explorer. It's the original version, wired, but still works great. Alongside my Natural Keyboard Pro, it's an old, functional, comfortable piece of hardware that I refuse to get rid of. The replacements that have come along since often fall short in various ways. And, much like the Natural Keyboard Pro and other strong Microsoft hardware input devices from years gone by, Microsoft's software drivers have stopped supporting them.

There's no real reason for them not to work today. The keyboards haven't changed much, except to add or change the extra control keys sprinkled around the standard 121. Mice, even less so; they have the same X-Y directional input, five buttons, and a scroll wheel they've had for over a decade. But if you install the current version of IntelliType or IntelliPoint, they will refuse to detect your older keyboard and mouse; and even though the operating system will use them just fine for standard functions, all the fancy buttons and the ability to remap them (that used to work on older versions of the software) won't be available.

I came across this blog post on Blogfeld.com that describes in detail how to get a Natural Keyboard Pro to have full functionality in Vista and Windows 7. I followed these instructions earlier this month, and I can verify that they work flawlessly with the current version of IntelliType software (currently version 8). I thought maybe the same technique could be applied to get my old IntelliMouse Explorer to work with IntelliPoint 8 as well.

I won't post the details here — Blogfeld already does an excellent job at describing everything — I'll just indicate what I did to apply his technique to IntelliPoint.

I searched for an old version of IntelliPoint off of Microsoft's download site. You can still download IntelliPoint 5.2 from their site (link as of the time of this post is here, but you can search for "IntelliPoint 5" on download.microsoft.com to find it) and installed it on a Windows XP workstation in order to get the old files.

On the Windows 7 machine, I opened up the point64.inf file (IntelliPoint's version of IntelliType's type64.inf — and yes, I'm using 64-bit; the 32-bit version would naturally be point32.inf), and in the [MsMfg…] section, I added the following string to the block of IDs listed:

%HID\Vid_045E&Pid_001E.DeviceDesc%=HID_Filtr_Inst, HID\Vid_045E&Pid_001E

Further down in the [Strings] section, I added:

HID\VID_045E&PID_001E.DeviceDesc="Microsoft USB IntelliMouse Explorer (IntelliPoint)"

The next step was to modify the IPointDevices.xml file. This one required a little more thought, as IntelliPoint 5 did not have an IPointDevices.xml file to copy from. I noticed, however, that the IntelliMouse Explorer 3, which is supported in IntelliPoint 8, has the exact same configuration as the IntelliMouse Explorer 1. So, I found the <Device> section that describes the IntelliMouse 3, copied it, and pasted it to the end of IPointDevices.xml. I changed the <Name> node to read, simply, "IntelliMouse Explorer", changed the <OemAbbreviation> node to "IME", and changed the value under <HWID Type='PID'> to read "0x001E" (the last four characters of the USB ID, used in the point64.inf file above). I also had to change the ID in the <Device> node itself to something that was not used elsewhere in the file — '10' was good enough.

I followed the rest of the instructions from Blogfeld, and sure enough, it worked great. The configuration screen in IntelliPoint uses the images of the IntelliMouse Explorer 3, and it allows configuration of all five buttons and the scroll wheel, including per-application settings, like any other mouse it "officially" supports.

2010-10-20

Firefox + Ajax + Refresh = Disaster

Usually, when coding a web page that's targeting users of IE and Firefox, the browser that's going to cause the lesser amount of problems is Firefox. So I was genuinely surprised when I came across a bug reported for Firefox only that came down to what I consider the browser misbehaving.

The requirements for our app included a series of dropdown boxes, where the selection a user makes in one dropdown drives the choices that appear in the next one (what's commonly referred to as a "cascading dropdown"). For a nicer user experience, this is typically done with AJAX, so that the request/response that generates the second dropdown upon selection of the first doesn't require an entire page refresh. ASP.Net makes this really easy with the UpdatePanel control. Controls inside of an UpdatePanel can be refreshed without reloading the entire page. It's not as lean as a pure AJAX call could be, since the server reprocesses the whole page, but the coding time is greatly reduced.

Our environment includes a standard master page that includes a ScriptManager component (required for using UpdatePanels) and the following script:


<script language="javascript" type="text/javascript"> 
    function onEndRequest(sender, args) {  
        ajaxPostBackButton.disabled = false;  
        var error = args.get_error();  
        if (error != null) {  
            window.location = "../errorPage.aspx";  
        }  
        var updateProgressPanel = $get("<%=this.UpdateProgressPanel.ClientID %>");  
        updateProgressPanel.className = "HideObject";  
    }  
    function onBeginRequest(sender, args) {  
        var ajaxPostBackButtonId = args.get_postBackElement().id;  
        ajaxPostBackButton = document.getElementById(ajaxPostBackButtonId);  
        ajaxPostBackButton.disabled = true;  
        var updateProgressPanel = $get("<%=this.UpdateProgressPanel.ClientID %>");  
        updateProgressPanel.className = "DisplayProgressLayer";  
    }  
    var ajaxPostBackButton;  
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(onBeginRequest);  
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest);  
</script> 

The script, in essence, binds a couple of functions to the AJAX start and stop methods that do this:

  • On start:
    • Disable the control used to trigger the AJAX call (this helps guard against double-posting)
    • Show a div that contains a "loading" animated gif to let the user know something's happening
  • On end:
    • Enable the control used to trigger the AJAX call
    • Check for an error, and if found, redirect the browser to the standard error page
    • Hide the div with the "loading" gif

Now, if the user makes a selection in the first dropdown, everything runs normally, and the second dropdown appears. If the user then presses F5 to refresh their browser, the browser reloads the page from its initial load state, i.e., with the first dropdown with the initial "Please select…" option selected, and no second dropdown.

At least, that's the way it works in IE. In Firefox, what I was seeing was, the first dropdown was getting selected to the option I had selected before I hit refresh, it was disabled, and there was no second dropdown.

Finding out why was no easy task. With the help of Firebug, I was able to show that, on refresh, neither the onBeginRequest nor the onEndRequest methods were being called, and those were the only places the dropdown's enabled state was being tinkered with. I could only conclude that Firefox itself was setting this state. But why, and how do I stop it?

A couple hours of internet searching on why a dropdown in an UpdatePanel would be disabled failed to yield any useful information. I did find one user complaining about Firefox repopulating form values with prior input on refresh; unfortunately, that user's request for how to get around it was met with a snarky response about how it was a useful feature of Firefox and how the user was mentally deficient for not appreciating it. Sorry, but when you're coding a web application that is trying to control the content of form values and states and react to changes, and the browser breaks all rules and changes those states without raising any events to react to, I'll have to go with the feature being deficient and buggy.

Coming at the problem the next day with a fresh set of search terms, I came across this blog post: Firefox refresh viewstate updatepanel bug hell!!! The post describes a more serious error that can occur with Firefox's mucking about with a form after refresh that got updated with AJAX. The solution, renaming the form's ID on every refresh, seemed a little more of a brute-force hack than I wanted, and he mentions it doesn't work well in a master page scenario anyway (which we're in).

The comments on that post, however, point to an article on developer.mozilla.org that describes the feature in more detail and, more importantly, how to turn it off. By adding the nonstandard attribute autocomplete="off" to the page's <FORM> tag, it suppresses this bothersome behavior and lets the page work as expected.

We're now determining if this action is something that should be done site-wide (add it in the master page's markup), as it could be an uncaught bug on other pages; or if it's something that should be done on a page-by-page basis, by adding this.Page.Form.Attributes["autocomplete"] = "off"; to the prerender event of any affected page.

2010-08-31

Raingutter Regatta racetrack

Regatta side viewAlthough I am not the Cubmaster anymore, I wanted to share this project. In the past, the Raingutter Regatta was a troublesome event. The kids enjoyed it well enough, but for raingutters, all we had were vinyl gutters. It was always a trick to get them elevated, so that the kids could stand and walk beside them, but keep them supported enough so they wouldn't collapse when filled with water. Also, the end caps just snapped onto the gutters, and they never formed a perfect seal; so someone had to be volunteered to keep a bucket filled so the gutters could be refilled as needed. While the kids deal with it well enough, you definitely notice a drop in enthusiasm when they have to wait for the adults to figure out how to shore up a gutter and refill it with water every couple races.

Last summer, I was the Cubmaster, and I got to the church early to start setting up the gutters. I thought I had a bit of an advantage over years past in that we had a new building that had a pavilion with picnic tables. The tables, I figured, would support the length of the gutters and keep them from folding. All I needed to do was support the sides.

As I was filling the gutters with water and trying to figure things out, however, I was blindsided by nothing short of a miracle. Our newly-called Webelos den leader had taken it upon himself to build the project you see in the picture above. (Click the picture to see a couple more images — unfortunately taken from my outdated cell phone.) He pulled up in his truck and asked me to help him unload this large boat from the back. He said he didn't want to say anything before, because he wasn't sure he could finish it in time. Indeed, he had just put some of the finishing touches on it that afternoon.

It was, to say the least, amazing. A length of PVC pipe, cut in half, formed the tracks, which were wide enough to accommodate the hulls of the boat kits we were using (which were simple styrofoam blocks — much lower tech than the Pinewood Derby cars, but much easier for the boys to cut and form on their own). The half-pipes were laid in the top of the wooden form of a large boat. (Last year, the boat did not have the sail; that was something he added for this year.) A drain hole was drilled in the bottom of one end of each track, with a standard rubber drain stopper plugging it up, so the tracks could be easily drained at the end of the night.

We had some minor problems with leaks — because he caulked it earlier that day, it didn't have time to completely dry and seal — but it wasn't anything we weren't used to. There was no worrying about gutters buckling or collapsing, and the legs were sturdy enough to keep it from going anywhere when it got bumped.

It certainly made my day. And the boys', too. That event was easily one of the most successful we had all year.

2010-08-25

I found Microsoft Phone!

Following up to this post, where I ponder what happened to a certain Microsoft software product that seemed way ahead of its time hit the market and disappeared with almost no fanfare.

At my new job, I just got my phone configured. It's an IP phone that plugs into an ethernet jack (and apparently draws power from that jack as well, as there is no other power cord), and once it connected and downloaded all its necessary updates, the IT guy walked me through some of the features.

He directed me to set up my voicemail account. He pressed the voicemail button, and a friendly-sounding, female, synthesized voice announced, "Welcome to Microsoft Exchange." He then gave me a quick overview of the features available, which included the ability to access my email from my phone.

It would appear that Microsoft Phone grew up, moved out of the house, and got a job in the corporate world.

It certainly has come a long way. One of the "cool" features he demonstrated was the voice-activated directory. He pushed "Directory", and the voice prompt asked for the name of the person to call. In his moderate southeast Asian accent, and in a relatively soft voice, he spoke the name of the coworker in a neighboring cubicle. Within a second, the computer repeated the name (which it got exactly right on the first try), asked for confirmation, and then proceeded to dial.

Later, when I set up my voicemail account (setting my own PIN, greeting message, etc.), I experimented a bit. One of the options presented to me was "Calendar". I chose that option, specified "Today" (at which point the computer told me I could just say "Calendar for today" at the main menu to get straight to this point), and the computer proceeded to read to me my appointments for the day.

The voice synthesis was very clear. While it could never compare to seeing the information on the screen where you could glance at any piece of information at will instead of waiting for it to be read to you, it was no different than, say, the difference between reading a book and listening to an audiobook version of the same. All of the commands were done by voice. At no time did I have to repeat a command that the computer didn't hear, nor did it misinterpret any command I gave it; and I didn't speak any louder or exaggerate my pronounciation when I gave my commands. Although, the whole interchange was a little slow, considering I had to wait at the end of each operation for the computer to give me a list of all the things I was "allowed" to say. (I would imagine that accuracy goes way up when the number of possible inputs is constrained.) It was still far easier than the laughable experience I had trying to use voice controls in Windows Vista.

I am a little disappointed that this product does not appear to be available for the home anymore. More than once, I've been away from home and wished I could have easy access to an email when all I had was my phone. However, I think they're probaby dead on in their target market. It seems like people are using their cell phones more than their home computers as their address books and calendars, so the need to "phone home" just isn't there. Those who do access email on the road tend to pay for a data plan for their cell phones, so they can scan through email visually instead of having it read to them linearly — a huge advantage on a home email account that may get email from hundreds of sources, most of it spam that gets through filters. On the flip side, business email accounts tend to be more business-focused (in my experience; YMMV), so hearing unread email can be less of an exercise in "sifting through junk". Also, providing a phone access path to check information means that all employees can access their personal accounts without providing or provisioning VPN accounts, company cell phones, data plans, etc.

2010-08-16

In B4 Unemployment

When I was "downsized", I got some severance pay in addition to my unused vacation time. Because of this, my unemployment benefits were due to not start until a few weeks after my actual termination date.

Today, I started my new job.

I had a few interviews that came down to a couple solid possibilities. Both were very good jobs, and I thought it would come down to a choice between them. While I was waiting to hear a final decision, I spent some time in prayer that I would be guided to the right job. Sure enough, I only got an offer from one company; the other told me my qualifications were perfect, but they decided to go with another candidate who they just "felt was a better fit".

I supposed I should be used to this by now, but I'm still impressed, and thankful, with how Heavenly Father provides a very clear path to what He has provided for me. The path may not always be the smoothest or the shortest, but it's always gotten me where I've needed to be.

2010-08-13

Friday the Thirteeneth Strikes Again

I got a notice in the mail a while back about a recall Toyota is doing on vehicles, including my Prius, for a possibility of floor mats jamming accelerator pedals. Now, I'm more inclined to believe this is more media hype than any actual problem, but as long as it's free, I have free time, and especially since they were promising a free floor vacuuming with the service, I might as well take the car in. So I made an appointment.

I left for the dealer this morning, and my wife promised to leave shortly thereafter in the minivan to pick me up. On my way in, though, I got a call from an upset wife. The van wouldn't start. The battery didn't have enough of a charge to turn it over. This was a new battery, one we bought earlier this year. It should not be dead. Unfortunately, it didn't agree.

Now, fortunately, we have a plug-in battery charger that we got many years ago, so she began charging it while I dropped off my car. Since she was going to be leaving a lot later, I walked over to our next stop, the FedEx center, to pick up a package from my former employer that had apparently already forgotten my correct address. A healthy dose of exercise and still a ten minute wait, and my wife drove by to pick me up.

We were going to get family pictures today, so we went to the shopping center. My wife wanted to stop by the shoe store to get new shoes for a couple of the kids first, so we pulled up there. The baby was still asleep, so I was going to wait in the van. She rolled down the windows and shut off the minivan. While we were unloading, though, the baby woke up. I went to start the car to roll the windows up, but all I got in response was "click click click click click". Despite the 40-minute round trip to pick me up from FedEx and come back to the shopping center, the battery had no charge. And now, we were stranded on the wrong side of the shopping center.

We hiked across the shopping center to get to our picture appointment. Fortunately, it was still morning, so it was not too warm yet; but it was still a decent hike with four kids, slightly uphill, passing a distance that included a full-size Wal-Mart and a Sam's Club (these are not small stores).

Once we got to our picture appointment (on time, even), we started trying to call the phone numbers of anyone we had in our cell phones to see who might be home and who might be able to shuttle one of us home to get jumper cables and to my mother's to pick up her truck.

Getting pictures done, we then went to get lunch at one of the nearby restaurants. While we were there, one of our church friends showed up to drive me to my house and my mother's. At my house, I got my mother's house keys, and then we went to my mother's house. Problem, the house key does not work on the storm door on her front door. It would've let me in from the garage, but I didn't have her garage door opener. We had one in the minivan, but she didn't pick me up from the minivan; she picked me up from the restaurant. (I'm not sure I would've thought to grab the garage door opener anyway.)

Fortunately, she was willing to let us try jump-starting off of her truck. We just had to go back to my house to pick up the jumper cables I forgot to grab. (I was going to pick them up after I got my mother's truck.) And, fortunately more, we weren't inconveniencing her much; through all the driving around, her daughters in the car were lulled into a nap they don't usually get, so she was getting a nice bonus.

Jump-starting the minivan was fairly uneventful, except for the usual problems of trying to get the clamps secured on the terminals and finding a good ground. Rant time: Why don't they make battery terminals longer, so that jumper cables aren't constantly in danger of slipping off the things? And, why don't they make an obvious grounding post for clamping the negative cable? The first place I clamped it was secure, but obviously not a decent ground, as it completely failed to start the car; as soon as I clamped it to a less secure but more obviously metal bolt, the minivan started right up on the first try. Rant over.

We thanked our friend profusely for the ride and vowed not to turn off the minivan for as long as we could. My wife followed me to my mother's, so we could grab her truck. (If we needed to leave the minivan behind while it got its battery replaced, we would need the extra vehicle to get home.) With the garage door opener in the minivan, this was a much easier trip.

We made a long drive to Sears, where we bought the battery, so they could check it out and replace it. Long story short, they were able to replace it while we wandered the store, so we were able to take the minivan home. They said it was in fact a bad battery, and everything else checked out ok. Unfortunately, this not only made the truck unnecessary, having the extra vehicle meant we were unable to simply stop by and pick up my car, which was already done and will now require another extra trip out to go get.

I'm not usually one to consider the 13th of a month falling on a Friday as being anything but a statistical curiosity, but it certainly seemed unlucky today.

Still, it all worked out in the end, and the worst of it was just inconvenience. Annoying, exhausting inconvenience, but just inconvenience.

2010-08-07

Land lines (and their owners) don't deserve to die

Cell phone "elitists" bug me. These are the people who insist that land lines or home phones are relics of a bygone era, and anyone who has a home phone are either simply wasting their money, or refusing to change with the times, or are somehow mentally deficient for not ridding themselves of a land line and going exclusively with cellular phones.

We know a handful of families that have ditched the land line and gone entirely with cell phones. (To their credit, they have been far from "elitist" about it.) Unfortunately, we have encountered some common problems trying to call our cellphone-only friends. These are based on actual, real-life experiences.

  • You have to double (or more) the number of phone numbers you have to know to call the family. You can't just call one number for the family, you have to know the number for the husband, and the one for the wife, and possibly the numbers for any children.

    • Published phone directories will likely not be set up for this and list only one number, which at best will be a 50:50 chance of belonging to the specific family member you wanted to contact; so unless you make a point of getting down everyone's number, you'll consistenly call one family member just to ask for the number of another family member. (While the first family member could simply hand their phone to the second, I've found it's more common they will request you call the second number, so the first phone is still free for calls that are actually for the first person.)

  • You don't know if they are home when you call, and you will end up reaching them at an otherwise inconvenient time (i.e., when they are out shopping, at work, running some other errand, away on vacation).

  • If you don't care whom you contact (i.e., you want to call the family to set up a visit, invite them to dinner, pass them some information about a community event, etc.), you end up having to decide whom you're going to contact.

    • The person you decide to contact will end up being the least convenient person, as they will end up being the one who is out of the house (as above), greatly raising the chance any information you wanted to convey to the family will be long forgotten by the time said person returns home.

  • The cell coverage in the neighborhood isn't great, and the call will end up sounding like tin cans and string (when it's not dropped). This seems to be especially true in our "outer suburbian" neighborhoods, and even more so near certain schools.

  • Even when the desired person is at home, and assuming their phone is getting enough reception, it is not uncommon for someone to misplace their pocket-sized device, or not hear the single ringing phone from elsewhere in the house; and they can easily miss the call for being unable to hear or find their phone in time.

While I could possibly see this working more for singles or couples, it just doesn't make sense to me for families. In order to allow your children to make or receive phone calls at all, you either have to yield "your" cell phone, or shell out the money for their own.

I understand why some people do it. The families we know that have gone to cell phones have done so to save money, and to get away from endless telemarketing calls. Those are certainly appealing reasons — we easily get three times as many unwanted calls on our land line as calls we actually want to take. But in practice, it just makes calling a family unnecessarily complicated, and they are just problems we'd rather avoid. It's not a waste of money, and we're not stupid or living in the past.

2010-07-15

On the Job Hunt

At my place of employment, once a month, we had a "one-on-one" with our boss, a scheduled time where we could talk about how work was going and such. In my most recent one this month, I expressed my concern that the work I was doing was not being recognized or appreciated. The project I had originally been hired on to work on was basically shelved seven months ago (despite the new feature release I had built last year, the special on-site trip I made to a client's site on its behalf, and my work in getting it through Microsoft Certification), and all the work I had been doing on the company's flagship product since then was going unmentioned and undemonstrated at trade shows and in press releases. My boss assured me that my work was important, that it was bringing the product and the company further than it had ever been in years.

Turns out, I was right. Yesterday, very suddenly, I was told I was being let go. The Powers That Be had decided, as a cost-cutting measure, to completely eliminate the project I was hired on for, and, since I was tied to that project (despite the fact that I hadn't worked on it this entire year, except to get it the aforementioned Microsoft Certification, which was done as a cost-savings measure since it would get the company free OS/software licenses), my position was also being cut.

There were so many things I wanted to say, so many arguments I wanted to make, but the decision had already been made without discussion. My boss, who told me the decision was not his, had in his hands my final check and the termination agreement dated for that day. I knew nothing I would say would make the least bit of difference one way or the other. All I could think was that I have a wife and four kids at home, and attempting to say anything would only lead to a useless discussion that would delay my inevitable departure and keep me from finding my next job so I could make sure my family was provided for.

I am tempted to write more, to rant about how I think it's unfair or how I think it was a bad decision (not just because of how it affects me personally); or I could pine for the things that have been taken away from me, the conveniences I had working there; but really, what would be the point? Nothing changes the fact that I need to get my résumé up-to-date and off to recruiters so I can find my next job.

2010-06-24

Installing software: Linux vs. Windows

I wanted to install the MySql Workbench on my Linux development box. My experience only reaffirmed my position that, despite the many advances made over the years, Linux still isn't quite ready for the masses. I list these steps and problems here, not as a list of what could happen, but as a list of things that actually happened to me at least once during this process.

Although MySql Workbench is the product in question here, this could really apply to any piece of software (and, as noted, did apply to more than one of the libraries I had to try to install in the process).

  • First, I went to the download page for MySql Workbench. They had several packages available, but none that corresponded to my particular version of Linux (CentOS 5.5, roughly equivalent to Red Hat Enterprise Linux 5.5). So, it seemed I was bound to compile from source.
  • I downloaded the source package, unzipped it, and ran ./configure. It proceeded to run a bunch of checks on my system, ultimately stopping when it could not find a certain library it considered critical. I checked the package repository (using whatever GUI front-end to "yum" that comes with CentOS), and found it. Although I did have the library installed, I didn't have the library-devel package installed, which I guess is required for compiling programs against it.
  • Development package installed, I ran ./configure again. And the check immediately after the previous library, it failed to find another critical library. Ok, go back to the software installer and… oh dear, it's not there. Search the internet, find a package for RHEL5, and install it.
  • Run ./configure again. Another library missing. Not in the package installer. Search the internet. No pre-compiled package this time; download the source code. Install library from source. (n.b.: This, and any other time I have to "install from source", means going through this whole series of steps/possibilities for that library. And yes, a library can have a dependency on yet another library [or series of libraries] that I have to go find and install, etc.)
  • Run ./configure. Wait, it says the library I just installed isn't installed. locate library; it's in /usr/local/lib instead of /usr/lib. Figure out how to configure pkg-config to include the other directory.
  • Run ./configure again. Another library problem — the version I have installed is too old. Newer version not in the package installer. Search the internet. No pre-compiled package. Download source. Install library from source. Run ./configure again. Still reporting library is too old. Attempt to remove old library from software manager; decide against it when software manager decides it wants to remove a host of other packages that depend on the existing one (as it is unaware of the newer version I just installed). Find the files that tell pkg-config what's installed, and remove the entries for the older version, so it won't see those before it sees the newer version. (n.b.: I discovered I could do this more easily by telling pkg-config to look in /usr/local/lib first, and /usr/lib second.)
  • Run ./configure again. Another missing library. Not in the package installer. Search the internet. No pre-compiled package. Download source. Attempt to compile library from source code, get an error. Search the internet. Find that someone has submitted a patch for that problem. Apply patch. Compile and install library.
  • Run ./configure again. Configuration completes. Attempt to compile. Get errors about missing symbols. Go online, find a reference to the problem and an invitation to join an irc chat room for support.
  • Install irc client and join chat room. Told that the version of Workbench is out of date, and given a link to the next version.
  • Go to link. Binary package is available — for RHEL6, not 5. Download the source. Run ./configure. Find another library that's too old. Download updated library, and updates of the libraries it depends on. Compile and install.
  • Run ./configure. pkg-config finds the updated version of the libraries, but the next check finds the old version, and demands that I uninstall the old version. Decide against it when I see that attempting to uninstall it from the package manager will uninstall over half of the packages on my system.
  • Decide to throw caution to the wind and download the RHEL6 binary package. Software installer complains that it depends on libraries I don't have and/or have old versions of, and it can't automatically find (including an updated version of some of the MySql database files themselves, which I could not accept, as I have to develop against a specific version of the database to provide accurate support); and it refuses to install.
  • Go to MySql download site. Download Windows version of Workbench to Windows workstation. Double-click installer. Enter connection credentials to database running on Linux. Connect successfully.

I like the idea of Linux; I really do. There are limitless possibilities with it. And I am reasonably confident that, if I ever did get this software installed, I wouldn't need to worry about it again. I have a Linux server at home that took me several days to set up, but once I got it running, I've rarely had to touch it. And on the occasions when I do decide to update it, it works pretty magically.

But when it takes two days of my time to attempt to install a utility — and ultimately failing — when I can do the same task (and succeed) on Windows in less than ten minutes (with most of that time spent downloading the file I want), sometimes I wonder if it'll ever make a viable replacement for an OS that, despite all its problems, most of the time "just works".

2010-06-15

A 400-Pound Doorstop

I woke up Sunday morning to my wife asking me for the password to my laptop, so she could put on a DVD for the toddler; and said toddler explaining in great detail how the TV doesn't turn on when you press the button. The TV had served pretty well for 9 years, but lately it had been showing signs of decay — the lower-left corner was perpetually out of focus, the image would very slightly and very occasionally "fuzz" for just a second), but it had finally given up the ghost.

On the one hand, I had hoped it would survive long enough for 3D technology to mature and become the "standard". On the other, if it's going to die, the week leading up to Father's Day, with the corresponding retail sales, isn't a bad time to do it.

Yesterday, we went out to a certain big electronics store known for blue and yellow polo shirts and compared TVs. Because of where we were putting the TV, we had a fixed size limit. A 50" might have barely fit the space, with a fraction of an inch to spare, but we didn't really want to cut it that close — the kids would be bumping it into the walls with reckless abandon. LED screens did provide a sharper, higher-contrast picture than the plain LCDs, but the technology is still new enough that the price difference was pretty large. In the end, our eyes were drawn to the Samsung models, especially since the quality of the LCD model was quite comparable to the LED (and both models seemed to outshine other brands, both LED and LCD).

Long story short, we brought home the reasonably-on-sale TV and the not-on-sale mount, and paid for Best Buy to come and recycle the old TV. I had figured we would wait for them to remove the old behemoth before we installed the new one, but my wife was insistent on installing it immediately. (Excited for the new TV, or desperate to entertain the kids — you make the call.) We were less than gentle in rolling the old TV out of place (what are we going to do, break it?) and managed to get the new one set up with a minimum of finger-smashing incidents.

We hooked it up to the DVD player and the Xbox, and I spent a little bit of time viewing the videos from E3 and playing the game that happened to be in the disc drive before going to bed. I have to say, it was like getting a new pair of glasses. Everything is much brighter, sharper, clearer, easier to see. I used to complain about the Xbox dashboard and being unable to read the dark-grey-on-light-grey 6-point text (especially since it fell in the out-of-focus area on the old TV), but now, even though I still think it's a less-than-optimal color scheme, I have to say it's insanely easy to read when the letters actually have edges. The game, too, was exceptionally clear and sharp.

The only down side? (Well, besides the knowledge that 3D is coming, and it probably won't be too long that I'll find myself a generation behind again.) My wife wants a blu-ray player to go with it now.

2010-06-05

AT&T showing how data caps stifle services

AT&T is making news for announcing the end of its unlimited 3G wireless data plan. While those who are currently on such a plan can keep it, no one getting a new plan will have "unlimited" even as an option. The reason this is such big news, of course, is because Apple has an exclusive contract with AT&T to provide service for all iPhones and iPads.

I'm not going to debate the popularity of Apple's products, mainly because I don't understand it. I've owned a Tablet PC, and the iPad does less, by design. The iPhone doesn't do any more than a lot of other phones out there. Both devices are locked into Apple's closed and tightly-controlled environment and its single, exclusive service provider. Despite all that, the fact is, the devices are very popular and very hyped. And because of that, people take notice.

Because of the iPad's popularity, media companies are actively looking at streaming more data to these devices. Major media companies have apps for the devices, Netflix can stream movies to them, and more are coming.

And now, AT&T has essentially put a limit on these new services, saying you can only use 200MB or 2GB (depending on your plan) a month.

That number seems extremely low, but how much is it really? There's an article on Clicker.com, titled How Much Video Can You Actually Stream With AT&T’s New Data Plans? that calculates the numbers with real-world data.

Unfortunately, I can't tell if it's high or low. I don't have a data plan personally, as I find them too expensive to deal with and am usually close enough to a PC with a "real" internet connection throughout most of my day. There have been times, though, that I've wished I've had it, but for the most part, it's been a convenience I've been happy enough to live without. (As an aside, I have a Zune with me often, and it can use Wi-Fi when available. However, I have almost never found a convenient open Wi-Fi access point when I need one. So, I find the claims that these new limits won't affect anyone because "open Wi-Fi is everywhere" to be laughable at best, and downright insulting at worst.)

If I were in a position where I had more roaming downtime, such as when I worked downtown and took the bus or train in to work every morning, I could see making a lot of use of 3G services. However, because I drive myself to work, and I work on a computer all day, I think I might end up being one of the "unaffected" lot, finding that my actual usage was well below the cap.

Interestingly enough, though, the measurements only take into account active usage. Sometime soon, the next iPhone OS will be released, and it will allow for multitasking, so that services can be running in the background. What happens when people suddenly have the ability to stream music over 3G in the background while they're doing other things? Data usage will no longer be active, but it'll be racking up passively in the background. Will 200MB be enough then?

2010-06-01

May Bandwidth

In84.90 GB
Out6.38 GB
Total91.29 GB
Comcast's measurement75 GB (-16.29)

Another exciting post in my most consistent blog posting to date. I've noticed that, although SpeedTest.net seems to still report a fairly consistent rate, things in general don't seem quite as fast as they used to be. Netflix movies have a tendency to go "blocky" a little more frequently; YouTube videos don't always download faster than they play back; even Xbox Live updates, which used to download in a couple seconds, seem to take close to a minute to download now; and games don't always report my network status as "green". Not sure what the problem is, or if it's just my perception — from the accounts I've read, even though it took me a couple hours to download the Halo Reach beta from overloaded servers, I still got a better connection than most.

Not that I wouldn't welcome a little competition around here to help keep Comcast on their toes. O FiOS, where art thou?