Monday 13 April 2009

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?

Sunday 29 March 2009

I got a new toy this weekend and this is the first output

I got a new toy this weekend. It was meant to be for my Birthday which is next week but Amazon were a bit too good at delivering to Ballygobackwards ;-).

The Gadget in question is a new Wacom Bamboo MTE450KEN Pen Tablet and of course it had to be de-boxed and tested ... just in case it was faulty and had to go back. I am relatively new to using pen/tablets as user input devices. Some of my chums who are way more into digital graphics than i am swear by Wacom products, having said that they use the WAY more expensive ones. This particular one is only £60.00 BUT from my point of view so far (3 days) it is really eye opening what you can do with it.

So this is my first finished thing I have done with it.. using GIMP 2 ...

Preparing for UKLUG in Edinburgh #2 - Don't use the Scottish version of Vista!

It has come to my attention that several people when they heard UKLUG is happening in Edinburgh may have downloaded the Microsoft Vista Haggis Fix and Language pack to immerse themselves in the "Scottish Geek Experience" prior to journeying to the Scottish capital in October. This was very far sighted of you, but may have come as a bit of a shock.

If you did download this you may need some help understanding the commands. The Scotland edition may be recognized by looking at the opening screen. It reads "WINDAES VISTA, Ye Ken!" It has a background picture of William Wallace superimposed on a St. Andrews Cross and is shipped with a Mel Gibson screen saver.

The Recycle Bin is called 'Thon Bucket.'
My Computer is called 'Thon Computer Thingie.'
Dialup Networking is called 'Phone the Bhoys.'
Control Panel is known as 'Daworkins'
Hard Drive is referred to as 'thon whizzy thing way maw porn onit.'
DVDs are referred to as 'thon wee plastic disc thingies.'

Other features:
- Instead of the standard error message you get a window covered with a picture of a turnips and the cheerful message "Aw fer feck's sake!"
- OK = 'ats fine'
- cancel = Get ti fuk ye baw bag
- reset = Och ye'd be as weel startin again
- yes = Och aye
- no = nae chunce mon
- find = if ye'd bothered to pit it in a safe place, ye widnae need to look for it noo
- go to = go'n ower 'ere
- back = back the wye
- help = geese a haun'
- stop = pack it in
- start = com on 'en
- settings = sittins
- programs = stuff whit daes stuff
- documents = stuff I hive done afore

Also note that Windaes Vista Haggis does not recognise capital letters or punctuation marks.

Some programs that are exclusive to Windaes Vista Haggis
- "Pincil an paper" is a word processor
- "Colurrinin book" is a Graphics program
- "Addinup" is the calculator
- "Andrex" is the notepad
- "Mawtoons" is the CD player
- "Pickies" is the graphics viewer
- "Tax records" is a program that creates an empty file

If you have problems please feel free to contact the UKLUG Etiquette and ferign baw bag's Liaison team.

Conditional reasoning - When if - then's get muddled

I was having a conversation the other day on conditional reasoning and how bad we IT people can be at using logic in our programming. I was reminded of an example that was put to me when I was at University. This is relatively famous in Maths geeks circles and was put forward by Wason and Johnson-Laird in 1972 to show how poor we really are at reasoning.

Four cards are laid out as below (UPDATE Letter on one side number on the other - Thanks Richard!)
EK47


The conditional statement is then given
If
a card has one vowel on one side
then
it has an even number on the other side.

The question is now to decide what is the minimum number of cards that need to be turned over to prove that the conditional statement is true, and what are those cards?


If you said "E" well done that is "affirming the antecedent", "E" is a vowel and thus should have an even number on the other side. If there was an odd number on the other side, the statement would be false, so E must always be turned over to check the validity of the "if - then"

But what other card(s) do you need to turn over?

If like many people you choose "E" and "4" then with "4" you are affirming the consequent. Even though 4 is even, it may have a vowel or consonant on the other side and the statement is not falsified by either so that was wrong

If you said E and 7. Then 7 could deny the consequent and hence must be checked. If there was a vowel on the other side, the statement would be false.

So if you said E and 7 well done! If you said E and 4 well be careful how you use your IF / THEN arguments you might get bitten on the bum!

