Compsoft Flexible Specialists

Compsoft plc

Compsoft Weblog Compsoft Website News Archive Privacy Policy Contact Us  

Wednesday, January 27, 2010

Using javascript to put the cursor at the end of a textbox

All too often with software development it's the feature that seems the simplest that takes the most time to implement.

We had a <textarea> on a page that typically contained a lot of text. The customer wanted that textarea to have the focus when they arrived at the page, with the cursor at the end of the text ready for them to type some more. If there's enough text in the box for the vertical scrollbar to appear, we'd need that to be scrolled to the bottom too.

"Sure, no problem!" I said, thinking this would take about five minutes to implement. It was more like two hours of research and wrestling with browser compatibility.

Let me save you two hours. Skip to the end and use my code, or stick around and share my pain.

The nicest way to position a cursor within a text input or textarea is to use the setSelectionRange function. This can also be used to select portions of text:

document.getElementById('myTextBox')
    .setSelectionRange(startPos, endPos);

Setting startPos and endPos to be the length of the text puts the cursor at the end. So far so good. Unfortunately, this is a non-standard javascript function, and some browsers doesn't support it - most notably IE.


Another method to put the cursor at the end is to replace the contents of the textbox with itself. Easy peasy with jQuery:

$(this).val($(this).val());

Unfortunately this doesn't work so well in Google Chrome: though it scrolls the textarea to the bottom, it leaves the cursor at the beginning of the text.


OK, so we use a combination of the two - use setSelectionRange if it's available, replace the text if not.


Now, though, we find that Firefox and Google Chrome won't have scrolled the textbox. That's OK - we can set the scrollTop property to a large value (a little dirty, but hey - it works):

this.scrollTop = 999999;

Phew! Job done, right?


Well no - there's still one little "unique browser feature" we have to account for, and not one you'd ever know about until you met it doing this sort of thing.


This bit of code should just work in all browsers that support setSelectionRange:

var len = $(this).val().length;
this.setSelectionRange(len, len);

If you're already saying "Ha! That'll never work in Opera!" then you're clearly too much of a cross-browser javascript-character-encoding genius to be reading this blog.


This will work fine if the textarea contains no carriage returns.


It turns out that when Opera measures strings (using .length), carriage returns count as one character. However, when it comes to setSelectionRange, they count as two.


This means that in Opera, the cursor will be positioned near the end, just not quite at the end - it'll be back by as many letters as there are carriage returns in total.


Ironically, Opera's perfectly capable of handling unicode characters just fine. You can mix Roman, Greek and Chinese characters in your textbox to your heart's content and Opera will count them consistently, no matter how many bytes each one takes to be stored. Press Enter though and all is lost.


This cross-culture check was an important one to make. If Opera had been counting characters for .length and counting bytes for setSelectionRange, things would have got a little complicated - you never know quite how many bytes will be needed to encode the most exotic character a user might one day need. As it's only carriage returns that mess us up, we know we can only ever be out by at most a factor of two. Thus we can just say this:

var len = $(this).val().length * 2;
this.setSelectionRange(len, len);

That will handle the worst case where the textbox contains only carriage returns.


A quick check to ensure that no browser minds us trying to go beyond the end of the string like this, and we really, truly, are all done now.


My only remaining moral obligation was to ensure that no one else had to reproduce this effort. I've bundled this all up into the PutCursorAtEnd jQuery plugin. The code for release 1.0 is as follows - tested in IE6, IE7, IE8, Firefox 3.5.5, Google Chrome 3.0, Safari 4.0.4, Opera 10.00, and probably safe in pretty much everything else too:

// jQuery plugin: PutCursorAtEnd 1.0
// http://plugins.jquery.com/project/PutCursorAtEnd
// by teedyay
//
// Puts the cursor at the end of a textbox/ textarea
// codesnippet: 691e18b1-f4f9-41b4-8fe8-bc8ee51b48d4
(function($)
{
    jQuery.fn.putCursorAtEnd = function()
    {
        return this.each(function()
        {
            $(this).focus()
            // If this function exists...
            if (this.setSelectionRange)
            {
                // ... then use it
                // (Doesn't work in IE)
                // Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
                var len = $(this).val().length * 2;
                this.setSelectionRange(len, len);
            }
            else
            {
                // ... otherwise replace the contents with itself
                // (Doesn't work in Google Chrome)
                $(this).val($(this).val());
            }
            // Scroll to the bottom, in case we're in a tall textarea
            // (Necessary for Firefox and Google Chrome)
            this.scrollTop = 999999;
        });
    };
})(jQuery);

Monday, January 11, 2010

ASP.NET 4.0 now 50% more SEO friendly

Okay, so I made that statistic up, but this post will cover some of the extra SEO related goodness Microsoft is including in the .NET framework.

I previously mentioned the Microsoft SEO Toolkit which helps find SEO issues with your site here.

Why is Microsoft including SEO features anyway?

For public facing web sites and web applications, visitors are the lifeblood that keeps their businesses flowing. Every visitor is a potential customer, and who doesn't love customers?

For most web sites, a high proportion of new traffic comes from search engines, so improving the relevancy of your site will lead to higher rankings in search results. This in turn leads to greater visibility and higher traffic.

SEO can be the difference between success and failure, and that importance is reflected in the changes made in ASP.NET 4.0.

So what's new?

1. Page.Keywords and Page.Description.

The Keywords and Description meta tags have traditionally been the first place to optimise your pages, in keywords you can offer a list of words relevant to the current page. Description is used as a short description of the page, search engines often show this as part of the listing in the results, so it's very important.

Whereas before you had to manually inject keywords and description into a page, you can now manipulate these directly via the Page class.

2. Permanent Redirects

Renaming links and removing old content that have previously been indexed can lead to an accumulation of stale links. Nothing turns visitors off like a big error page when they click one of your broken links.

One way to handle these broken URLs is to do a Response.Redirect to a working URL, this means the visitor gets a page which is good, but results in the search engine believing the link is still fine, which it isn't. The best way to deal with this is to use a permanent redirect so search engines know the page has permanently moved, this means it will index the new URL and remove any dead links.

.NET 4.0 introduces a nicer way with:

 1: Response.RedirectPermanent"("PathOfWin.aspx")

You can do this manually by returning the 301 status code yourself, but this is certainly a win for speed.

It also introduces the MVC method of:

 1: Response.RedirectToRoutePermanent("SomeRoute");

I'm sure there'll be lots more info on .NET 4.0 improvements to come in future posts.

Labels: , , ,