Compsoft Blog

  • iPad, Glorious iPad

    Thursday, April 08, 2010

    Shipped from the USA, our iPad has been in the office for 27 hours or so... well, nearly. The MD took it to a meeting yesterday afternoon and then home and played in to the small hours with it. And now it has gone to another meeting. Interestingly, the meeting yesterday was about the development of an Android phone app, but that quickly got forgotten as the iPad stole the limelight.

    I had the pleasure of spending some time with it this morning, looking over it with colleagues and have received a variety of opinions:

    The Sales Team: they loved it. It is a tactile thing that wants to be used, to be touched, to be seen. They can see that putting it in front of customers with their iPhone / iPad app on will blow them away. I guess the telling sign is that all bar none have expressed their desire to get hold of an iPad.

    The Support Team: the only comment required is that as I left the Head of Support was on the phone to his wife, currently on business in the USA, asking her to get to an Apple Store! (Update: she is on a waiting list!) (Update #2: Wife was able to pick up 64GB iPad; Head of Support uncontrollably happy!).

    Design Team: in spite of expressed concerns our Senior Designer 'loves it'. The slickness of the interface has impressed him, and he too sees how clients will love seeing their imagery in a fresh crisp view. He was exploring how he could justify to his wife the purchase!

    Development Team: it shouldn't surprise that their view focused on its gaming potential - the additional control that the larger surface offers over the much smaller iPhone was evident as a Senior Developer demolished a tower in 'Angry Birds'. When questioned, the dev team confirmed that they would rather build for iPhone / iPad (iPad using a similar development framework to iPhone) than for other mobile platforms.

    The client: I took the liberty of introducing a long-standing client to the iPad; his reaction used colourful language to illustrate his surprise at its ease of use and its capabilities.

    The girls next door: It's a gadget, a boy thing... really? They were the first to want to touch the screen and flick through pages on the book reader. Mind you the guys from next door were impressed with the comic book reader.

    My considered opinion:

    This is a great gadget. For viewing websites, ebooks, documents, videos (the on board speaker is pretty good, not great but adequate) and photographs, it is revolutionary. It doesn't have a Flash player, which means media on the BBC website is not viewable (yet?), but the experience of viewing the news pages is great. Really great. In educational situations, I think this may well transform revision - one app that looks at the Periodic Table is phenominal. It is a delight to look at and to use!

    Do I see this becoming a business tool? Absolutely. We previously built an iPhone app that presents a host of videos; our dev team converted this for use on the iPad and, wow, it is very impressive. OK, so this app is an instructional tool for a golf tutor, however, the stunning presentation can be applied for use by sales teams, project management ... anyone! For example, in my marketing capacity I can see already how easy potential customers will be able to view a range of documents and supporting videos.

    We have an internal app that has an interface on the iPhone. We currently can edit info from the iPhone, however, the touch screen keyboard is not a practical size, comments added, therefore, consist of only a few words. With the iPad and its more capable screen size, it is much easier to type meaning that greater amounts of information will be included. Actually, the word processing app works well; it enables one to add text naturally unlike with the iPhone, and certainly unlike other smartphone devices.

    It is because of the combination of these that I think it will become a valuable business tool; it works as a presentation medium, as a document viewer and as a means to capture textual information. And it is fun.
    So, perhaps the caveat is that the iPad is going to work well for businesses, provided the right apps exist.

    My challenge is now to convince the wife that it is a good idea of hers for us to get one...

  • Using Team Foundation Server (TFS) with Xcode on a Mac

    Friday, March 05, 2010

    We live and breathe TFS here as I genuinely feel its the best source control product on the market. The Visual Studio integration is spot on. The web access add on give nice access for all none developers to create / edit bugs etc.

    We recently have been ramping up our iPhone development and as you may be aware its Mac only using Xcode. Currently there are no TFS plugins for Xcode as it as limited (no?) support for source control plugins.

    After some googling, I stumbled upon SvnBridge. This is a small module you pop on to your application tier and BOOM, you have SVN access to your existing TFS library. No mods, no hassle, just works.

    Getting used to Xcode and svn can be hard work. The intergration isn't the smoothest in the world. So watch out for issues adding / removing items or moving existing items around.

    Overall we are pleased with the support SvnBridge provides, day to day use works well, just a few Xcode / Svn / SvnBridge /TFS fringe issues.

  • MySQL and the warm blankets of Replace and On Duplicate

    Thursday, February 25, 2010

    Two very useful features MySQL has that MSSQL doesn't are the 'REPLACE' and the 'ON DUPLICATE'.

    I've found these are most helpful when updating existing records, although it is best to understand how they differ and how best to combine them with 'INSERT' statements.

    Just for reference a normal 'INSERT' might look like this:

      1: INSERT INTO TABLENAME (productName, productCost, productId)
      2:   VALUES ('new product name', 'new product cost', 'new product id')
    And an 'UPDATE' statement might look like this:
      1: UPDATE TABLENAME SET
      2:   productName = 'new product name',
      3:   productCost = 'new product cost'
      4:   WHERE productId = 'existing product id'
    'REPLACE' is great if you want to insert new records or update records that have matching unique keys. This is because if a record is not found that has a matching key, the record is just inserted. However, if an existing record is found, the record is first deleted, and then inserted.

    An equivalent 'REPLACE' statement looks like this:

      1: REPLACE INTO TABLENAME SET
      2:   productName = 'new product name',
      3:   productCost = 'new product cost',
      4:   productId = 'new or existing product id'

    This makes 'REPLACE' handy as you don't need to worry about finding or deleting records when there is data that just needs to be added or renewed, and you can do it all in one statement that takes care of it for you.

    Caution is needed with 'REPLACE' because it DELETES RECORDS if they exist, before inserting them. So if you have data that has information in that you don't want to loose then you need..

    'ON DUPLICATE'!

    Combining an 'INSERT' statement with 'ON DUPLICATE' functions similarly to 'REPLACE' except that it doesn't delete existing records, but gives you the power to decide what fields are replaced with what values.

    An 'INSERT' with 'ON DUPLICATE' statement looks like this:

      1: INSERT INTO TABLENAME SET
      2:   productName = 'new product name',
      3:   productCost = 'new product cost',
      4:   productId = 'existing or new product id'
      5:   ON DUPLICATE KEY UPDATE
      6:   productName = Values(productName),
      7:   productCost = Values(productCost)

    Notice how the new value for the updated field is chosen from the 'Values' collection passed into the 'INSERT' statement. The new field value can be updated to any value that SQL can accept for the field type being update, and you don't have to update them all.

    It can also be used with clauses that you would use with a plain 'INSERT' statement.

    To find out more, hop on over to http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html

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

    Wednesday, January 27, 2010

    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);
  • ASP.NET 4.0 now 50% more SEO friendly

    Monday, January 11, 2010

    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.

View Older Posts

Find out more about by contacting us