** Update **
The E / 4 answer shows how easily we fall into what is known as confirmation bias.. When we attempt to confirm the claim, we can forget that it is also important to try and falsify it. Finding a pairing of vowel and even number does nothing to support the claim; it's the failure to find a vowel with an odd number that confirms it.

Saturday 28 March 2009

Preparing for UKLUG in Edinburgh - a guide for Sassenachs and non Teuchters

UKLUG is approaching, OK it is in October (on the 8th and 9th to be exact) so it is still a small dot on the horizon of the Yellowverse some 194 days away. If you are planning on going I would advise you to get your skates on and apply now, for rumour has it that the places are filling up fast and "wait-listing" is not that far away!!

So nip over to http://www.uklug.info now and get your name down as an attendee or for that matter if you feel the urge to share some of your knowledge submit a session abstract ... I have ... but more on that nearer the time.

Last year I tried to prepare our more distant Noterati Colleagues travelling to ILUG for the Irish Culture Shock Syndrome with a series of blog posts. As ILUG is taking a well earned rest in 2009 I might as well do the same for UKLUG.

Now UKLUG is happening in Edinburgh, capital of Scotland home of the kilt, haggis, deep fried mars bars, bagpipes, whisky and golf. Now there is a scurrilous slur, probably started by the English, that folk from Scotland are a bit miserly. In fact is has been said (usually from a safe distance across the border) that Scottish folk are that tight with their cash they squeak when they walk.

THIS IS NOT SO! They are just "careful"

For example you may have heard of this occurrence at LS09

Four noterati went for a drink after Lotusphere in Orlando.
They turned a corner on the Boardwalk and see a sign that says, 'Old Timers Bar - all drinks 10 cents'.
They look at each other, and then go in, thinking this is too good to be true. The barman says in a voice that carries across the room, 'Come on in and let me pour one for you! What'll it be, Gentlemen?'

There seemed to be a fully-stocked bar, so each of the men ordered a martini. In short order, the bartender serves up four iced martinis...shaken, not stirred, and says, 'That'll be 10 cents each, please.' The four men stare at the barman for a moment. Then look at each other...They can't believe their good luck. They pay the 40 cents, finish their martinis, and order another round.

Again, four excellent martinis are produced with the bartender again saying,"That's 40 cents, please.' They pay the 40 cents, but their curiosity is more than they can stand. They have each had two martinis and so far they have spent less than a dollar. Finally one of the men says, 'How can you afford to serve martinis as good as these for a dime a piece?'

I'm a retired tailor from Boston ,' the bartender said, and I always wanted to own a bar. Last year I won $125 million in a Lottery and decided to open this place. Every drink costs a dime......wine, liquor, beer, it's all the same.'

Wow!!!! That's quite a story, says one of the men.

The four of them sipped at their martinis and couldn't help but notice a group of other people at the end of the bar who didn't have drinks in front of them, and hadn't ordered anything the whole time they were there. One of the martini drinkers asks the bartender,

'What's with them?'

The bartender says, 'Oh, they are the Scottish Lotusscript developer caucus They're waiting for happy hour when drinks are half price.'


This is UNTRUE it was actually the English Home Counties C-API and Embroidery Group!


Appendix #1 Index to Scottish Words in this post

Teuchter - (pronounced Chew-ch-ter) a person from the north of Scotland

Sassenach - (pronounced Sass-en-ack) a person not from Scotland usually English

Tweetybird is 60!

Flex for Thick Gits #2 -MXML is not a Roman Date!

Right it is Saturday, there is no rugby worth the watching so what better way to spend the time - lets talk about MXML.

MXML is what you right FLEX apps in. (At this point i should mention that an AIR app is just a FLEX app that runs outside the browser using a runtime .. ok?) it is just ordinary common or garden XML that describes the application, once you have written the MXML you compile it and you have your FLEX application.

If you use FLEX BUILDER it takes a lot of the pain out of the "painting" of the application and I urge you to download it and try it, it will make your transistion into a FLEX developer so much easier that writing the MXML first hand.

OK lets look at some MXML



(Click Image to make bigger)

