Web, JavaScript, Linux, Apple, Australia and whatever else crosses my mind...

Like Media Centre? Don’t upgrade to Windows 8!!

Michael Brown  May 5 2012 11:33:03 PM
I just can't wait for Windows 8 to come out.  It's going to be Microsoft's biggest ever disaster; bigger than Me and Vista combined!

Having already saddled it with a UI that nobody has a clue how to operate, oh and with the old UI still hanging around in the background if you can work out how to find it.  Now they've started yanking out the few bits that were actually any good and attempt to charge you for them as a separate product!!  Yep, Windows Media Centre, which is one of the best features of Windows 7, is to be pulled and replaced by a non-free download pack, cost currently unknown.

The argument, it seems, is that only 6% of Windows users actually use Media Centre, and so 94% of users are being "overcharged" for Windows.  But that only holds water if Windows 8 really is noticeably cheaper than Windows 7.  I'll believe it when I see it.  As one of the 6% - I have it on my home-built HTPC (Home Theatre PC) and it works pretty well... for a Microsoft product - I'll be sticking with 7 there, thank you very much, and with Kubuntu and Mac OS X everywhere else.  Not that I had any intention of touching Windows 8 with a barge pole anyway.

Now, didn't this used be one of the proprietary OS vendors' arguments against Linux: i.e. Linux doesn't play MP3 and DVD out of the box, whereas Windows and OS X do?  The idea is that Apple and Microsoft have prepaid for the necessary codecs on your behalf, all incorporated in the fee that you pay them for the OS, so you need not worry about it.  Now Microsoft turns that on its head!  You pay them for the OS and then again to watch a DVD!  Just one more reason to go Linux in my book, especially as those DVD/MP3 restrictions are trivially easy to get around in Linux anyway; easier than they will be in Windows 8, I suspect...

jQuery code completion in Aptana/Eclipse

