Monthly Archives: February 2014

Detect mobile browsers in server-side code

Last week I found myself needing to detect mobile browsers on the server-side and ran across this extremely useful site:

http://detectmobilebrowsers.com/

It offers open source code for doing just that. Many languages are available: C#, Ruby, JavaScript & node.js, PHP, Python, and more. Even Perl!

Often you’d use this code to redirect the user to a mobile version of your site. However, my site uses the responsive Twenty Twelve WordPress theme. This works well on mobile browsers. Thus, I don’t really want or need to redirect the user.

Unfortunately, there’s one particular piece of content that was banjaxxing the page width on mobile devices. It needed to be replaced. Normally I’d do this on the client-side, which is what the theme does. In this cases the content’s Ts & Cs meant I wasn’t allowed to. But I could do it on the server.

You probably know that you can’t get the client’s screen resolution or browser window dimensions on the server. However, you can use the user-agent string to detect mobile browsers. This is exactly what the code at detectmobilebrowsers.com does. They’ve written and tested code that will reliably detect mobile browsers across most devices. That isn’t something I wanted to attempt myself (how would I test it?), and neither should you.

WordPress runs on PHP so I now have this particularly minging, but highly functional, lump of code in one of my template scripts:

<?php
$useragent=$_SERVER['HTTP_USER_AGENT'];
if(preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) : ?>

    <div style="padding-bottom: 16px; margin-left: -24px; margin-top: -24px;">
        <!-- Content displayed on mobile (but not tablet) browsers here -->
    </div>

<?php else : ?>

    <span style="float: right; clear: right; padding-bottom: 8px;">
        <!-- Content displayed on all other browsers here -->
    </span>

<?php endif; ?>

DO NOT copy this code. New devices are being released all the time so make sure you grab the latest version from detectmobilebrowsers.com. That way your code will work with the most recent generation of devices.

To edit your WordPress templates just open up your dashboard and click Appearance > Editor:

Edit WordPress templates.

(Oh, and if I ever need that check in more than one place I’ll refactor it into a method. For now I can live with it sitting in the one template where I need it.)

As my comment in the code suggests, this won’t work for tablets. If you need special support for them, add the code snippet under the Tablets section here to the first regex. You can also separate the checks for mobiles and tablets, or even different models of mobile/tablet, if you need more fine-grained control over site behaviour.

How to take a screenshot of your iPhone or iPad in iOS 7

Taking a screenshot/screengrab of your phone in iOS 7 is really easy, and it works in all apps. Just follow these simple steps.

  1. Press and hold the Power/Sleep button (see image below).
  2. Click the Home button (see image below).
  3. Release the Power/Sleep button.

Location of iPhone 5S Power/Sleep and Home buttons.

(Note: it also works the other way around: press and hold Home and then click Power/Sleep. Use whichever you prefer.)

If it works the screen should flash briefly to indicate that a screenshot has been taken. If your iPhone isn’t on silent you’ll also hear the camera shutter sound. Make sure you don’t hold Power/Sleep for too long or you’ll switch your iDevice off!

Your screenshot will be saved to the camera role so open up the Photos app to take a look at it. You can see here that I’ve taken several screen grabs today:

Screenshots in Photos app.

Been getting screenshot snap-happy today.

Tap on the screengrab you’ve just taken to view it full size.

Viewing individual screenshot in Photos app.

Looking at an individual screenshot: note the sharing button in the bottom-left corner.

You can get to sharing options by tapping the button in the bottom left corner (the one that looks like a square with an arrow pointing upwards out of it).

Sharing options for screenshot in Photos app.

Here I can share the screenshot or, more likely, send it to myself.

From here you can share the photo or send it to specific people via MMS or email. Just tap the appropriate icon and iOS will walk you through the rest.

Node.js apps: what’s the difference between installing npm packages locally and globally?

You don’t need to spend too much time with Google to realise that there’s some amount of confusion about the purpose of global packages. Local packages people seem to grasp easily. Global packages… well, confusion. And if you’re one of those confuse people, don’t feel alone: I was confused too.

Ironic, considering I’m working on the npm support in Node Tools for Visual Studio. But, up until recently, global packages really weren’t that important in the implementation. We gave you a way to install and uninstall them in the alpha, but that was about it. Not much further thought given really:

Managing global packages in NTVS's npm Package Management dialog.