Since MXML is XML the first line of any application has to be
<?xml version="1.0"?>

This defines it as XML, you will note that it does not have a closing </xml> tag, this is fine so don't worry about it.

Next we have
<!-- DominoYesMayBe Is A Love God -->

This is a comment, you may want to make yours more meaningful, however if you feel you must extol my god like appearance to the world please feel free to do so ;-)

Next we have
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

This is the start of your MXML, everything to do with your application will happen between this opening tag and the corresponding closing tag </mx:Application>

Next we have
<mx:VBox>

This is the opening tag of a visual component called a vBox, it has to have a corresponding end tag of </mx:VBox> which you will see several lines further on.

Then there is
<mx:TextInput id="myText" text="Calypso Duck Snot" />

A TextInput is the visual equivalent of an HTML <input type='text'> input field. Note I have given it an ID of myText and some default text of "Capypso Duck Snot". Those eagled eyed folk will notice there is no closing tag for this item. Well the / before the > closes the tag so that you don't need a </mx:TextInput>

Also you will not that the vBox tags enclose the TextInput tag this means that visually the TextInput will be inside the vBox.

Both the vBox and the TextInput are neatly enclosed in the <mx:Application> tags. Thus placing them inside your application - This is as it should be for this is the Tao of XML :-)

OK.. in the next post we will create another little application and have a look at variables!

Friday 27 March 2009

Flex for Thick Gits - My version of a flex "hello world" first app - "Calypso Duck Snot"

Okey Dokey Peeps.

Flex what is it and how do I "do" it?
Good Question and hopefully this will be the first in a series of initially basic "how to" posts for the absolute beginner on how to do sexy things with flex.

So what is Flex? Flex is a highly productive FREE open source framework for building and maintaining sexy looking web applications that you can deploy on all major browsers (using the pervasive flash plugin) and desktops using the AIR runtime and like notes it can be deployed on most OS's

Now the first thing you can do is down load the Flex IDE called Flex builder currently at V3 this gives you a 60 day trial after which you have to buy it. So I hear you scream where is the FREE bit? Well you don't actually need Flex Builder as you can develop in a decent text editor, like Notepad++ .

I suggest you download Flex Builder and get all you can out of it during the Trial, as it will do all the boring bits for you and if you can't get the $$ for it you should have a decent grounding in the way the code is put together. The IDE is built around Eclipse so it should be familiar to devs who have moved up to the V8.5 designer client, but more on that in later posts.

So you have downloaded and installed your Trial of Flex Builder from the link above.. it is OK to do this even if you have the 8.5 DDE editor installed the two installs are separate and won't interfer with each other. You click on the chunky Flex Builder Icon on your desktop and voila it opens... (click on any of these piccies to make 'em BIG)



Now I will go into what does what in later posts for now lets just do the DominoYesMayBe version of a "Hello World" application. So Click FILE then NEW then FLEX PROJECT ...like this



and then you will get a nice dialog asking for a name and other things that will define the project.. for now just given it a name and click FINISH

... and your project will be created and ready for you to play with. The screen itself is a bit scary cos it comes up in script mode and that can be a bit intimidating because it starts ?XML which is enough to make some developers go pale and have palpitations :-)


Take a moment to compose yourself and click on the Design Tab, the screen should look like this


The big grey bit is your canvas onto which you will drag components and do your designing of the UI. So I drag a Button component from the list panel on the left and drop it on the grey canvas.



Over on the right i change the LABEL text for the button to have something more edifying than BUTTON. In this case "Click me Now".. (the actual text on the button will not change until you move focus away from the property field)



OK next I drag a LABEL from the component panel onto the canvas.. I size it using the corner anchors so that it is relatively large, then change

A) The ID of the label to be MyWord
B) I cleared the LABEL text.. cos I dont want it to say LABEL when the project starts
C) the Font Size to be 30pt

it looks like this ...



and that is it for my design.. now lets make the button do something.. switch to the SOURCE tab. You will notice that the source has changed.. These are the components and their properties that you have added to the canvas... it will look like this ...


Go down to the line that reads
<mx:Button x="59" y="31" label="Click Me Now" width="136"/>