Michael Brown  March 30 2012 03:21:00 PM
Recently, I've been leaning towards Aptana Studio as my preferred JavaScript IDE.  It's based on Eclipse and, like Eclipse, is open source and cross platform.  You can use it either as a plug-in for Eclipse itself or as a stand alone application.  (I've only used in the latter configuration.)  Admittedly, it can be a little sluggish at times, but nothing that I can't live with.

Aptana Studio has a very neat code assist/completion feature, which looks like this for native JavaScript:

JavaScript code assist in Aptana

The code assist info will often appear automagically when you're typing.  If it doesn't, then try hitting the ctrl->space keyboard combination to bring it up.

This is great for native JavaScript, but what about for external libraries such as jQuery?  Well, here's what you get by default if you try to use code assist against some jQuery code:

jQuery without code assist in Aptana

I.e., not very much.  It shows the signatures for the jQuery methods - looked up from your project's installed jQuery library itself, presumably - but displays no information about what they're for and how they work.

However, code assist for jQuery is available for Aptana; you just need to install and enable it.  To do that, you need to
  1. Install the jQuery bundle into Aptana

  2. Enable the jQuery bundle for each project where you want to use it



Installing the jQuery bundle

From the main Aptana menu, click on Commands->Bundle Development->Install Bundle and select "jQuery" from the list dialog.  Note: on my own installations, the "jQuery" option was right at the bottom of the list, even though the rest of the list was sorted alphabetically.  Go figure.  Click the Okay button to install the jQuery bundle.   You need to do this step only once for your Aptana Studio instllation.


Adding the jQuery bundle to your project

You need to do this on a project by project basis.

Right-click on your project name in the Project Explorer and pick "Properties" from the pop-up menu.  In the resulting dialog, select "Project Build Path".  You should now see a list of jQuery library versions, as shown below:

Choosing jQuery bundle for your project

Select (i.e. tick) the library version that you're using (or closest to it) and click the okay button.

Now type some jQuery code into a file from within that project.  Code assist jQuery code should nowl bring up some more meaningful information.  Again, you may have to hit ctrl->space to invoke the pop-up information.

jQuery with code assist in Aptana

As you can see, those dry "signature only" definitions are still there, alongside the fuller definitions.  You just need to look at the one marked as "jQuery" in the right hand column.

Google Maps Web App

Michael Brown  March 24 2012 11:11:00 PM
Here's a simple web app that I've put together in order to show how to pull in and display data from Google Maps.

Messing About With Google Maps App

In order to access the Google Maps API you need to get a Maps API key from Google, which means you need a Google account (e.g. Gmail) if you don't already have one.  Once you've got that, you need to load the Google Maps API JavaScript library, directly from Google's server, like so:
script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=YourKeyGoesHere&sensor=false"


Please don't use my key if you're copying the code.  Also, don't try to copy the Google JavaScript library and load it locally in a misguided attempt to speed things up.  It won't work unless you're loading the API library directly from Google's own server.

The main code is in the code.js file.  Note: the code is namespaced - a subject that I'll be returning to in a later post - so that most of the functions are inside a global object called myGlobal.


Getting Your Position

When the page loads, the $(document).ready() function (provided by jQuery) makes a call to navigator.geolocation.getCurrentPosition() in order to get your current position.  You will see a dialog prompt at this point, asking if you if you want to share your current location with the server.  Note that the navigator.geolocation object is a native to HTML5.  It is not part of jQuery or the Google Maps API.  This call will work on any HTML5-compliant browser. I tested on Chrome, Firefox and IE 9.  The line if(navigator.geolocation) {} checks to see whether this functionality is available in your browser.  (Remember, it's good practice to test for functionality rather than for browser versions, since the latter are a moving target.)

The navigator.geolocation.getCurrentPosition() takes two function arguments.  These are callback functions: the first callback function runs if the getCurrentPosition() call successfully returns your position, and the (optional) second callback function runs if getCurrentPosition() fails for any reason.  A successful getCurrentPosition() call will automatically pass a position object as the first parameter to its defined callback function.  So, it makes sense to call that parameter "position", which I have in my code.  Here's what you get in that object, as displayed by Firebug:

The position object

We're interested in the latitude and longitude properties of the coords property.  We can pass these to the Google Maps API to plot our position on a Google map.  I do this via a call to my myGlobal.codeLatLng() in my "success" callback function.  (We're still inside $(document).ready() at this point.)


Getting the Map Object from Google Maps

myGlobal.codeLatLng() takes three parameters: the latitude, the longitude and a callback function that I've set to markupMap, which I'll get to in a moment.  myGlobal.codeLatLng() creates a simple object, called latlng, by passing to it our latitude and longitude values.  This is our first call upon the Google Maps API.  There's a further bit of prep to do, in that our next call to the Google Maps API requires the latlng object to be a property of another object. I've called this second object initObj.  Its property must be called latlng in this case.  Finally, the myObj.codeLatLng() function calls my myGlobal.getGeoCodeResultsObj, passing as parameters the new initObj object and the same callback function that we passed in, i.e. markupMap.

The myGlobal.getGeoCodeResultsObj sets up a new google.mapsGeocoder object called geocoder, if it's not been set up already.  It then makes a call to the new object's geocoder() function, passing in the initObj object that we created in myGlobal.codeLatLng(), plus two callback functions: the first for a successful call and the second for a failure, once again.  The "success" callback function calls the callback function that we've been passing through all our functions so far, i.e. markupMap.  It passes to markupMap the results of the call to the Google Maps API's geocode() function.  Those results are a JSON array of objects.  You can see the data in them on the web page itself, because I write a string version of them underneath the map itself.  (See the "Returned Geocoder JSON array" box.)


Plotting the Map

The myGlobalMap.markupMap() function plots the map on the page.  It's going to put in a div with the id of map_canvas.  The code creates a new google.maps.Map, if one doesn't already exist, passing in the map_canvas div as its first parameter.  Note that this parameter must be a DOM object for the div, not just its id as a string.  The object passed is where the API will attempt to put the map.  The second parameter passed is a config object, on which I've set a sensible zoom level and set the map to be road map (as opposed to a satellite map).

Now I've got a map on my web page, I need to tell it to show my current location.  The line myGlobal.map.setCenter(resultsArray[0].geometry.location) does this.  Note here that I'm being a tad presumptuous in assuming that the first object in the array returned by the earlier google.mapsGeocoder.geocoder() call is the right one.  In a production app, you might want to give the user the option to choose, but my way will do for this little test app.  Once I've centred the map on my current location there, I want to place a marker at that location too.  The following lines to that by creating a new google.maps.Marker object, called marker, and then placing it on my map at the desired location.  You'll note that I also push the marker object onto an array called myGlobal.markersArray.  The reason for this is that there doesn't seem to be any built-in way in the Google Maps API to clear all the existing markers.  So, I've had to write a function to clear them all, one by one - see the myGlobal.markersArray() function.


Searching and plotting your own addresses

As well as passing the google.maps.Geocoder call a set of coordinates to get some results, you can pass it an address and Google Maps will try to match it.  This is, of course, just what the Google Maps main site does, and I've tried to match that here with the Plot Address button.  Type an address in the text field and hit the button.  Google Maps will plot the first match it finds (there's my presumption again!) onto the map.  The code to retrieve and plot this map is pretty much identical to that I've already described.  In fact, you'll see that I'm reusing most of it!  The only difference is in the config object that is passed into the google.maps.Geocoder() call.  This needs to be an address object rather than a latitude/longitude object.  Check the myGlobal.codeAddress function for how I set up this address config object, using whatever has been typed into the text box.