More recently I’ve been improving the way you interact with npm packages, and global packages are back in the frame. And the question is, what are they for? When (and how) should you use them? And when shouldn’t you?

Let’s take a step back. You might already be familiar with the outline structure of a node.js app:

Structure of a node.js app

On the left we’ve got the Explorer tree, and I’ve highlighted the root ExpressApp2 folder of my app (I was just using this for testing). The ExpressApp2 folder you can see above that is the Visual Studio solution folder.

On the right you can see the contents of my Node.js app, which is pretty sparse, along with the Visual Studio ExpressApp2.njsproj project file.

We also have the node_modules folder, where locally installed npm packages are stored. You can see that I’ve got angular, express, jade, and stylus installed locally.

If I want to use one of these modules in my code, I’d write something like:

var express = require('express');

No surprises so far. But what if express wasn’t there, but was instead installed globally? Could I still use it?

Well, yes, and no.

You see the global package installation folder (for such it is) is not just a big bucket of miscellaneous stuff that’s visible and accessible to all your node applications. There’s no way you can say in package.json, “please get this from (or install it to) the globally installed packages”. And if you try to require it in your code, well, that won’t work either.

And this makes sense, right? I mean you could have anything in your global packages so you probably don’t want all of them visible in all your node.js apps. The potential for problems would be significant.

So, back on point, what are global packages for?

Global packages are for anything that you need to access from the shell. By contrast local packages are for using within your apps.

So you’ll often find yourself installing frameworky or infrastructurey things in your global packages. Installed globally they’ll be on your PATH so you can use them anywhere.

A good example is Yeoman and its generators. You’ll use yo from the command line to scaffold out projects in a variety of places, so both Yeoman and the generators you want to use must be globally accessible.

Going back to express, this is an example of a package that you’ll often want to use in your node apps, so you’d normally install it locally. Except that it also has a command line interface… so you’ll want to install it globally?

Well, you can actually do both, and this might be the easiest option.

But, as I said earlier, you can use that global install in your apps. Maybe you have a lot of apps and you want to use the same version of express in all of them. That way, when you upgrade express, you only have to upgrade it globally and all your apps will get the upgrade. Nice, right?

If you wanted to do this, you’d need to link express into your node apps. To try this out, execute the commands below from the shell in a convenient folder. Couple of points:

  • On Windows you’ll need to run the Command Prompt as administrator, or you won’t be able to create the link,
  • For the npm init command, which will scaffold out a basic package.json for you, just accept all the default suggestions.
mkdir linktest
cd linktest
npm init
npm install express -g
npm link express

Unfortunately, unlike the npm install command, there’s no way to save express into your package.json dependencies list. You’ll need to edit the file and add it yourself. However, you should find that your linktest folder now contains a node_modules folder. Within that, you’ll find a symbolic link to your global express install. You can obviously drill into that folder just as if it were really in the linktest folder.

Now, as I said, if you update your global install of express your linktest node app will also get the update.

Hopefully that clears up the differences between local and global packages.

TAKE-HOME MESSAGE: always try to use local packages unless there’s a very good reason not to! (I.e., you need to use the package from the command line.)

 

Speaking on Node Tools for Visual Studio at Node.js & JavaScript Cambridge Meetup

I’m pleased to say I’ll be speaking at the Node.js & JavaScript Cambridge meetup on Tuesday 8th April. It’s upstairs at the Fountain Inn on Regent Street in Cambridge (UK), starting at 7.45PM.

I’ll be talking about and demoing Node Tools for Visual Studio. If you want to learn how to develop for Node on Windows, and you’re in the local area, please do come along. You can already sign up at:

http://www.meetup.com/NodeJS-Cambridge/events/164845272/

There will be two talks during the evening. I’m not sure what the other one is yet, but I’ll post as soon as I know. The usual format is 20 minute talks with 10 minutes at the end of each for questions.

I’m going to try to cover:

  • The different project templates
  • npm
  • Editing
  • Debugging
  • Profiling
  • Azure deployment

That’ll probably more than fill 20 minutes without too much difficulty. Being Cambridge, people love to ask questions so we’ll see if I can get through it all or not!

As I say, if you’re in the area that night, please do come along. They’re a sociable crowd and there’s plenty of time for drinking and chatting afterwards.

The iOS 7 Keyboard: Un-Damn Your AutoCorrect

