The perfect Swiss Army Knife?
posted by robert | filed under uncategorized
This is fantastic – what more could you need? The people at Airstream and Victorinox have put their heads together and designed what really must be the perfect way to be totally mobile – the new Victorinox 125th Anniversary Special Edition Airstream:
It’s got the usual shiny Airstream body and looks wicked as it is. The design job on the inside tops it. The inside is very nicely finished and doesn’t look at all “caravan-like”.
Very nice design. Let the pictures speak for themselves:
Yes, that’s a nice big bed and there’s a separate shower – no showering over the toilet here…
I’ve often joked that I need a caravan to be able work in some of the locations that people suggest to me. With this little beauty I’d be only too happy to do so!
The downside: There will only be 125 of these produced and I can’t afford one
I also don’t know if they’ll be available in Europe – which is wierd when you think of the fact that Victorinox are certainly not American! Anybody know?
Maybe somebody from Airstream or Victorinox would like to give me one of these and I can travel around Europe in it writing a daily blog about life with an Airstream? hm?
By the way: You can cut apples with it too – there’s a set of Victorinox kitchen knives, watches and other goodies provided to the lucky buyer!
Refreshing, soft pixels
posted by robert | filed under uncategorized
Apparently, the only brief that London duo Ubik from Not To Scale had for this clip was “refresh, renewal, rejuvenation”. The result is spot on – refreshing. Starting with an empty swimming pool, pixelated ripples and then clouds appear. Pixel rain fills the pool to trigger the growth of a plethora of life. Marvellous
The short has been created for f5 festival in New York.
Very nice indeed! ![]()
How to be invisible (courtesy of Twitter)
posted by robert | filed under uncategorized
Nice call Twitter! Excellent idea. This’ll really further Twitter’s growth and popularity!
OK, enough sarcasm. Twitter seemed to have made a monumental decision sometime while I was offline and/or asleep. They have decided to not show public replies sent by friends to people they themselves are not following.
“So what?” I hear you say…
Well, it’s a pretty daft decision and reminiscent of the types of quick and dirty decisions that we’ve witnessed coming from Facebook before.
For most people the very essence of Twitter is that they find interesting information and new ideas from the Tweets they see in their “feed” – a feed of Tweets that comes from people they know, and follow, and those who they don’t know but are shown because somebody they already follow is privy to. This very ability to see new information and, as a result, find new people to follow based upon the themes they Tweet about, is one of (if not the main) the features that are behind the phenomenal growth that Twitter has seen over the last months.
Now they’ve switched it off. Not smart.
Here’s what Twitter user Scott Hepburn (@ScottHepburn) had to say about it:
Thank you Scott. Perfectly summed up!
Don’t take away the very features that make your platform usable.
It really does seem to me that a lot of tech start-ups in the social space are prone to making hasty decisions without really thinking them through. Users are not very forgiving – the competition is only a click away and people will look for other options.
Has the Twitter train run out of steam?
What goes around…
posted by robert | filed under uncategorized
…comes around. Very true.
I was recently impressed by a simple and yet very effective anti-war advertising campaign that uses this phrase together with some well-executed visuals to portray the futility of war in no-nonsense way. The posters are designed to be wrapped around posts and columns so that they join again to complete their message.
This is one poster from the series. Judge for yourself:
Or this one:
As I said: Simple, effective. War is futile.
MySQL: Append 0 values to end in sorts
posted by robert | filed under uncategorized
So, here’s a little challenge I had to address today: My Flash Application reads in an XML file with the positions of players in a race (Grand Prix feeling!) and then plots them, in the appropriate positions, on the race track. Fine so far.
It’s just possible that one of the players will be in the “pits”. This is indicated by a position of 0.
Simple enough: A basic PHP admin page allows positions to be entered and then builds the XML file for the flash after it’s added the player data to a MySQL database. To save some Flash processing I’ve sorted the rows in the players table and I’ll write the XML in the sorted numerical sequence.
Now, we all know that sorting a numeric field with values between, say, 0 and 12 will put the 0 values first in the list. This is not ideal as I want to show a score table populated from the XML file and would rather not have to sort at all in the Flash app (keep it light).
So how do we sort a numeric column in a MySQL SELECT statement and also “move” any 0 values to the end of the list?
Try this:
PHP:
$query = 'SELECT *, posn=0 AS isnull FROM player ORDER BY isnull ASC, posn ASC'; |
|
$player = mysql_query($query, $conn); |
Works a treat!
What we do, in addition to retrieving all of the table rows, is to retrieve the results of a condition as the “column” isnull:
posn=0 AS isnull
This results in the value of isnull being 1 (true) for any values of 0 and 0 (false) for other numerical values. Sort this “column” first and your 0 value rows will be listed at the end of the result set.
Happy coding!
Robert
Weekly Wordle #8
posted by robert | filed under uncategorized
It’s back!
After a period of bank holidays and short weeks the Weekly Wordle is back – and looking extremely geeky this week, I must say!
It’s not hard to see what I’ve been writing about most the last week or so ![]()
Have a good weekend all!
Robert
Coke gets fresh for the Summer
posted by robert | filed under uncategorized
Another design feature – this time new designs from Coca Cola for the summer. I particularly like the barbecue one ![]()
Seen on www.thedieline.com.
Adobe Creative Suite for only $80!
posted by robert | filed under uncategorized
Well, not THE Adobe Creative Suite but rather an extremely cool set of handmade pillows that would look fantastic gracing the sofas of any creative agency:

