Wednesday 29 April 2009

Standing on the shoulders of Giants and peeing down the back of their neck

Kevin Pettitt of LotusGuru.com noticed that some of the Noterati blog postings had been copied and pasted without attribution onto another blog. Now these were straight "copy and paste" ... not re-jigged or added to in anyway, honest to god copy and pretend they are original pieces.

Nip over to Kevin's Blog and have a read at the whole story

Now we all stand on the shoulders of Giants, some small hairy ones like Bill Buchan and some that have surgically attached baseball hats like Rob McDonagh. What we try to do by blogging is help each other by passing on useful tip, traps and other bits and bobs that might be useful to others. When we find a blog that has helped us we acknowledge the help and say "Thank You" and the next time we see that person we buy them a pint.

We do not climb of the shoulders of the giants and then pee down the back of their necks. It is just NOT done, it makes you look like a twonk and it annoys the giant (unless they subscribe to "golden showers for really big people monthly" and I am reliably informed that our Noteati giants are not like that at all!)

So Mr Dheeraj Pal SHAME ON YOU! SHAME ON YOU!

Sunday 26 April 2009

NW200 weekend approaches

The Northwest 200 (NW200) is approaching quickly... on the 16th May. One of the last, great motorcycle races run on public roads will be having it's 80th birthday this year on the Coleraine/Portrush/Portstewart circuit. To mark such an auspicious day I am being joined by Messrs Bill Buchan, Chris Coates and Jon V. Silk for a weekend of 200 mph Bikes, beer and perhaps if it stays fine BBQ.

Should any local or visiting Noterati that are planning to appear at the races drop me an email and lets see if we can't have an impromtue Notesbeer event ... not that we need that much of an excuse :-)

Saturday 25 April 2009

The Weight Loss, Wallace and Gromit Boxers, Clothes shops and Lingerie Rant

During my 2008 annual trip to the doctors I was told "Everything you do is BAD for you ... so STOP IT" as a result of being in the late ultra-violet of my adolescence such prognostications from your local doctor, shamen or wise woman should not be ignored.

So to cut a long story short, I reduced my calorific intake from one that when added up on my calculator required it to be expressed with exponentiation (you know ... when that "e" appears in the middle of a big number) to one that only had 4 numbers in it and I started to walk ... briskly ... while glowering at teenagers who were to a spotty sullen hoodie garbed androgynous individual skinnier than me ... bastards!!

12 months has passed since I started my lifestyle change the bathroom scales have stopped trying to hide every Saturday morning and no longer require Prozac. I have to pass on my thanks to Rob Novak who pointed out that weighing yourself AFTER your shower could add a pound to your weight, so weight watchers .. this is important ... weigh yourself, POST visit to the toilet, POST shave but PRE breakfast and PRE shower to minimise the distance your scales needle has to move!

I have lost nearly 28 lbs and now none of my fecking trousers fit! This came to a head (or an ankle in this case) on Friday when I discovered that if I jumped up and down vigorously OR had more than £3.76 in small change in my pocket, my work combats gradually worked their way over my hips and if not stopped would leave me deeply embarrassed ... particularly if I am wearing my Wallace and Gromit Boxers with the light up, glow in the dark LED eyes.

I should have realised this would happen as I can now look down and see both of my feet without having to wave them like an eejit cockney pearly king doing the hokie cokie on the Queen's birthday. So today I had to do that thing that no grown man should have to do more than once every 10 years, I had to go shopping for clothes and actually do more than pretend interest.

I discovered that I am not longer a generous 36" waist. I am a comfortable 34" and even more wonderful is that if I lie down flat and use a coat hanger with the hook through the eye of the zip and pull like a mad thing for half an hour I can just about get a 32" waist past my hips! I am so proud :-)

I bought a nice pair of trousers and as it is the start of the "less rainy season" in Ireland a pair of suitably restrained "where is my surf board dude?" shorts and lastly a Belt so that I get the wear out of the 36" items in my wardrobe but do not expose my Wallace and Gromit's to the world at large ... #WIN #WIN #WIN!