I used to suspect that most of the posts on damnyouautocorrect.com were faked. That was until last month, when I finally upgraded my aged iPhone 3GS to an iPhone 5S and, with it, iOS7.

Overall, it’s been a great experience, but the autocorrect… oh, how I hated the autocorrect. Every time I wrote an email, replied to an SMS, I felt like I was fighting with it. It would even correct correctly spelled words. For example, “were” became “we’re” and, with a bizarre nod to either Shakespeare or Schiller, “passcode” became “pass ode”.

Really annoying.

I don’t know if this is because iOS 7’s autocorrect different from iOS 5’s. Maybe it was just the cumulative effect of 4 years of typos combined with that putatively tweaked algorithm. Whatever, it become intolerable.

Fortunately there is some relief to be had with a bit of tweaking. Let’s take a look at the options, starting with the least intrusive and working our way up from there.

Option 1 – The Nutcracker: teach the dictionary one word at a time

Next time you enter a word that it wants to wrongly auto-correct and the suggestion pops up, hit the little X you can see on the right of the suggestion:

Incorrect suggestion when writing an SMS.

Dammit, no! “Were” is a completely valid word.

OK, now delete the word and try to type it in again. When the suggestion pops up again, hit the X to dismiss it. Now delete the word and enter it again, etc. Keep doing this until the incorrect suggestions stops appearing: it’ll probably take about 5 attempts. Once that happens it should mean the dictionary has forgotten the old correction and will instead use the word you’ve entered as the new correction in future, if it makes any suggestion at all.

That’s fine, obviously, but if it’s wrongly correcting loads of words this process could become quite arduous. Which brings us round to…

Option 2 – The Sledgehammer: reset the keyboard dictionary

For me the situation was so bad I had to go down this route. Before you follow me though, understand that there is a downside. Resetting the dictionary will remove all the words it’s learned from you, so it’ll have to learn them all over again. Whilst it’s doing that it’ll probably suggest all manner of humorous and possible highly inappropriate or career-limiting alternatives.

(Just thought I should warn you.)

To reset your keyboard dictionary, open up Settings, and then drill down to General > Reset. Now tap Reset Keyboard Dictionary.

Settings page for resetting various aspects of iOS.

Reset your keyboard dictionary from here.

You’ll be asked to enter your unlock passcode:

Reset keyboard dictionary passcode confirmation screen.

Enter your normal unlock passcode here.

Once you’ve done that you’ll be asked to confirm that you want to reset the dictionary (with a warning about losing all your custom words, as I mentioned):

Reset keyboard dictionary final confirmation.

No going back after this.

And you’re done.

You might still find the vanilla dictionary a bit annoying to start off with, but at least now you have a clean slate. You should find it suggesting a lot fewer spurious autocorrections.

But, if this still doesn’t satisfy you, there’s always… 

Option 3 – Nuke autocorrect from orbit: it’s the only way to be sure

It’s a bit extreme, but you can just disable autocorrect, and it’ll never bother you again.

You need to do this via the keyboard settings, which you’ll find in Settings > General > Keyboard. They look like this:

Keyboard settings.

If you can’t find joy any other way, these settings give you access to the thermonuclear option.

You just need to switch off Auto-Correction. If it annoys you, you can also switch off Auto-Capitalization.

It’s also worth checking your shortcuts to make sure none of them is causing any annoying autocorrections.

Note: the Check Spelling setting is nothing to do with autocorrect. All it does is highlight what it thinks are misspelled words when it’s switched on. It does not try to correct them for you.

Final Thoughts

Things have definitely been better since I reset the keyboard dictionary, but there’s still the odd noticeable difference in iOS 7 autocorrect behaviour as compared to previous versions. For me the most noticeable is that in general it seems to suggest corrections/autocompletions much less often than did previous versions. This is sort of OK but it does mean you feel like you’re having to type a lot more.

Another comment I’d make is that with the form factor of the iPhone 5/5C/5S being longer and thinner than the 3GS and 4/4S, I don’t think Apple’s vanilla keyboard works quite as well because you have to stretch further to hit the keys in the centre. For me, at any rate, this seems to result in a few more typos.

There’s a lot of innovation around mobile and tablet on-screen keyboard design on both Android and Windows 8.1/Windows Phone 8. A good chunk of this is from third parties. Unfortunately this isn’t an option with iOS. I can see why Apple would be unwilling to open up the keyboard implementation to third parties, but it would be good to see them revisit it.

