Friday, November 30, 2007

Fixing the window resize event in IE

Anyone who has hooked into the resize event of the window object in Internet Explorer knows the pain - the event is fired twice for every single movement (once for horizontal and once for vertical).  To make matters worse, if you drag the window size it doesn't get fried twice at the end, it gets fired numerous times throughout the resize.  The result of this is that if you are hooked into the event and are resizing some other elements (and probably re-rendering them too), performance suffers and the page seems unresponsive.

Luckily there is a relatively straight-forward resolution to this:

Sys.Application.add_load(function(sender, args) {
    $addHandler(window, 'resize', window_resize);
});

var resizeTimeoutId;

function window_resize(e) {
     window.clearTimeout(resizeTimeoutId);
     resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}

Essentially you queue up the resize handling code, and then if the window resize occurs again, you cancel it, and re-queue it.  This keeps happening until the resize is complete, at which point, your doResizeCode() function is actually executed.

Recursively finding controls - where to start?

I love hearing about bugs and problems in components I have authored.  Most people hate hearing about bugs (I assume because they like to think they are perfect), but I like it because it lets me know that people are actually using components I have written, which is always rewarding to know.

I had a report on the CodeProject in response to the article I authored, Persisting the Scroll Position of child DIV's using MS AJAX about a client-side InvalidOperationException during page initialization.   The particular user was embedding my control in a user-control placing two of the controls on the page.  Because my control is an "extender"-type control, one of its properties is the control ID of the other control.  I then use a recursive FindControl method to locate the desired control:

protected virtual Control FindControlRecursive(Control root, string id)
        {
            if(root.ID == id)
            {
                return root;
            }

            foreach(Control c in root.Controls)
            {
                Control t = FindControlRecursive(c, id);
                if(t != null)
                {
                    return t;
                }
            }

            return null;
        }

 

The call to FindControlRecursive looks like:

protected internal Control Control
        {
            get
            {
                if(_control == null)
                {
                    Page page = Page;
                    if(page == null)
                        throw new InvalidOperationException("Page cannot be null");

                    _control = (Control)FindControlRecursive(Page, ControlToPersist);
                    if(_control == null)
                        throw new InvalidOperationException("Could not located the specified control");
                }

                return _control;
            }
        }

Both DIV's in the user-control were named "div1" - can you spot the problem?

_control = (Control)FindControlRecursive(Page, ControlToPersist);

How about now? The problem was I was starting to scan from the Page and all of its children controls - since both DIV's were named "div1", it was always picking up the first control! To resolve this issue I changed Page to Parent:

_control = (Control)FindControlRecursive(Parent, ControlToPersist);

In this case, the Parent is the web-control (or page) hosting the extender control. Lesson Learned: Always start scanning controls from your parent control, not anything higher up in the chain.

Monday, November 26, 2007

Don't store request variables in the ViewState!

I've been mucking around with (D)LINQ all week (this will probably be its own series of posts if I get around to it) and as a part of this, I've been reading a lot of blogs (no-thanks to Microsoft's lack of implementation demos).  Something I've noticed in a few entries is storing a variable available in the Requests body in the pages ViewState.

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            if (!string.IsNullOrEmpty(Request["id"]))
                Id = Convert.ToInt32(Request["Id"]);
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Controls.Add(new LiteralControl(string.Format("Id is {0}", Id)));
    }

    protected int Id
    {
        get
        {
            object o = ViewState["Id"];

            return (o == null ? -1 : (int)o);
        }
        set { ViewState["Id"] = value; }
    }
}

I can think of a few reasons why this is unnecessary:

  1. During any ASP.NET client-server interaction on this page, the exact URL will be used hence the data will always be available in the HttpRequest object
  2. Adds to viewstate (obviously) = increased transit size and time-to-serve
  3. Serialization/deserialization on every hit

Since it's available on every request, don't bother yourself with the viewstate, save a few lines of code and just grab it from the Request during the pages Load event:

public partial class _Default : System.Web.UI.Page
{
    int Id;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(Request["id"]))
            Id = Convert.ToInt32(Request["Id"]);

        if (!Page.IsPostBack)
        {
           // Do stuff...
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Controls.Add(new LiteralControl(string.Format("Id is {0}", Id)));
    }   
}

As an added bonus, the HttpRequest is available much earlier in the page lifecycle (before the viewstate) permitting initial events access to this (you would of course need to parse it much earlier too).

Monday, November 19, 2007

Apple Warranty's aren't so hot

I feel like every time I open my mouth about Apple something negative comes out. I try to be positive, I really do, but the reality is that experience after experience, I just don't have anything good today.

I came into my office today to find my MacBook revving its fan's at high speed displaying a folder with a question mark.  Rebooting only yielded a "click-click-click," classic HD failure symptom. Luckily nothing is important on this machine.  This raises the first myth I'd like to dispel: "Apple hardware is of higher quality than others."  FALSE! The truth is, Apple, Dell, HP, Lenovo, etc., all use pretty much the same hardware.  At the end of the day, they all have Intel processors, ATI/NVidia/Intel video cards, and Maxtor/Segate/WD hard drives, and they all share the same failure rates.

I was actually somewhat excited about this failure as it'd let me test Apple's support first hand.