However what is it with clothes shops "tryin' on" rooms?? There I am with my selections wanting to try them on to see if I can strut my stuff in sartorial elegance and where do the shop designers hide the cubicles?? In the fecking Lingerie section. Don't get me wrong, I like ladies to have the odd bit of lacy frippery as much as the next chap but I do not have to walk thru racks of thongs, bras and whale bone reinforced gussetted underfrillies on my way to try on my prospective purchases.

I need an quiet avenue of suits, ties and shirts with the odd sycophantic sales person bowing to me at every opportunity and muttering the sacred mantra of men's apparel "suits you sir.. oh yes suits you". What I do NOT need is a 6'x3' picture of a lady in her underfrillies informing me of the virtue of the new blue satin bra with inflatable pouches so you too can go from a 34a to a 36C with just a bit of puffing and blowing. I do NOT need independently inflated cleavage satin clad or not! AND I most certainly do NOT want to see an octogenarian lady holding up a black lacy thong to her waist in front of a mirror! Now don't get me wrong, octogenarian ladies should feel free to buy and wear black lacy thongs and when and if I hit the 80 mark I hope they do! For now I just don't need to be an on-looker in her purchasing experience. #shudders#

So all you shop designers out there, get the finger out and put your male changing rooms somewhere else. Guide us through the retail experience with gentle hands, by all means direct us as to what is and what is not cool this season, but please please pleeeeeaaaase end this inhuman practise NOW!.

Sharing my Javascript toolbox - tiplets

In addition to my last post here are two more tiplets from my JS toolbox

First additions to the String object that allow you to use left(x) and right(x) just like in LS

// ****************************************
String.prototype.left = function(n){
if (n <= 0)
return "";
else if (n > this.length)
return this;
else
return this.substring(0,n);
}
// ****************************************
String.prototype.right= function(n){
if (n <= 0)
return "";
else if (n > this.length)
return this;
else {
var iLen = this.length;
return this.substring(iLen, iLen - n);
}
}
// *****************************************


and another String function setCharAt(x,y) which will replace the character at postion x with character y. BTW x starts at 0 as the first character!
for example

myString = "My Dog has no nose"
myString.setChar(3,"G")

would result in myString being equal to "My God has no nose"


String.prototype.setCharAt = function(index,chr) {
if(index > this.length-1) return str;
return this.substr(0,index) + chr + this.substr(index+1);
}


Finally for today and extension to the number object Number.padZero(x) that will return any number as string x long with left padded zeros.
For example
var myNumber = 12
var myPad = myNumber.padZero(4)
would return myNumber = "0012"
This function is useful if you are populating the DOM with objects based on a FOR loop and you want the object.id's to be a set number of characters long.

Number.prototype.padZero = function(cnt)
{
var retvar = this.toString();
cnt=cnt-retvar.length
if(cnt>0)
{
for(var x=1;x<=cnt;x++)
{
retvar = "0"+retvar;
}
}
return retvar;
}

Sunday 19 April 2009

Sharing my Javascript toolbox - Date Formatting

I was sorting out my Javascript Utilities into some semblance of order over the weekend and I found an extension to the date object that you might find useful. This is one of those things that I use on a daily basis and kinda forget that it is not standard and that other people may find it useful.

Basically what I got pissed off having to recode date formatting routines and having to remember things like how to work out the week number in the year given a data. So I extended the native Date Object with a new method called format which if you supply it with a date format string will return the date in the format you require. Rather like the format() LS command. However being a bit of a PHP nut I used the PHP format string structure as my starting point, because it makes more sense (well to me anyway... and i am very odd)

The format string you use can be made up of the following characters.
All other characters and spaces in your string will be considered as constants., but be careful of including words like "and" which will be resolved as "a", "n", "d"