Going Mobile

And here it is as an app on my iPhone - well, actually in the iPhone simulator to take this screen shot, but it is running on my real iPhone too!
The Maps App on the iPhone

Note this is an app, not a web page running in the Safari browser.  If I wanted to, I could put this up on the iTunes store and sell it, and then how Angry Birds would tremble!  And it's the same source code too, all written in HTML5, CSS and JavaScript.  I tweaked the formatting to better fit the smaller screen, and then add some CSS, courtesy of the jQuery Mobile library, to make it look a bit more iPhoney.  I also load the Google Maps API library with the sensor parameter set to true, i.e.
script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=YourKeyGoesHere&sensor=true"


This lets the API take advantage of the iPhone's built-in GPS.

This magic is possible due to the wonders of PhoneGap, which lets you use web programming tools to create apps for iPhone, Android, Blackberry and numerous other mobile platforms.



 

Web server for Mac OS X

Michael Brown  March 22 2012 05:34:54 PM
I was looking around for a local web server to install on my Mac OS X desktop and made the pleasant discovery that there's one already built in!  Yep, an Apache web server is part of the default install for both Lion and Snow Leopard (although I don't know about versions before that.

It's not enabled by default, but it's easy enough to do that.  Just open System Preferences and look under Sharing.  If you can't remember that, just type "Apache" in the search box of the System Preferences, and it will tell you where to find it.

Mac OS X System Preferences

In the Sharing dialog, make sure that the Web Sharing box is ticked.  (You'll probably have to click on the padlock icon at the bottom and enter an admin id and password first.)

Mac OS X Sharing Preferences

You can see that there's a link on the right to open your personal web site folder in a browser (there's a default "Welcome" index.html file set up for you) and also a button to open the same in Finder.

Microsoft programmers = trained gibbons?

Michael Brown  March 14 2012 11:32:38 PM
Maybe that's not an entirely accurate description: I don't actually think they're trained at all.

A few weeks back, customers of Azure - that's Microsoft's me-too, in the cloud service - lost access to their email, Office docs and whatever else they were fool enough to put up there, for up to eight hours.  And here's why.

It seems that the whole thing relies on a service that issues a certificate with a duration of one year.  To calculate the certificate's end date, they take the current date and then add one to the year portion. (Alarm bells ringing yet?)  When that service tried to run on 29 Feb 2012, it added one to the start date's year portion to come up with an end date of ... drum roll, please .... 29 Feb 2013!!!

And good night.....



Now, if a graduate trainee had made a mistake like that for his pet summer project, you'd still be kicking his arse up and down the length of the floor.  That's "mission critical" quality for Microsoft though.

Via iProgrammer: Azure Outage - Date Arithmetic Details


Windows 8. Looks kind of familiar....