and before the /> type this:
click="MyWord.text='Calypso Duck Snot';"

It should now look like this...


(BTW if you typed all the source into a notepad and used the SDK to compile it it would result in the same application!)

Ok you are ready to test it, so press [ctrl]+[s] or File then Save to save your project and then on the tool bar click the RUN button.



Your browser will open and there will be your button in all its glory ... Click it go on you know you want to... and when you do up pops CALYPSO DUCK SNOT in the label.

Here is my Version live on the interwebthingie .. (oh BTW you find all the files you need to go live in the bin-release folder of your project directory)

So that's it.. your first Flex App, it wasn't hard was it. In the next post I will try and a bit sexy with some more components and more events... WHAT FUN!

Ando Hiroshige - a mediation for troubled times.

We are in the teeth of the fiscal year end, the credit crunch is biting deeper everyday, jobs are evaporating and the world is going to hell in a hand basket, or so we the media tell us endlessly.

Is at times like these I visit one of my favourite artists and just let my eyes suck in the marks and splodges they made on paper or canvas. Long ago I gave up trying to understand art, now I look for the meaning I can see and what it means to me at the time I am looking at it. Today was one of those days and I dug out a book of pictures by Japanese artist Ando Hiroshige. Probably not a name you are familiar with but you should recognise this picture for it is arguably his most famous.


We cannot control our lifes. If we are set upon doing so we have abdicated ourselves from the peace that balances what is desired with what is possible. As Hiroshige shows us the great wave is in waiting for any boat. The wave is unpredictable, as uncontrollable now as it was at the dawn of time. We wonder will the slender boats and the fishermen in them survive or will they be overwhelmed? Risk is a human constant, it has to be accepted, embraced and then laid aside.

What we can do, we do.

Beyond that, we endure, our endurance framed by a sense of what matters and what does not. The worst that can happen is not that we may be overwhelmed by disaster but to look back in that final moment and realise that we did not live life.

We are fallible and the real antithesis of achieving peace is to refuse to recognise failure, to learn by our mistakes and to pick ourselves up and start again.......

......Anyhows Hiroshige painted his pictures between 1811 and 1858.

Here are some of my favourites Enjoy :-)




Stockholm Syndrome - all the way up to 11!

Monday 23 March 2009

** Hot News** UKLUG is open for registration!

OK Folks in the Yellow Bubble (tm)

The UKLUG Website is up and running and looking for folk to sign up as both Attendee's and Speakers. Warren Elsmore blogged about it here and you can rush over to the new sparkly wonderous xPage driven and skillfully crafted by Ideajam's Matt White web site here

There is no ILUG this year so attendance places will be in great demand, so i wouldn't leave it to late to book your place!

It is all happening on the 8th and 9th of October in Edinburgh, Scotland. I have my place booked and hopefully will see you all there!

Friday 20 March 2009

Arch Harridan Iris Robinson gets off

Arch harridan, MLA and wife of the First Minister of the Northern Ireland Assembly who I have ranted long and hard about in the past got official notification from the cops that
"On receipt of the advice of the Public Prosecution Service and considering all of the matters raised, the police service is satisfied that on the occasions considered, Mrs Robinson did not commit an offence,"


Sorry but WTF??

see here
for the story and other links on the Beeb.

I don't protest her having the views she has, she can believe that little purple pixies live inside her clit and give her orgasms for all I care. What I get very very very cross about is that she as a representative in high public office when she expresses her opinions it can and is construed as coming from her position as the Chair of the Stormont health committee

In summary she said that Homosexuality could be "turned around" with the help of a psychiatrist. Would I be surprised if a lot of people end up believing that someone in her position she might actually know what she is talking about? No of course I wouldn't!

How DARE she make value judgements on air and in the press that compare a legal, accepted form of human sexuality to the crimes of murder and child molestation.
Let her keep such idea to herself and keep the airing of such statements to the times when she is in the company of fellow Xtian wannabe sybarites who all ache for the luxury of an afterlife free of Catholics, Gay People and Sinn Fein.

You may have got away with any form of censorship or sanction this time Mrs Robinson but there are those that disagree with you and will continue to disagree with you and some of us will be as offensive about you as you are about others!