When you add my code to your web pages/forms all you need to do is instansiate your date and then use the new method format([format string],[locale code]) and the date stored in your Date object will be returned in the format you requested For example
myDate = new Date();
xxx =myDate.format("d/m/Y","EN")
Will result in xxx containing 19/04/2009 or
myDate = new Date();
xxx = myDate.format("D dS, F Y","EN")
will result in xxx containing Sunday 19th, April 2009

Localisation

I have provided 3 Locale's English =EN, French =FR, and German = DE however it is really easy to add others if you need them. In the code find the definition for

daysL = Names of Days Long
daysS = Names of Days Short
monthL = Names of Months Long
monthS = Names of Months Short
daySuf = Suffices for Day numbers (st,nd,rd and th)

and add the values that you want in the format that the other countries are in.

You can get the JS source code DateExt.js here feel free to use and if you find anything odd, wrong or additions that you find useful please let me know ... enjoy ;-)

Monday 13 April 2009

UKLUG - Are you going? (the advert)

video

Flex for Thick Gits #6 - Populating a list box from a Domino Agent

OK we are going to look at a real example. I am assuming you have FLEX BUILDER installed for this.. although you can do it with just the SDK, it is a lot easier if you are in FLEX BUILDER.

01. Fire up your Notes Designer Client and create a new blank application called flexdata.nsf on your developement server.

02. Create a form called mydata and populate it like this
The ItemKey is a computed field "Computing on Composed" to @Unique

03. Save your form

04. Create a view called mydataview and have it select ONLY forms = "mydata"
sort it by ItemKey Ascending not categorised.

05. Create an agent call it getdata and give it these properties


06. In the Initialize sub write the following code

Sub Initialize

Dim ThisSession As New NotesSession
Dim ThisDb As NotesDatabase
Dim ThisView As NotesView
Dim ThisDoc As NotesDocument

Set ThisDB = ThisSession.CurrentDatabase
Set ThisView = ThisDB.GetView("mydataview")
Set ThisDoc = ThisView.GetFirstDocument
Print |Content-Type:text/xml|
Print |<?xml version="1.0" encoding="ISO-8859-1"?>|
Print |<items>|
Do While Not (ThisDoc Is Nothing)
Print |<item>|
Print |<key>|+ThisDoc.ItemKey(0)+|</key>|
Print |<name>|+ThisDoc.ItemName(0)+|</name>|
Print |<price>|+Format(ThisDoc.ItemPrice(0),"##0.00")+|</price>|
Print |</item>|
Set ThisDoc = ThisView.GetNextDocument(ThisDoc)
Loop
Print |</items>|
End Sub
All this code is doing is looping around the documents in the view and printing them out as XML
You could use the inbuilt &readviewentries function to return the XML however I want to keep the XML produced as simple as possible for the moment.

The most important thing to note are the top two Print Statements
Print |Content-Type:text/xml|
Print |<?xml version="1.0" encoding="ISO-8859-1"?>|
this ensures that the rest of what is produced is XML!

07. Change the ACL on your file to be Default = Manager so you can test access to the nsf without having to logon (you would NOT do this in real life!)

08. Open the data base in the Notes Client and create 4 or 5 items

09. Goto your browser and enter the url
http://[myserver]/[mynsf path]/flexdata.nsf/getdata?openagent
for example on my server that would be
http://www.unseenuni.com:81/flex/flexdata.nsf?getdata

10. You should see data like this

SUCCESS!!

OK you can close down your Notes Client for now and start the Flex Builder Application

11. Create a new project called DomonoData1 using File then New then Flex Project

12. Open the script TAB and paste in this
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="myData.send()">
<mx:HTTPService id="myData" url="http://www.unseenuni.com:81/flexdata.nsf/getdata?openagent" result="dataResult(event)"/>