Here’s where you can find them: www.mysuitestuff.com
Shame they don’t offer international shipping yet!
How to GetFriends (and influence people?)
posted by robert | filed under uncategorized
The Facebook Actionscript 3.0 API is good. The documentation for the API is lacking. There are also several posts in the forum related to the API which don’t really help to clarify how to use certain features of the API. This doesn’t make things easier for otherwise clued-up developers who want to get to work with Facebook and Actionscript.
One example of this shroud of mystery is the use of GetFriends. I had posted a question about using this method, only to receive no response. After watching this video from Daniel Dura(thanks Daniel!) I had a good basic application running in Flex. The application logs into Facebook and retrieves the Name and Profile Picture for the logged user.
I suggest you watch the video and follow it through to arrive at the same basic example app – it’s nicely done and the app is nice and clean. It also works ![]()
I then set about extending it to retrieve the user’s friends. Here’s what I then did:
Firstly, add a call to a new function, getFriends(), just after assigning the user picture and name text in the complete() function. Your complete function should now look like this:
Code:
private function complete(event:FacebookEvent):void { |
|
var infoData:GetInfoData = GetInfoData(event.data); |
|
var user:FacebookUser = FacebookUser (infoData.userCollection.getItemAt(0)); |
|
|
|
userAvatar.source = user.pic_square; |
|
userName.text = user.name; |
|
|
|
getFriends(); |
|
|
|
|
|
} |
Please note that we have no error checking in here. See my previous post or the final code for this…
Line 8 above is our new function call.
Then, build the function to use the API method to retrieve all friends for the logged in user (implied by the fact that you made them log in):
Code:
private function getFriends():void { |
|
var call:FacebookCall = fbook.post(new GetFriends()); |
|
call.addEventListener(FacebookEvent.COMPLETE, gotFriends); |
|
} |
OK, no rocket science there… Then code the gotFriends function. This function will be triggered once the friends data has been returned:
Code:
private function gotFriends (event:FacebookEvent):void { |
|
var getFriendInfoData:GetFriendsData = GetFriendsData(event.data); |
|
friendArray = new ArrayCollection(); |
|
|
|
var len:uint = getFriendInfoData.friends.length; |
|
var friendIdArray:Array = new Array(); |
|
|
|
for(var i:uint = 0; i < len; i++) { |
|
friendIdArray.push(getFriendInfoData.friends.getItemAt(i).uid); |
|
|
|
} |
|
|
|
|
|
var call:FacebookCall = fbook.post(new GetInfo (friendIdArray,["first_name", "last_name"])); |
|
|
call.addEventListener(FacebookEvent.COMPLETE, gotFriendsInfo); |
|
|
} |
So, a little bit more code in there. Here’s what it does: Firstly, we extract the actual friends info data from the event data returned, casting it to the GetFriendsData class as we do so.
The next line, line 3, is referring to a public var declared for our app. make sure you declare this!
We then loop through the returned getFriendInfoData items (it’s basically an array) and assign the uid values to the array variable we’ve just declared, friendIdArray. The aim here is to build up an array of friend uid values for use in the next call: The GetInfo call.
We already used GetInfo to retrieve the name and profile picture for the logged in user. Now we’ll use it again to retrieve the names of all friends for whom we’ve saved a uid in the friendIdArray array. The first parameter into the GetInfo function call is an array of uid values. By passing in the array with all values already in it we can retrieve all names of all friends with one API call – and avoid a timeout or “limit exceeded” error from the API!
We then define an event listener to trigger once all of the information has been returned.
Now code the gotFriendsInfo function:
Code:
private function gotFriendsInfo (event:FacebookEvent):void { |
|
var getInfoData:GetInfoData = GetInfoData(event.data); |
|
var len:uint = getInfoData.userCollection.length; |
|
|
|
for(var i:uint = 0; i < len; i++) { |
|
var userFriend:FacebookUser = FacebookUser (getInfoData.userCollection.getItemAt(i)); |
|
userFriends.text += userFriend.first_name + " " + userFriend.last_name + "\n"; |
|
} |
|
} |
Again, cast the event data to the class we need – in this case getInfoData (as per the original tutorial). Then we loop through the results and retrieve the name values and, in this case, output them to a TextArea.
That’s it!
There’s no real mystery to the GetFriends API method once you’ve made it work. The exact same approach can then be applied to GetEvents and other API calls, simply ensuring that you cast the event.data returned to the correct class to use it further.
For those who would like the entire code, including the original tutorial contents, here’s mine (with added error checking):
Code:
<?xml version="1.0" encoding="utf-8"?> |
|
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> |
|
<mx:Script> |
|
<![CDATA[ |
|
import com.facebook.errors.FacebookError; |
|
import mx.messaging.channels.StreamingAMFChannel; |
|
import mx.collections.ArrayCollection; |
|
import com.facebook.Facebook; |
|
import mx.validators.ValidationResult; |
|
|
|
import com.facebook.net.FacebookCall; |
|
|
import mx.controls.Alert; |
|
|
import com.facebook.events.FacebookEvent; |
|
|
import com.facebook.utils.FacebookSessionUtil; |
|
|
import com.facebook.data.users.FacebookUser; |
|
|
import com.facebook.commands.users.GetInfo; |
|
|
import com.facebook.data.users.GetInfoData; |
|
|
import com.facebook.data.users.GetInfoFieldValues; |
|
|
import com.facebook.commands.friends.GetFriends; |
|
|
import com.facebook.data.friends.GetFriendsData; |
|
|
|
|
|
public var facebookSession:FacebookSessionUtil; |
|
|
public var fbook:Facebook; |
|
|
public var friendArray:ArrayCollection; |
|
|
public var eventsArray:ArrayCollection; |
|
|
|
|
|
public function login():void { |
|
|
facebookSession = new FacebookSessionUtil("<insert key>","<insert secret>",stage.loaderInfo); |
|
|
facebookSession.addEventListener(FacebookEvent.WAITING_FOR_LOGIN, waitLogin); |
|
|
facebookSession.addEventListener(FacebookEvent.CONNECT, connect); |
|
|
|
|
|
facebookSession.login(); |
|
|
} |
|
|
|
|
|
private function waitLogin(event:FacebookEvent):void { |
|
|
var alert:Alert = Alert.show("Click OK when you've logged in", "Logging into Facebook"); |
|
|
loginStatus.text = "Connecting"; |
|
|
alert.addEventListener(Event.CLOSE, doClose); |
|
|
} |
|
|
|
|
|
private function connect(event:FacebookEvent):void { |
|
|
fbook = facebookSession.facebook; |
|
|
var call:FacebookCall = fbook.post(new GetInfo([ fbook.uid ], [ GetInfoFieldValues.ALL_VALUES ])); |
|
|
call.addEventListener(FacebookEvent.COMPLETE, complete); |
|
|
} |
|
|
|
|
|
private function complete(event:FacebookEvent):void { |
|
|
if (event.success == true) { |
|
|
var infoData:GetInfoData = GetInfoData(event.data); |
|
|
var user:FacebookUser = FacebookUser (infoData.userCollection.getItemAt(0)); |
|
|
|
|
|
userAvatar.source = user.pic_square; |
|
|
userName.text = user.name; |
|
|
|
|
|
getFriends(); |
|
|
} else { |
|
|
traceError(event); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
private function getFriends():void { |
|
|
var call:FacebookCall = fbook.post(new GetFriends()); |
|
|
call.addEventListener(FacebookEvent.COMPLETE, gotFriends); |
|
|
} |
|
|
|
|
|
private function gotFriends (event:FacebookEvent):void { |
|
|
if (event.success == true) { |
|
|
var getFriendInfoData:GetFriendsData = GetFriendsData(event.data); |
|
|
friendArray = new ArrayCollection(); |
|
|
|
|
|
trace("getFriendInfoData.friends.length: " + getFriendInfoData.friends.length); |
|
|
var len:uint = getFriendInfoData.friends.length; |
|
|
var friendIdArray:Array = new Array(); |
|
|
|
|
|
for(var i:uint = 0; i < len; i++) { |
|
|
friendIdArray.push(getFriendInfoData.friends.getItemAt(i).uid); |
|
|
} |
|
|
|
|
|
var call:FacebookCall = fbook.post(new GetInfo (friendIdArray,["first_name", "last_name"])); |
|
|
call.addEventListener(FacebookEvent.COMPLETE, gotFriendsInfo); |
|
|
|
|
|
} else { |
|
|
traceError(event); |
|
|
} |
|
|
} |
|
|
|
|
|
private function gotFriendsInfo (event:FacebookEvent):void { |
|
|
|
|
|
if (event.success == true) { |
|
|
var getInfoData:GetInfoData = GetInfoData(event.data); |
|
|
var len:uint = getInfoData.userCollection.length; |
|
|
trace("Facebook friends retrieved "+len); |
|
|
|
|
|
for(var i:uint = 0; i < len; i++) { |
|
|
var userFriend:FacebookUser = FacebookUser (getInfoData.userCollection.getItemAt(i)); |
|
|
trace("Facebook Name: " + userFriend.first_name + " " + userFriend.last_name); |
|
|
userFriends.text += userFriend.first_name + " " + userFriend.last_name + "\n"; |
|
|
friendArray.addItem(userFriend.first_name + " " + userFriend.last_name); |
|
|
} |
|
|
} else { |
|
|
traceError(event); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
private function traceError(event:FacebookEvent):void { |
|
|
var errObj:FacebookError = FacebookError (event.error); |
|
|
trace("Facebook error "+errObj.errorMsg+", "+errObj.reason); |
|
|
} |
|
|
|
|
|
private function doClose(event:Event):void { |
|
|
facebookSession.validateLogin(); |
|
|
loginStatus.text = "Logged in"; |
|
|
loginButt.enabled = false; |
|
|
} |
|
|
|
|
|
]]> |
|
|
</mx:Script> |
|
|
|
|
|
<mx:Button id="loginButt" x="92" y="61" label="login" click="login()"/> |
|
|
<mx:Image id="userAvatar" x="174" y="61" width="50" height="50"/> |
|
|
<mx:Label id="userName" x="244" y="63" width="129"/> |
|
|
<mx:TextArea x="92" y="132" id="userFriends" width="281" height="155"/> |
|
|
<mx:Label x="92" y="94" width="74" id="loginStatus"/> |
|
|
|
|
|
</mx:WindowedApplication> |
My project is a Flex project for an AIR application. You can basically use this same code for a non-AIR Flex app, or reuse the Actionscript within the <mx:Script> tags within the Flash environment – just make sure you create the UI pieces and rename references in the code accordingly.
Hope this helps to clear up some of the confusion with GetFriends!
Robert


