Compsoft Flexible Specialists

Compsoft plc

Compsoft Weblog Compsoft Website News Archive Privacy Policy Contact Us  

Monday, December 21, 2009

Dodging the browser's autocomplete when capturing the user pressing Enter

You often need your web page to catch when the user presses Enter, and most of the time you want to click a button or a link when they do this.

This is nice and easy in javascript, but the browser's autocomplete feature can get in the way a bit: often the user will start typing, see the autocomplete suggestions, tap the down arrow a couple of times to pick one, then press enter to pick it.

If your javascript kicks in at this point, that's probably not what your user meant to happen: they just wanted to select that item from the autocomplete suggestions - they didn't want to click the "Next" link just yet.

I posted a question on stackoverflow to see if anyone else had found a solution to this that was better than saying "press tab, not enter!" to your users.

No one had an out-of-the-box solution, but one user suggested tracking the user pressing the up and down arrow keys - they'd have to press these to get into the autocomplete suggestions.

Much as this seems like a solution made out of string and sellotape, it totally works! We need a few more tweaks (catching page up/ page down too; not doing anything in Opera because it already does it itself).

I've implemented this in jQuery and made it available on jQuery.com as the SafeEnter plugin.

You can use it like this, to click an element when the user presses enter:

$('#myTextbox').clickOnEnter(myElement);

. or you can handle the event yourself like this:

$('#myTextbox')
    .listenForEnter()
    .bind('pressedEnter', function()
    {
        // Do stuff
    });

To save you going hunting for it, the full code of the plugin's here:

//codesnippet:2e23681e-c3a9-46ce-be93-48cc3aba2c73
(function($)
{
    $.fn.listenForEnter = function()
    {
        return this.each(function()
        {
            $(this).focus(function()
            {
                $(this).data('safeEnter_InAutocomplete', false);
            });
            $(this).keypress(function(e)
            {
                var key = (e.keyCode ? e.keyCode : e.which);
                switch (key)
                {
                    case 13:
                        // Fire the event if:
                        //   - we're not currently in the browser's Autocomplete, or
                        //   - this isn't a textbox, or
                        //   - this is Opera (which provides its own protection)
                        if (!$(this).data('safeEnter_InAutocomplete') || !$(this).is('input[type=text]') || $.browser.opera)
                        {
                            $(this).trigger('pressedEnter', e);
                        }
                        $(this).data('safeEnter_InAutocomplete', false);
                        break;
                    case 40:
                    case 38:
                    case 34:
                    case 33:
                        // down=40,up=38,pgdn=34,pgup=33
                        $(this).data('safeEnter_InAutocomplete', true);
                        break;
                    default:
                        $(this).data('safeEnter_InAutocomplete', false);
                        break;
                }
            });
        });
    };
    $.fn.clickOnEnter = function(target)
    {
        return this.each(function()
        {
            $(this)
                .listenForEnter()
                .bind('pressedEnter', function()
                {
                    $(target).click();
                });
        });
    };
})(jQuery);

Monday, December 07, 2009

Using MSDeploy as a build task in TFS

MSDeploy is a new tool out by Microsoft that allows easy synching of files between servers. This can be used from inside IIS or just run from command line.

You can read more on MSDeploy here. Read MSDeploy's team blog. Nice article on using the msdeploy command line.

I thought I would share an actual use of the MSDeploy in our TFS build scripts. It also uses the XmlUpdate task from the MSBuild Community Tasks Project.

<Target Name="AfterDropBuild">

<!--
Update web.config to be in release mode -->
<XmlUpdate XPath="/configuration/system.web/compilation/@debug"
XmlFileName="$(DropLocation)\$(BuildNumber)\Release\_Published
Websites\Site\web.config
" Value="false" />

<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Message="Deploying Website"
Condition="'$(IsDesktopBuild)'!='true'" >
<
Output TaskParameter="Id" PropertyName="InstallerStepId" />
</
BuildStep>

<
Exec
Command='"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
-verb:sync
-source:contentpath="$(DropLocation)\$(BuildNumber)\
Release\_PublishedWebsites\Site"
-dest:contentpath=\\SERVER\Websites\Site
'
ContinueOnError="false" />

<
BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Id="$(InstallerStepId)"
Status="Succeeded"
Condition="'$(IsDesktopBuild)'!='true'" />

<
OnError ExecuteTargets="DeploymentFailed" />

</
Target>

<
Target Name="DeploymentFailed">
<!--
Called if deployment of the web site fails -->
<
BuildStep
TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Id="$(InstallerStepId)"
Status="Failed"
Condition="'$(IsDesktopBuild)'!='true'" />
</
Target>

Labels: , , ,