<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent
import mx.collections.ArrayCollection
[Bindable]
private var items:ArrayCollection = new ArrayCollection
private function dataResult(event:ResultEvent):void
{
items= event.result.items.item;
}
]]>
</mx:Script>
<mx:FormItem label="item" width="272" height="48">
<mx:List id="itemlist"
rowCount ="2"
dataProvider ="{items}"
labelField="name" height="46" width="229"/>
</mx:FormItem>
</mx:Application>

Replace the URL in the HTTPService tag with the URL that points to the agent on YOUR server!!

13. Click on the RUN button in the Flex Builder Toolbar


14. Your browser should open and you will see something like this


OK lets look at the code in some more detail
A = This is the application definition. Note that the last line of the code is the closing tag for this item. All the code is enclosed in these tags, with the exception of the &lt:?xml ... ?> xml definition tag. I have also added a creationComplete function called myData.send() this function will run when the FLEX app has totally loaded and will trigger the HTTPService object myData to go and get data.

B = this is the definition of the HTTPService agent, it has an id of myData and you will note this is name that is referenced in the creationComplete function defintion of the <Application> tag. I supply it with the URL that provides the application with XML data from the server I also supply it with a function that will run when data is recieved in this instance it is a function called dataResult and i am passing it the event object that the result event creates.
C = these two imports tell the Flex compiler to bring in the extra MXML code for RPC events and ArrayCollections. This code is not automatically brought in so we have to add it in manually.

D = the [Bindable] metatext tells Flex that the var that follows will be available for binding to other data capable objects. The var declaration that follows creates a new empty ArrayCollection called items

E = This is the function I defined as the result event handler in the HTTPService object B
The HTTPService object result event object contains the XLM returned as a nicely formatted property. So I can assign this data to the ArrayCollection var I just created. It is worther of note that the event.result object holds the data in the same hierarchy as defined in the XML i created
If you remember each record was stored in an [item] and these were surrounded by an [items] tag. So the data we want is found in the event.result.items.item which is (for me anyway) a little odd.. i would have put it in the event.result.items but it isn't so BE Careful!

Lastly here are the elements on the page itself.... a FormItem and a List. The important thing here is the dataProvider="{items}" line. This tells the list item to bind to the items ArrayCollection which has been populated by the dataResult() function triggered by the creationComplete event.

30 lines of Flex code, a domino form, view and agent .. and you have data moving from your domino server down to your flex app .. :-)

I have popped the NSF and the FLEX project directory up to the web and you can download it here. Simply move the FlexData.nsf DB to your server and sign it. the Flex project.. copy into your Flex Project dir and load.. and away you go.. enjoy. :-)

Flex for Thick Gits #5 - Getting data from a remote source

OK lets get down and dirty and jump to the interesting bit.. how to get data into the app from an external source, like your domino server :-)

You do this using the HTTPService class. This inbuilt component allows your app to go to a URL and read the data that the URL returns. Usually (but not always) this will be XML. Once the data is returned you can use it in your app and that is what we will look at today.

1. The HTTPService Object

You create the object in MXML all you need to do this is the URL that will provide the data and function that will "deal" with the data. So it will look something like this
<mx:HTTPService
id="mydata" url=http://www.unseenuni.com/flexdata.nsf/getdata1?openagent
result="myResultHandler=(event)"/>
2. Getting Data

Simply creating the object doesn't actually go and get any data, you have to invoke the send() method. Now a word of caution here if you are going to use the data for a view or as list for say a combo box you app needs to be fully loaded so all the components are ready to receive the data. In MXML there is a useful even called creationComplete which is fired when your application has completely loaded and has reached a stable condition. This is the perfect time to go and get your data! This is analogous to the onLoad event in the traditional browser DOM.

3. Using the returned data

There are actually 2 ways to use the data that is returned. When the URL returns data it is stored in the lasResult property of the HTTPService object. So lets say your Domino agent returns the following data