Hope this has been useful for you! And please let me know if you’re aware of anything else that might help.

C# quick tip: does exception handling work with async method calls?

The short answer is, yes… but.

Say you’ve defined some async method:

public async Task<bool> MyAsyncMethod() {

    // Location A: some code here

    var result = await SomeOtherAsyncMethod();

    // Location B: some more code here

    if (someCondition) {
        throw new SomeException();
    }

    return result;
}

How can you call MyAsyncMethod in a try-catch block so you can catch SomeException?

Here’s what you DON’T do:

try {

    // Location C: yet more code here

    MyAsyncMethod();

    // Location D: and even more code

} catch (SomeException ex) {

    // Location E: exception handling code

}

The problem is the call to MyAsyncMethod (highlighted) doesn’t await its return. As soon as MyAsyncMethod has finished executing the code at location A and hits the line that calls SomeOtherAsyncMethod, control returns to the code after the call to MyAsyncMethod (location D). It then passes out of the try-catch block before the code at location B has chance to execute.

Thus, if SomeException is thrown, it won’t be caught. Since there’s now no handler for it, your app is going down…

Oops, something's gone wrong.

(The specifics of what actually happens will depend on the type of app and, sorry desktop IE, I don’t mean to pick on you.)

To catch the exception, you need to await the return of MyAsyncMethod:

try {

    // Location C: yet more code here

    await MyAsyncMethod();

    // Location D: and even more code

} catch (SomeException ex) {

    // Location E: exception handling code

}

Or, if you need its return value:

var result = await MyAsyncMethod(); // etc.

Either way control will not return to your calling code, continuing at location D, until MyAsyncMethod has completed. If MyAsyncMethod throws SomeException, it will be caught and handled by the code at location E – as expected.

IMPORTANT: there is no blocking here so your app will not become unresponsive whilst MyAsyncMethod runs.

There’s a lot of compiler magic* The compiler does a lot of work for you to ensure this works seamlessly. It also uses some support types in the framework itself. This means you can keep your code nice and straightforward.

If you’d like to know more about how async compilation works, check out http://weblogs.asp.net/dixin/archive/2012/11/02/understanding-c-async-await-1-compilation.aspx.

*It’s clever, but it’s absolutely not magic. Rather, it’s awesome engineering.

Git basics: how to merge changes from a different fork into your own branch

If you work with git, especially with either GitHub or CodePlex, you’ll commonly need to merge from branches in a different fork into your own branches in your own fork.

A typical scenario is you’ve forked a repo, made some changes, and now you want to send a pull request to get your changes into the original repo. Of course, not many people will accept your pull request unless you first merge their latest changes into your code – it’s only polite, after all!

At first this can seem daunting but, once you’ve done it a few times, it’ll become second nature.

The method I’m going to show you isn’t necessarily the quickest or most efficient under all circumstances but it’s reliable and, most importantly, if you make a mistake you won’t lose any work. When you use git (or any scm) sooner or later you’ll screw something up. Everybody does: don’t worry about it. If you’ve taken precautions, it won’t matter, so you should feel free to experiment and learn. In the worst case you can always blow away your local repo and do a fresh clone from your remote.

Anyway, back to our merge. There are three stages to the process:

  1. Prepare so that if something goes wrong (it shouldn’t) you can get your local repo back into a consistent state.
  2. Merge changes from the branch on the other fork into your local branch.
  3. Push those changes to your fork’s remote branch (optional).

I’ve broken the first two stages down into quite a few steps, but don’t worry: they’re all simple, and the whole process really doesn’t take very long. Like I say, it’ll quickly become second nature.

1. Prepare