My initial call was answered by a routing agent within a few rings, but upon routing, I waited on hold for 20 minutes.  I rarely wait more then 5 minutes with Dell.  Upon reaching a tech, I was asked for my first name, phone number, and serial number.  I was advised that I have a 1yr hardware warranty and that my 90 phone support warrantee had expired. "It's definitely a hardware issue," I said.  The Apple rep kindly replied "OK, well what I can do then is start a support incident [requiring your credit card], and if it turns out to be hardware, we'll refund your money."  I then asked what the next step would be and it turned out that for MacBooks, Apple does not offer advanced replacements or on-site technicians, rather you have to take it to an authorized depot.  This regardless of warranty type.

My experience at the depot (MIAD) wasn't much better - A tech came to take my computer, but upon trying to enter in the information into his system, he was unable to do so because of a system problem.  I waited for 20 minutes only to be told that "we'll enter it in later and send you the info."  Not wanted to leave my laptop without any type of receipt, I had the tech write down all his info on a business card. I'm told I they will have a part within 24-72 hours, and fixed within 48 hours after that, depending on their volume (ie: it could be longer).

So all in all, I'm not overly impressed.  Just for the sake of it, let's take a look at a "standard" warranty on a MacBook Pro versus a Dell Latitude:

Standard Features Dell Latitude Apple MacBook Pro
Phone Support Lifetime 90 days
Hardware Warranty 3yrs 1yr
Hardware Replacement Next Business Day advanced swap, 4hr and 2yr available 24-72 hours for parts + 24-72 hours for replacement, return to depot, no advanced swap available
Onsite Technician For parts deemed not "customer replaceable units" (CRU) Not offered

Wednesday, November 14, 2007

MS AJAX Sys.UI.DomEvent documentation missing keyCode property

If you've ever reviewed the JavaScript source code for some MS AJAX-based components like the AJAX Control Toolkit, you might have noticed the use of the Sys.UI.DomEvent.keyCode property in a number of places to handle keyboard input in controls.  I had recalled that there was also a charCode property on the same class, so interested in what the difference was, I headed over to http://asp.net/AJAX/Documentation/Live/ClientReference/Sys.UI/DomEventClass/default.aspx to take a look at the official documentation, but to my surprise, there was no keyCode property listed.

My initial reaction was that this was either an internal field or something that had been deprecated in the RTM, yet there are references to it in the target property too.  What I ultimately discovered is that this is a simple omission in the documentation.

Now back to why I was looking it up in the first place - what exactly is the difference between charCode and keyCode? Patrick Long has a blog entry at http://blogs.charteris.com/blogs/patl/archive/2007/07/04/keycodes-charcodes-and-asp-net-ajax.aspx that sums it all up nicely; charCode will return a value related to the character being pressed whereas keyCode is related to the key being pressed.  For example, 7 on the number pad and 7 on the QWERTY pad will return different keyCode values but the same charCode values.

Tuesday, November 13, 2007

Widescreen resolutions & DVI

One of our helpdesk reps reported an odd problem trying to setup a local workstation with 2 widescreens - when running in DVI, he couldn't get the horizontal resolution any higher then 1280 even though the monitor is optimized for 1400x900.

We're all used to fiddling with video card drivers to resolve these types of issues, but this one was a bit different because it required a monitor driver (when was the last time you had to install one of those?).  Slight side note, but generally speaking you should install the monitor driver because it usually ships with an color profile for the monitor which helps with replicating color consistently.

Before I attempted to install the driver for our Acer 1916W's, I figured I'd take a look at the drivers INF file to see if there was anything of interest to help resolve this issue, and sure enough, there was.

[DEL_CURRENT_REG]
HKR,MODES
HKR,,MaxResolution

[1280]
HKR,,MaxResolution,,"1440,900"

[AL1916W.AddReg]
HKR,"MODES\1440,900",Mode1,,"30.0-82.0,56.0-76.0,+,+"

The interesting line of course is the one proceeding [AL1916W.AddReg].  HKR is an identifier for "relative root", which in the case of the Acer driver is HKLM\System\CurrentControlSet\Control\Class\{4D36E96E-E325-11CE-BFC1-08002BE10318}\XXXX\MODES (the GUID is found at the ClassGuid property of the INF file).  You can see that the INF is adding in the supported resolution to the Modes key, allowing us to choose the correct resolution now!

Tuesday, November 06, 2007

Windows Live Writer is Here!

Finally, a Microsoft Blog publishing tool that works!

I have been trying to get Microsoft Word 2007 to talk with Blogger for some time now to no avail and to further frustrate matters, the beta versions of Windows Live Writer would not install on x64, but that has all changed now.

Microsoft has just released Windows Live Writer, and keeping up with everything else coming out of the Live BU lately, it seems just great!

If you're interested in trying Windows Live Writer, along with the rest of the Live software packages (Messenger, Photo Gallery, etc), you can grab them at http://www.windowslive.com/.

Monday, November 05, 2007

Paul Thurrott's "Inside Windows Server 2008"

Paul Thurrott has an interesting article on how Windows Server 2008 was developed - a short but recommended read: http://www.winsupersite.com/showcase/win2008_inside.asp

Thursday, November 01, 2007

Mac Trojan In the Wild

http://www.boingboing.net/2007/10/31/mac-trojan-in-the-wi.html

Maybe the guy in the Mac commercial shouldn't be so smug next time.