<myXML>
<myItem>
<itemName&gtWidget 1</itemName>
<itemPrice&gt15.95</itemPrice>
</myItem>
<myItem>
<itemName&gtWidget 2</itemName>
<itemPrice&gt11.95</itemPrice>
</myItem>
<myItem>
<itemName&gtWidget 3</itemName>
<itemPrice&gt17.63</itemPrice>
</myItem>
</myXMLa>
All I need to do to access the myItem Collection is to query the HTTPService object (which if you remember had an id of mydata the code would look like this
mydata.lastResult.myXML.myItem
This can be useful when debugging but the one of most use is the event handler i set up in the HTTPService object myResultHandler(event) this event will be fired when the URL you specified has returned all the data it is going to return.

If you are familiar with LS or JS the way you code up the function is very similar it looks like this

private function myResultHandler(event:ResultEvent):void{ ...do something here... }
the returned data is available within this function as property of the event object. Using the XML returned in the example above i would access the myItem collection like this
event.result.myXML.myItem
Now all we need to do is make that data available to the other objects in your application and we do this by making a BINDING ArrayCollection. An ArrayCollection object is an extension to the flex ARRAY object.Now you can use a plain old simple ARRAY object in Flex for storing the data but if you intend to populate controls, filter or sort the data then the ARRAYCOLLECTION object is the one to go for because it comes will loads of extra functionality the ARRAY object does not posses. The most crucial of this is if the underlying data is refreshed (ie you go to the server and get a new set of data) if you use an ARRAYCOLLECTION all the bound objects that use that ARRAYCOLLECTION are automatically updated. If you use an ARRAY this does NOT happen!

This is really very very easy and in my next post I will show how to do this.

Sunday 12 April 2009

Flex for Thick Gits #4 - Creating a Class

OK I was going to talk about the Event Object in more detail in this post however, i realized that I hadn't talked about classes. Now there is neither time nor space to talk in detail about Object Oriented Programming (OOP), so if you don't know what a Class, a Property or a Method is, drop me a line and I will send you some links. ;-)

Now in Flex there are some things called Value Objects also called Data Transfer objects and they hold only data related to the object and no data about flex or business logic and you implement them as ActionScript Classes. The are called Data Transfer Objects because quite often they are used as containers for the data returned from or sent to a back end database

So how do I create a Value Object?

In Flex Builder you do it in your project select File / New / ActionSrcipt Class


You will be presented with a dialog like this



First give it a PACKAGE name, this will create a folder of the same name in your project tree. Then give the class a NAME, this create a file in the PACKAGE directory called Items.as, lastly make the class PUBLIC by clicking the Public option in the Modifiers section. There are other options I have no displayed, don't worry about them nowm just click on the FINISH button at the bottom of the dialog, When you do this you will be taken to the class editor and it will look like this.

Now I will want to use this class to hold data and then bind that data to an object I need to add something to the class like this

The [Bindable] line means that every property in this class will be used when this class is bound to another object in the application (like a list box etc). Next we have to give our class some properties..



I am adding itemName, itemKey and itemPrice, not that I have typed each property (the bit to the right of the : )

Lastly.. for this example I need to build a constructor method that will use to build an object from this class.The constructor is the public function Items() section.
This function requires 3 parameters, cItemName, cItemKey and cItemPrice, these parameters are then assigned to their equivalent property. You should remember that the type of the parameter you pass MUST match the property type you have given the property! It would be a BAD thing to try and assign a NUMBER to a property you have defined as a STRING :-)

To add this class into your application you would then switch back to the project MXML file and in the script block below the &lt![CDATA] I add this

import tells the complier to go to the myObjects directory and load in the Items.as file and create it as a class that I can use in the application. To create a object based on this class all i need to do is this

The [Bindable] tag allows me to BIND the object that follows to another object and then I have declared a new variable called myData with a type of Items.
this is the equivalent of the DIM statement in LS, something like
Dim myDate as NotesDateTime

I have create an instance of the object but it has yet to be instansiated, i do this with the following line
myData now exists as an object with the values passed to it in line 12.