The purpose of this is to ensure that, if anything goes wrong, you can get back to a repository in a consistent state without losing any of your own changes.

  1. If necessary, switch to the branch you want to merge into (make sure you’ve committed or stashed any changes on your current branch first!) with:
    git checkout <branch_name>
  2. Firstly, check if you have any local changes. Make sure you’re in a folder somewhere in your local repo and execute:
    git status

    This will tell you about any changed, new, or deleted files.

  3. Now stage any modified files for commit (you can obviously skip this step if there aren’t any):
    git add <path_to_file_1> <path_to_file_2> ...

    You can also use wildcards:

    git add *.cs *.js

    BE CAREFUL with this. You can inadvertently add a lot more than you intend! If that does happen you can unstage any erroneously staged files with:

    git reset HEAD <path_to_file_1> <path_to_file_2> ...

    If you’ve accidently added loads of files you’ll probably find it easier to use the same wildcards to unstage the lot, before adding the right files individually:

    git reset HEAD *.cs *.js

    Don’t worry: you WILL NOT lose uncommitted changes: you’ll just change the status of these files from staged back to modified/added/deleted.

  4. Commit your changes locally with:
    git commit -m "Write your commit message here."
  5. Pull any changes from your own remote:
    git pull
  6. Manually merge any conflicts that git couldn’t auto-merge. I use Scooter Software’s Beyond Compare for this, but you can use whatever tool you like. I used to be a fan of WinMerge but have recently run into problems with it. YMMV.
  7. Build your code, and fix any errors.
  8. Run your tests, and fix any failures.
  9. Commit any changes you’ve made locally again (git status, git add …, git commit -m …).
  10. If you’ve had to spend much time on the last four steps: pull, build, and run tests again (fix any problems and commit your changes again, obviously).
  11. Push changes to your remote repo:
    git push

    All your changes are now safe and, if something goes wrong, you can just clone again from your remote repo with:

    git clone <remote_repo_name>

    If you don’t want to push changes to your remote repo you can just create a copy of your local repo in a separate folder using Windows Explorer, or from the command line. You can of course try to fix your local repo using git commands but, unless you’re very experienced, there’s a good chance you’ll make matters worse. If you’ve created a backup this doesn’t matter: go ahead and use git to try to fix any problems so that you’ll become more competent with it and, if it doesn’t work, just rename your banjaxxed repo folder and copy your backup back into place. If you don’t have time to mess around just do the rename and copy.

2. Merge

This is where the fun begins.

  1. First we need to add the other fork as a remote for your repo.
    git remote add <remote_name> <fork_url>

    <remote_name> is just the identifier you will use when referring to the remote – essentially it saves you from having to type out the entire fork URL each time. For example, ms11022014.

    <fork_url>, as you may have guessed, is the URL for the fork’s repo, e.g., https://git01.codeplex.com/forks/bartread/ms11022014.

  2. Now verify the remote using:
    git remote -v

    You should see some output similar to this, with both a fetch and a push line for your new remote:

    ms11022014 https://git01.codeplex.com/forks/bartread/ms11022014 (fetch)
    ms11022014 https://git01.codeplex.com/forks/bartread/ms11022014 (push)
    origin https://git01.codeplex.com/forks/bartread/rgnpm01 (fetch)
    origin https://git01.codeplex.com/forks/bartread/rgnpm01 (push)
  3. Fetch the branches and commits of the new remote with:
    git fetch <remote_name>
  4. If needs be, switch to the branch you want to merge into, with:
    git checkout <branch_name>
  5. Merge changes from the required remote branch:
    git merge <remote_name>/<remote_branch_name>

    For example, to merge from the above remote’s master, I’d execute:

    git merge ms11022014/master
  6. Check git’s output for conflicts and manually resolve any you need to, as in Prepare step 6.
  7. Build your code, run tests, and fix any errors/failures, as in Prepare steps 7 and 8.
  8. Commit any changes to your local repo with git status, git add …, and git commit -m …, as in Prepare steps 2, 3, and 4.

3. Push

If you’ve got this far the hard part is over: you’ve merged changes from a branch in the remote fork into one of your own local branches, and committed them to your local repo.

That might be all you need to do at this point. If you do need to push changes back to your own remote fork (most likely, origin), just execute:

git push <remote_name> <branch_name>

So, to push changes from master back to origin, I’d execute:

git push origin master

And you’re done!

Help! It’s all gone horribly wrong! What do I do?

If you followed my advice in the prepare stage you can just “restore from backup” (if you didn’t, I’m afraid you’re on your own):

  1. Rename your local repo directory.
  2. Either clone your remote repo again (use git clone <remote_repo_url> from the command line), or copy (don’t move!) the backup of your local repo that you created in a separate folder back into its original location.
  3. Verify that your cloned or copied repo is in a good state (e.g., build your code, run tests).
  4. Delete the old local repo directory that you renamed.

Now you can try again.