Oh and if you like to indulge in a lobster thermidor once in a while... be afraid be VERY afraid.. you will be next on Iris's hit list. I am sure she has a nice wee psychiatrist in her offices that will be able to "turn you around" too!

In regards to the lobsters I am referring to Leviticus “Whatsoever hath no fins nor scales in the waters, that shall be an abomination unto you.” In regards to male homosexuality: “Thou shalt not lie with mankind, as with womankind: it is abomination.” Both abominations to the Lord and using Iris's reasoning both in the same scale as child molestation and murder. You have been warned!

Monday 16 March 2009

RIA's xpages and Flex

I have of late being experimenting with Adobe Flex and xPages in V8.5.0 with a view to creating Rich Internet applications (RIAs). I started with both at roughly the same time and have spent roughly the same amount of effort on both. Now I have to stress I am not an expert in either so this is an opnion based on my experiences to date rather than an indepth exploration of the pros and cons of one or the other.

To be fair it is a bit of an "apples" and "oranges" comparison xpages is aimed (at the minute) fair and square at Domino Data and Domino apps where as Flex is data source agnostic, if you can get JSON or XML out of a data source Flex will be able to play with it.

Both Flex Builder 3 and xPages are based around Eclipse so the IDE is pretty much the same and there is no real difference when faced with developing in either. You can develope Flex apps in Notepad (or my favourite Notepad++) and use the Flex SDK to compile your project up but this is for REAL geeks!)

In Flex Builder you design your UI by dragging and dropping components from a palette onto the design area. there are 65 components and you can also create your own Custom Components. On an xPage same sort of idea except you only have a palette of 26 components.
and here comes my first whinge about xpages. It is a domino product, loads of apps have a requirement for a NAB lookups but no Name Picker in the components, you have to build your own using one or more of the databinding form components which isnt that hard but hey it would be nice to have a drag on one to save all the bother of doing that.

Flex has chart controls and OLAP grid control and two types of data grid and all sorts of interesting things xpages at the minute in 8.5.0 has either not got them or has them but you cant tweak them as much.

Which brings me to visual tweaking in xpages you have to play with the CSS and preview in all your target browsers to see what it looks like, in Flex you design on the screen and thats what it looks like for the user. Again some might say this is an unfair comparison as the two technologies are totally different and yes I accept that, but to drag and drop and tweak is easier and quciker than drag drop fiddle with CSS and preview.

I also have a fear that a lot of xpages are going to stay with the oneUI css and will suffer from the generic Xpage "look". This certainly makes development easier if you do that, but for me will start to wear thin as a look after a while. "themes" certainly sound like the answer but I have had all sort of bother getting a floating and fluid xpage to stick together and display on the browser with any sort of sucess.

Xpages bind to the back end domino data really well and with a minium of fuss and bother which is really sweet, and the new JS impliemented @commands are fantastic, needless to say Flex has none of these facilities nor ever will and xPages wins hands down in this respect as you have to build agents to serve the XML or JSON to the Flex App or take POSTED data and apply it, whilst not difficult it is time consuming and you don't have to do it in xPages.

There is a bit of learning curve for both Flex and xPages when adding the code that goes behind the buttons and switches etc and it is much of a muchness there in that they are equally difficult/easy to pick up the basics.

You need a V8.5 server and V8.5 Designer to create and run xpages, you can leverage Flex from any Domino server that serves up XML or JSON, which I believe is way back to 6.5 or before. I can hear some of you say "...but you MUST be on V8+ to be on anything less is just silly." well yes but there is and it seems has been an intertia in some if not all Domino sites to be one or two versions behind the cutting edge. At the minute those that have not upgraded could leverage Flex based UI's but can't leverage xPages. I would of course recommend all readers to upgrade :-) Version 8+ it is really very good.

Xpages of course is not dependant on the browser having any plugins flex needs Adobe Flash Player 9 or 10. However even allowing for Adobe's hyperbole the flash player does seem to be pervasive in the installed browsers attaching to the internet.

There doesn't appear to be any difference speed wise from a user perspective, although I would hazzard a guess that Flex is more bandwidth intensive when getting data from the server for views.