Michael Brown  March 7 2012 09:48:42 PM
In case it might have escaped your attention, the beta Consumer Preview of Windows 8 (a.k.a. Microsoft's Suicide Note) arrived last week.  If you're not a fan of Microsoft or its products then you'll think you've died and gone to heaven.  Yes, It's that bad.

I'm going to start with the Metro Start Screen, which replaces Start Menu; yep, the latter's gone completely.  There's no registry hack to put it back either.  It's entirely inappropriate for what it tries to do, and it's rammed down your throat to an extent that's impossible to escape from.

When you first open the Start Screen, it looks something like this.  (I had moved a few things around, so yours won't look exactly like this.)
Windows 8 default start screen


This is how it looks after I'd pinned some useful, Desktop apps to the Start Screen.
Windows 8 start screen with some apps on it


When I looked at the screen above for a short time, I couldn't help feeling that it looks kinda familiar.....

Lotus Notes Workspace
 

Get AJAX data from *any* server... revisited

Michael Brown  March 3 2012 08:37:26 PM
Ajax makes web apps live and breathe, but it has a major restriction: you can only retrieve data from the same server on which you own code resides.  You can get around such a limitation by using, JSONP but that has limitations; I found that it didn't work well where an authentication key needed to passed to the Ajax service, for example.  

I recently discovered that it is actually possible on the Google Chrome browser to turn this same origin restriction off, so really allowing your Ajax call to fetch data from any server.  All you have to do is launch Chrome with a certain switch at the command line.  Here's how to do it.  (File paths may vary for your own OS, of course.)

On Mac OS X
open "/Applications/Google Chrome.app" --args --disable-web-security -–allow-file-access-from-files



On Windows 7
C:\Users\AppData\Local\Google\Chrome\Application\chrome.exe  --disable-web-security  --allow-file-access-from-files


On Linux
/usr/bin/chromium-browser --disable-web-security   --allow-file-access-from-files


Obviously, this is not suitable for a production environment; you can't go around changing how your customers/users launch their browser, even assuming that they're all using Chrome in the first place!  But for testing, it's a godsend.  You can test against production URLs from a test server, knowing that it will all work (you hope!) when the code is actually moved to that target server itself.

I'm also finding it useful for testing mobile web apps for PhoneGap.  Mobile web apps, unlike web apps that run inside a browser such as Mobile Safari, are not subject to the same origin policy.  After all, the mobile web app files are not actually on a server; they're sitting on your mobile phone or tablet.  Being able to simulate this environment in a full desktop browser before testing it on a phone simulator is great, because PhoneGap's debugging features are limited, to put it mildly.  It makes sense that it's fully debugged, as far as possible, as a desktop web app before you go mobile with it.  I say "as far as possible", because there are some mobile web app features that are not easy to simulate on a desktop browser, e.g. location services, accelerometers etc.

Apple PCs are overpriced because....

Michael Brown  January 19 2012 12:31:21 AM
...because you can get much the same hardware spec for a generic PC (i.e. a Windows) PC for much less.  That may be true, but as Neil said, there's more to the picture than meets the eye....

NB; this post is extended from a reply that I gave on another blog.  It's a UK blog, so I've given UK-based examples.  I'm no lover of Apple the company, by the way.  I think their constant use of the courts to try and suppress competition from the likes of Google/Android is reprehensible.  But I have to admit, they make great products.  And buying Microsoft because you don't like Apple's control-freakery is like cosying up to Hitler because you're pissed off with Stalin.


OS

We all have our opinions on this one.

There are those that maintain that Windows 7 is every bit the equal of Mac OS X, if not superior.  But when you look at those claims, they're usually along the lines of look and feel.  Sure, Windows 7 has got that pin the app on the Start Bar thingie, and it's got some kind of a jump list feature.  Whoopee-do.  They don't ever talk about the underlying architecture, because they don't understand that.  In the same way that some people buy a car based on the colour, the shape of the headlights, the knobs and dials on the dashboard, but without ever checking out the engine!  The truth is that Windows 7 got the good reviews that it did for one reason and one reason only: it wasn't Vista.

Take it from me, the underlying architecture of Windows just plain sucks and always has.  Sure, the NT-based versions - NT, 2000, XP, Vista (yes, even Vista!) and 7 - have a more reliable and scalable architecture than the DOS-based versions - 3.0, 3.1, 95, 98 and Me - but that's not saying a right lot, is it?  


Support

Apple's support is legendary. You can take any Apple product into any AppleStore in the world, and they will try to fix it on the spot for no charge. You don't need to produce any receipt or proof of ownership for this initial examination; you're holding an Apple product and that's enough.  Sure, if it needs real work doing on it, like a part replaced, then you do need to produce your receipt, or pay up if you're out of warranty. But they'll genuinely try to fix it for free first.

And these guys know their shit!  I've lost count of the number of times I've been in a generic PC store such as PC World (UK) or Harvey Norman (Australia), and wondered: does this in-house "expert" really believe the horse shit that he's telling that nice couple, or is he so stupid that he believes it himself?

It's not really that bad, you say?  Then you seriously need to look at Sky's 2009 investigation into computer repairs.  And I hope you have a strong stomach.   They investigated six London high-street computer repair shops and found that only one of them was honest.  How about a £230 charge for a "new motherboard" when all they did was push back a dislodged memory chip on the old one? Or your personal photos copied and passed around by a bunch of perverts? Or attempted hack-ins of your bank account?

Now ask yourself, how much would you pay to avoid all that?


Ongoing Costs

What's Windows 8 going to cost you when it arrives? As a guide, the upgrade version of Windows 7 Home Premium (from XP or Vista) is £85 on Amazon. And don't forget to multiply that by the number of Windows PCs in your possession if you want to upgrade them all. Sure, there are sometimes multi-upgrade packs available from Microsoft, but better catch 'em quick!  They don't hang around long - they're normally available only for a few month's after a major release, and then they're gone.  They're usually restricted to 3 PCs only too.

Mac OS X costs £21 on apple.co.uk and for that one purchase you can install it on as many Macs as you own.


Depreciation

Your Mac will hold its value way better than any generic PC. Have a look on ebay.co.uk.  I found nearly 5-year old Macbook Pros going for £400-500! You'd be lucky to give away a PC that old! Subtract that money from the cost of a new one when you want to upgrade, and suddenly it doesn't seem so expensive, does it?  I have a Macbook Pro from January 2007 that's still going strong.  And I reckon it's good for another three years yet!


At last, an untethered Jailbreak for iOS 5 is here!

Michael Brown  December 28 2011 11:00:42 PM
It's taken several months, but there is now an untethered jailbreak for iOS 5 (actually, 5.0.1).  For those of you not familiar with this scene, "untethered" means that your phone still works after a reboot.  With a "tethered" jailbreak, you can only reboot your iPhone if you have it connected to a PC or Mac running the jailbreak software.  (So a tethered jailbreak is essentially, useless, IMHO.)

The new jailbreak doesn't work with A5-based devices as yet, so sorry, no iPhone 4S or iPad 2 but they're working on it.  I've just done my iPhone 4 and it was the smoothest experience that I've ever had doing this process..

All details on the iPhone Download Blog at:

http://www.idownloadblog.com/2011/12/27/ios-5-0-1-untethered-jailbreak-redsn0w/

Extra instructions for you Windoze users at:

http://www.idownloadblog.com/2011/12/27/untethered-jailbreak-ios-5-0-1-windows/

Get AJAX data from *any* server!

Michael Brown  November 24 2011 06:43:57 AM
In the beginning there was AJAX, XML and JSON.  But AJAX has a major restriction: you can only retrieve data from the same server on which you own code resides.  Enter JSONP.

JSONP is way of retrieving data from via an AJAX call, but from any server you like!

Here's the code for a jQuery call that will fetch the last 15 Tweets from twitter.com, based on a search query.  You simply set the dataType to "jsonp" instead of "json", and then specify a callback function for your success property as per normal.

function doTwitterLookup(theQuery) {
$.ajax({
     url: "http://search.twitter.com/search.json",
     data: {q: theQuery},
     dataType: 'jsonp',
     success: function(returnedData){
             successCallBack(returnedData, unescape(this.data));
     }
  });
}


JSONP works by exploiting a loophole in the web browser's cross-domain scripting security: namely, that a script src="http://server" tag can set to retrieve source files from any server that you like.  It seems that JSONP does some background jiggery-pokery to pull in the AJAX into a new script tag, as if it were new JavaScript code... except it's data!  As ever though, jQuery hides all that overhead from you.

And here's a live example.  Just enter your query into the field and hit the button to retrieve the tweets:


Query/hashtag