... and that folks is how to create, design and implement a basic class in FLEX.

One of our number is doing the Great Wall of China KUDOS!

One of our number Ms Eileen Fitzgerald a familiar face to anyone who has attended or spoken at ILUG. Her Clipboard signs such as "Please wind up your session as soon as possible" (*please note Eilleen's signs were shorter and way more pithy i have edited them to save Ms Fitzgerald's blushes). Any old how she is very keen on raising money for good causes. This year she is off on a sponsored walk along the great wall of china not all of it cause it is a wee bit on the very very long side of very long.

She paying for it all herself and asking the world to sponsor her chosen charity, which it one close to her heart. You can read Why here and also take the opportunity to give a few £'s or $'s to what is a very worthwhile charity!

Friday 10 April 2009

Flex for Thick Gits #3 - Events what FUN!

I am going to assume you folk know what events are and not go into an detailed explanation, Basically one of the great unwashed (or users) does something in your app like clicking on a button and quite rightly that click does something. The "click" is the event and you have written some wonderful code that get processed when the "click" happens.

Now the most basic way of doing this is to put the code in the object .. like this

<mx:Label
id='myLabelThingie'
text="I'm Waiting"/>

<mx:Button
id="bigButtonOne"
label="Click Me Hard"
click="myLabelThingie.text='OOOO that was good'"/>


OK there are two things here... the first is a LABEL object which has an id of myLabelThingie A Label is a very simple object that will hold some text, in this example it starts of displaying the text I'm Wating. I need an id so that I can access it later on. Please make sure your IDs are always unique in your application!!

Next to it there is a BUTTON object. The text on it reads "Click me Hard" it looks like this


When a user clicks on the object the click=".." kicks in and the text on the label, accessed via it's ID is changed to "OOOO that was good".. like this


Just the same as LS, JS and even VB ;-)

this is a fine and dandy way of doing things but when you want to be really smart it does limit it you a little.. so you build functions to do the exciting stuff and call them in the Click Event of the object. functions are written in ActionScript and are placed in a <mx:Script> tag, Like this :-

<mx:Script>
<![CDATA[
private function clickMe().void
{
myLabelThingie.text='OOOO that was good';
}
]]>
</mx:Script>

<mx:Label id='myLabelThingie' text="I'm Waiting"/>

<mx:Button id="bigButtonOne" label="Click Me Hard" click="clickMe()"/>



Note that the actionscript code is nothing that even closely resembles well formed XML and this is why we surround it with the <![CDATA][ ... ]]> tag. If you forget this you will have LOADS of fun with errors!

Also of note here is that functions that types (the :void bit) this means that the function will not return any data. It is not strictly required, the complier will moan at you if you don't type your functions. Best practise is to :void functions that do not return things, it helps you and those that come after you recognise the function as a non-return function:-)

If you wanted to pass some data to the function, lets say some text for the label you can do this but you MUST type the value passed, just like in dear old LS.

<mx:Script>
<![CDATA[
private function clickMe(myWeeMessage:String).void
{
myLabelThingie.text=myWeeMessage;
}
]]>
</mx:Script>

<mx:Label id='myLabelThingie' text="I'm Waiting"/>

<mx:Button id="bigButtonOne" label="Click Me Hard" click="clickMe()"/>



Notice the :String - this is the equivilant of this LS

function clickMe(myWeeMessage as String)

OK now I want to mention a VERY important event creationComplete This event is fired when a component is all ready and waiting in the application. Every object in your app has a creationComplete event. The app itself has a creationComplete event and this is fired when all the component objects contained in the application are loaded and ready and have broadcast their creationComplete events upwards to the Application.

The Application level creationComplete is analogous to the onLoad() event in JS.

All your Flex applications have a built in "listener" function that listens for events, you don't need to know how it does this just know that it does and it does and know that it is your friend!