In conclusion having used both for around 3 months, I feel considerably less constrained in the way I design a RIA when I use Flex. Xpage development is locked in much closer to the domino data and is less flexible as a result. (or so it seems)

I am not giving up on Xpages ... as it matures, as I am sure it will, it will become much more of a lived in "environment" and better for it, however it would be foolish to overlook an environment that gives a better and more adaptable over all "finish" to a RIA.

This is of course my opnion, but I would suggest you have a look a Flex, particularly if you are stalled (for what ever reason) on version 7* or 6.5* with no immeadiate plans or budget to move up to Version 8*.

Some regex for the new to the Web programmer

I was asked today how on a web form you could check to see if an email address was correctly formatted before the form was submitted. Well with the advent of Xpages and the pervasiveness of AJAX frameworks, web pages in the Domino World, like any web faced back end are not exempt from the double requirement of being shiny sexy things that users love AND having functions that can stop users doing the stupid things they always do.

The question was posed by a RPG programmer new to the world of the web and when I said "och that's a piece of piss, use a RegEx" they looked at me like I had grown an extra head (which i do do on occasions for extra effect when I am being flash)

RegEx is short for Regular Expression
and is a string that describes a search pattern. *.txt is a RegEx that will be familiar to everyone. But proper RegEx is like that but on steroids, human growth hormone and crack cocaine.

There are loads of web sites that go into great detail about how to correctly form a RegEx and I will let you go find them yourself .. there is thing called Google and it is really useful ;-)

However how to use RegEx and a RegEx pattern to test an email address?

OK lets say you have this HTML on a form
Email Address <input type='text' name='email' value=''>
I am going to use this is a JS function that will return true or false if the email address entered is valid
function emailOK()
{
myRegEx = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
if (document.forms[0].email.value.search(myRegEx) != -1)
{
return true;
else
return false;
}
}
You will notice that I do NOT use a string literal surrounded by a pair of ""s for the myRegExp. Why? Because in a string literal \ is special (as in new line \n) so the RegEx expression \w+ would become "\\w+" in a sting literal which makes something that is very hard to read even harder to read. JS allows you to delimit RegEx's like this /pattern/ which makes things much nicer!

I pass this RegEx to the SEARCH method of the JS String object (which is what the .value of an input field is BTW) and it returns -1 is the pattern does not match or a positive integer if it does match. Which is all very simple BUT ... what does all that gooble-de-gook mean.. if you don't care .. then far enough, copy and paste the code and use it in your own app ;-) if you are curious here is what it means:

1. it begins with a / and the matching / is the very last character these act as the "" would in a normal string

2. The ^ symbol, means start matching at the absolute beginning of the string.

3. \w+ matches one or more alphanumeric characters.

4. This is where this gets interesting :-)
((-\w+)|(\.\w+))*
First, note that the whole thing is surrounded by (...)* which means that we want to match zero or more of whatever is inside.

Inside the ()* parentheses, we have (-\w+) and (\.\w+) separated by the | character This means it with match EITHER -\w+ OR \.\w+

The first one indicates that we should have a match if we find a hyphen followed immediately by a set of alphanumeric characters. The second part matches if we find a period followed immediately by a set of alphanumeric characters.

(NOTE . by itself is a special character so we must delimit it by placing a backslash in front of it.)

So far we have a pattern that will match [some alphanumerics]-[some alphanumerics] or [some aphanumerics].[some aphanumerics]

5. After this match, comes an \@ sign (once again i use \ to override any special meaning @ may have in RegEx

6. Immediately following the @ is [A-Za-z0-9]+ which matches a set of alphanumeric characters of either upper or lower case. I don't use \w+ because this would allow characters like _ and - ... OK?

7. next up is ((\.|-)[A-Za-z0-9]+)*

8. Note that the search is surround by ( ... )* this means we are matching one or none of a match to the pattern inside the ( ... )

9. So take them away and we are left with (\.|-)[A-Za-z0-9]+

10 First (\.|-) This is trying to match the first character as a . or a -

11. Then comes [A-Za-z0-9]+, the match only works if the period or hyphen is followed by a set of alphanumeric characters. This effectively represents an email address that contains a (possible) set of .something or -something sections. Because the * is used, the pattern works if they are present and also if they aren't.

12. Finally the \.[A-Za-z0-9]+ pattern matches a . followed by a set of alphanumerics. Because it is the last part of the regular expression, it represents the final part of the email address, which is the .com .co.uk bit.

13. The $ symbol ensures that the previous bit only matchs the END of the string.

14. The last character (the /) closes the first /

Simple .. init? ;-)

Tip of the Day- A JS way to create inline images to display from attachments in a Rich Text Field

Here is a wee Domino related JS tip.

Say you have a RT field into which users can attach files, these will in the natural schemem of things appear as a list of attachments with nice icons to click on. But what if you want to display them but couldn't be arsed coding in the domino bit of the form to get them to display as inline images.

01. Put a DIV tag around your RT field and give it an ID


<div id='imageRT'>[DominoRTField]</div>


03. Create an empty target [div] to display them in


<div id='imageDsp'></div>


04. Create a JS function in the form or page like this

function dspLinks()
{
target = document.getElementById("imageDsp");
imgLinks = document.getElementById("imageRT").getElementsByTagName("a")
for(t=0;t<imgLinks.length;t++)
{
imgLink = imgLinks[t].href;
img = document.createElement("img");
img.src = imgLink;
target.appendChild(img)
}
}


04. Put your dspLinks() function in the onload of the form and voila you have all the images in your RichText field displayed in the target div as well as the normal link icons you get from a RT Field's attachments.

Thursday 12 March 2009

Introducing the "Blue Skills" job site for IBMers

Okey Dokey.. here is a thing

Mr Mooney over at pmooney.net has just blogged a rather interesting prospect. He describes it way better than I will and with a lot less swear words. So take a trip over and have a look see both at Paul's post and at the beta site. Which Kevin Pettitt is currently trying to break.

To quote Paul
About a year ago, staff in Bluewave/BE Systems were discussing recruitment sites in general. Although mostly positive, the problems associated with them typically centred around inaccurate job specifications and vague applicant details. Also we noticed that there was a general inability to ask questions relevant to our specific areas of interest. We toyed with the idea of creating a dedicated careers site in the Big Blue field, focusing on finding the right people for the right jobs in our professional area.
Take a lookie see ;-)

Sunday 8 March 2009

I Love my job ! I love my job! I love my job!


It is March. The time for Fiscal Year End and Sarbanes Oxley Audits

Wednesday 4 March 2009

The latest Face Book Meme - The Which Mr Men are your friends (or how others see you)


This is doing the rounds on face book at the moment. You get it your mail box and each of the Mr & Miss folk has been tagged by one of your chums with a name they think "goes" with which Mr Man.

I have been "The one that gets up to no Good" twice now, and "The grumpy One" once!

Which i think is odd .. by inclination i would be "the geek", By appetite i am "the one thats always hungry", I would like to be "The Stylish one" or possibly "The Pimp".

But the one that is "Always up to no Good" ???

Posted by Picasa

Monday 2 March 2009

Introducing TiddlyWiki (well it was new to me!)

All .. i came across this a couple of weeks ago and it tweeked my inner geek. Anything that calls itself "a resuable non-linear personal web notebook" will make me cock an eyebrow and have a bit of an investigate.

Pop over to the tiddlywiki site and have a look see.
You can view TiddlyWiki files on all major desktop browsers on Windows, Macintosh and Linux and many mobile browsers such as the Apple iPhone and the Nokia 770/N800. You can save from all the major browsers (Sofaree and Oprah users need a wee plugin but IE and FF on winders saves changes after saying OK to an "are you sure message")

It is open source and really rather clever.

Config it in seconds bookmark it and you have a wiki style notebook that you can use on all of your tin to store your thoughts links and other stuff. I have it on my trusty ILUG08 memory stick, for those moments that server connectivity is just not possible.

It works .. I like it .. i am going to introduce it at work to see who likes it! Oh and have a look at the GTD variants like this one ...

Disqus for Domi-No-Yes-Maybe