When the "listener" function "hears" an event being fired somewhere in the application, it generates an event object and this event object contains lots of useful information. The event object's contents depend on the event that was "heard" by the listener" but all events objects are based on the same Actionscript base class.

In my next wander into FLEX land I will look at the event object in more detail

Dr Who, the daleks and George Bush On Holiday with Green Day

Dr Who, the daleks, George Bush, the glitter band a smidgen of The Sweet and Green Day
Just Plain Wonderful!
click to listen, right click save as to download

An just in case that isn't enuff feast your ears on Gun's and Carl Douglas
Sweet Kung Fu fighting Child of Mine

Wednesday 8 April 2009

U2 - Get On Your Boots the Justice Remix - If U2 sounded like this all the time I would be a fan

Have listen here from those lovely people at IHopeYourEarsBleed.com

Danger Danger Will Robinson! Upgrading to the V8.5 when you have QuickR 8.0.0.2 connectors installed

A word of caution for anyone thinking of moving from Notes 8.0.2 client to the new 8.5 client if you have Quickr Connectors installed.

This occurred today and I have tried it on two PC's and the same symptoms appeared on both installs.

The Enviroment :-

OSs: XP Pro & Vista HP
Notes Client Before: Notes 8.0.2
Notes Client After: Notes 8.5.0
Quickr Server: 8.0.0.2
Quickr Connectors Before: buildnumber=ORC8.0.1 buildtime=20071002.0115

The Problem :-
Post install V8.5 when you try to attach a file to a Notes Document in the Client the client will crash just before the appearance of the Quickr Dialog that prompts you to choose between sending the attachment or sending a link. This crash will happen in both Standard and Basic client mode.

Oddly this does NOT happen on a clean install of the Notes 8.5 client.

Removing Quickr Connectors makes the problem go away, reinstalling the *.0115 quickr connector makes the problem come back.

Tuesday 7 April 2009

Javascript Sorting

OK this came up today in a skype chat about browser side sorting of array's returned by AJAX, prior to display on the page. particularly useful if you want the user to have the ability to sort the date in a variety of ways without going back to the server to get it done. The great thing is there is a built in JS method on the ARRAY object that allows you to sort the contents in all sorts of interesting ways.

It is relatively simple to do but there are a few GOTCHAs to remember the main one of these being that sort() sorts lexicographically! So....
myArray = ["Bob","Anna","Zeebedee","George"]
myArray.sort()
...will result in myArray contents = ["Anna","Bob","George","Zeebeedee"]

Thats all fine and dandy however what happens when you do this?
myArray = [12,400,3,25]
myArray.sort()
You will get myArray = [12,25,3,400]!
Why???WTF??? I hear you cry.. this happens because it a lexicographic sort and lexicographically 3 is bigger than 25 ...go figure! But all is not lost to get arround this you would pass a function to the sort() method.

When such a function is passed into array.sort(), the array elements are sorted based on the relationship between each pair of elements "a" and "b" and the function's return value. The three possible return numbers are: less than 0, 0, or greater than 0

  • Less than 0: Sort "a" to be a lower index than "b"
  • Zero: "a" and "b" should be considered equal, and no sorting performed.
  • Greater than 0: Sort "b" to be a lower index than "a".

So to sort an array numerically and ascending for example, the body of your function would look like this:

myArray = [12,400,3,25]
myArray.sort(sortMyNumbersAsc)

function sortMyNumbersAsc(a,b) { return (a-b) }

This works the way it does because whenever "a" is less than "b", a negative value is returned, which results in the smaller elements always appearing to the left of the larger ones, in other words, ascending.

Sort an array numerically but descending isn't much different, and just requires reversing the two operands "a" and "b" into this

myArray = [12,400,3,25]
myArray.sort(sortMyNumbersDsc)

function sortMyNumbersAsc(a,b) { return (b-a) }

You can also have fun shuffling the contents of your array by randomising the entries, i don't actually test "a" and "b" I just return a value of less than 0, 0, or greater than 0

var myarray=[1996, "Duck", 28.445, "Gertrude's Lemon Corporation"]
myarray.sort(scrambleMe)

function scrambleMe(a.b) { return (0.5 - Math.random()) }
So that is what you do when you have flat single dimension arrays, what happens when I have a multiple dimension array -- can I still sort? Yes you can and here is how... conside this array
var myArray = new Array();
myArray.push( ["one",1]);
myArray.push( ["three",3]);
myArray.push( ["four",4]);
myArray.push( ["two",2]);
myArray.sort(sortMe);
Now when you pass a and b to the function the entire dimension is passed so you can refer to the index value to do the sort, like this is we want to sort ascending on the second numeric dimension
function sortMe(a,b)
{
x = a[1];
y= b[1];
return (x-y)
}
This will return the array sorted like this

["one",1]
["two",2]
["three",3]
["four",4]

Simple ;-)

Enjoy!

IamLUG Site now open

Social Software Guru and Noterati Empissimus Chris Miller has just announced on his site the arrival of the America's User Group Conference IamLUG a new user group conference, the inaugural conference is in St Louis in August this year.. The IamLUG site is up and running and available for Sponsor registration and it will be open for attendee and session speaker registration in the next couple of weeks.

So those of you that can't get to the European LUGs get ready to line up and register !!!

Welcome to the LUG conference calendar IamLUG, success is sure to follow!

Sunday 5 April 2009

All the dead voices

Just finished watching a BBC drama called "Five minutes of heaven" on BBC2 and although it had dark,sombre overtones it has left me more positive about this troubled little country I live in.

The drama revolves around two men whose lives intersected briefly in the late 70's when the one of the men murders the other's brother in a sectarian tit-for-tat murder.

Now I realise that many of my readers come from outside Northern Ireland and you probably don't know more than what the media has served up about "the troubles" through the years. Basically it came down to two tribes who hated each other with a ferocity that knew no bounds. The dogma of the two tribes was so strong that when strangers met they would either politely dance around looking for clues as to the tribe you belonged to, or they would ask bluntly "What are you?". It was and in some cases what tribe you were in was more important than who you actually were.

One tribe were mainly protestant and loyal to the Crown (ie the UK) the other mainly catholic and republican (ie wanting a united Ireland). The warrior elite of both tribes segregated themselves into ghettos and regarded the other side with a hatred that was as dark as it was palpable. To these "warriors" simply being in the other tribe was ample reason for your execution. It has been my experience that reason plays little part in proceedings that are driven by hatred fuelled by religion and I have long since stopped looking for it.

The drama this evening made me look at the effects "the troubles" had on me, my friends and those people I met along the way who were involved more intimately with the machinations of whatever tribe they chose to be in and the continuing effects it is having today.

The story went like this, some time in the 70's a protestant 16 year old goes to the UVF commander in his estate and volunteers to kill a catholic. There had been a spate of Tit-for-tat killings and some Protestant workers had been threatened by the Provisional IRA. The Protestant UVF then selected at random a Catholic worker from the same business, gave him a warning to quit and a couple of days later sent the 16 year old to kill him ... which he duly did. The killing was witnessed by the dead man's younger brother.

We zoom back up to the present, the killer and the young boy are now men. The killer served 12 years for his crimes and then was released under license as part of the peace agreement. A TV crew approach the two men with a view to making a program about "truth and reconciliation" and the two men agree to meet.

The program is available on iPlayer and stars Liam Neeson and Jimmy Nesbit, if you didn't get a chance to see it.. I urge you to.. it is not pleasant and the ending you expect may not be exactly the way you expect it to be.

For the first time in many years here was a drama that had hope amidst the violence and hate. The hope is that while all the dead voices are still there, their cries as strident as they ever were but instead of crying for vengeance perhaps they are crying for peace?

Disqus for Domi-No-Yes-Maybe