theChrisWalker.net

“Lithium RAD Framework rocks!”

says Chris

Archive for the ‘Code’ Category

QR Code for Permalink
Mongo — and the coolness of Document-Oriented Databases

without comments

I have been following a PHP Rapid Application Development Framework called Lithium with much interest (for other reasons which I fully intend to blog about later) and they are the ones I owe for turning me on to document oriented database systems.

So what are they and why are they so cool, and what/who the hell is “Mongo”?

Let’s deal with the what first. “Traditional” database systems are Relational, they are characterised by strictly defined tables, strong relations between tables and their ACID compliance. It simple terms that means you say:

“I want a table of users and each one will have a first name, a last name and an email address, and each of those will be a ‘text’ entry of a maximum of 255 characters”.

If at a later date you want to add more info, then you have to go back and alter your table definition, give the old rows default values and fix any coding bugs that relied on the previous structure (not that you’d ever develop such a dependant application). Now the approach in a document oriented database is that you say:

“I want a table of users”

Then you can give each one whatever data you want. you may have one user with a name and address, another with a name and phone number only, a third might have a phone number and address but no first name. All these records can co-exist! That’s pretty different and I really didn’t know whether it was a good idea. So I played with MongoDB.

MongoDB is really cool. I installed it my laptop simply and fired up the shell to play. The syntax is very javascript-like, becasue it is javascript! So we can do this.

MongoDB shell version: 1.3.3-
url: test
connecting to: test
type "help" for help
> db.myFirstMongoDB.save({key:"value", mixed:["one","two","three"], deep:{has:{another:"object"}}})
ObjectId("4b96b836ea70a136feb89c20")
> db.myFirstMongoDB.find()
{ "_id" : ObjectId("4b96b836ea70a136feb89c20"), "key" : "value",  "mixed" : [ "one", "two", "three" ],
   "deep" : { "has" : { "another" : "object" } } }
>

Notice two amazing things here.

  1. We never created the table! we simply call db.myFirstMongoDB… which creates the “collection” (as they are called in the document oriented world). We certainly never defined a schema!
  2. We passed an object with nested data. Not just simple fields! We can use this in a much more useful way in the next example

So why might you want to do this. Consider a website with articles. Articles are written by a person, they are published on a date and the have content, tags, comments, view counts, trackbacks, and a proprietary rating system. If this where a relational database, we are looking at the following tables:

articles: holds the article, date, person_id, view counts, proprietary rating
people: holds the writers
comments: the comments, related by article_id
trackbacks: link back details
ratings: the info for the proprietary system.
tags: tag info
tags_articles: a join table linking tags to the articles

Joining all that info together is not only complex, but can be a fair amount of load on the system. As more info wants to be added by the website owners changes become more complicated and difficult. However with Mongo I can hold the article in one collection like this:

[

{
  "published": "2010-03-09 21:21:00",
  "author": { "name": "Chris Walker", "profile": "/profiles/chris-walker" },
  "title": "My amazing Article",
  "content": "here's the text...",
  "tags": [ "wonder", "amazement", "mongo", "demo", "chris" ],
  "comments": [
    { "commenter": "Rosie", "comment": "What is this?", "when": "2010-03-09 22:02:00" },
    { "commenter": "Chris", "url": "http://thechriswalker.net/", "comment":"it's class, that's what!", "when": "2010-03-09 23:12:00" },
    { "commenter": "anonymous", "comment":"I am your father.", "when": "2010-03-10 01:25:20" }
  ],
  rating: { stars: 5, tagline: "what a monster!" },
  views: 1024,
  trackbacks: [
    { "url": "http://some.blog/some/where", "quote": "the text for the link"},
    { "url": "http://some.other.blog/some/where/else", "quote": "the text they used to link here"},
  ]
}

So that might look like a more complex entity. It is, but you can search for values in sub-documents, you can filter results on existence of certain keys, and you can pull all this info one result. Your previous 7 tables and 8 joins, just became 1 collection and no joins. guess which is quicker?

Try to pull articles with a certain tag: “balls”? In SQL you’d be doing this:

SELECT `article_id` FROM `tags_articles` `ta` JOIN `tags` `t` ON `ta`.`tag_id` = `t`.`id` WHERE `t`.`name` = 'balls'

And that would just get you the list of Id’s and you’d still need to get the info for each article. In Mongo with the collection we described above, you’d do:

db.articles.find({ tags: "balls"})

How much easier is that, and we’ve now got all the info, not just the “id”s! I was just amazed at how easy that is!

Of course this simplicity comes with a price, you lose the relational elements making tight relationships harder to work with. Also you some ease in aggregating things like “tags”, but MapReduce support makes this very efficient anyway.

In my next blog I’ll talk about Lithium, Mongo and how fast you can build a full blown web app with these tools.

Written by Chris

March 9th, 2010 at 9:44 pm

QR Code for Permalink
Xbox Live Gamercard API

without comments

So, got decided to join most of my friends and I got an Xbox 360. Me being me though, I got interested in the way that all the information about your “Gamertag” is stored an accessible on the xbox.com website. Wouldn’t it be fun to do something with this data!

As it turns out, I was beaten to the post by Duncan MacKensie (http://duncanmackenzie.net/Blog/put-up-a-rest-api-for-xbox-gamertag-data) who hosts a webservice to retrieve gamer data from Microsoft. I could find no details about how this service works, where the data comes from or anything! Either he has a relationship with Microsoft, or he scrapes xbox.com but either way, the data seems pretty consistent and reliable. Actually it turns out this information was right there on his website… http://www.duncanmackenzie.net/Blog/if-you-are-wondering-where-i-get-my-xbox-live-info So he gets it as part of his membership to the Xbox Community Developer Program.

However, the webservice is great, and returns XML which is fine, but I thought it would be more useful to me to have a PHP API for this data. So I wrote one which retrieves data from Duncans webservice.

Then I thought wouldn’t it be great to be able to use this dynamically in a webpage, so I wrote a service frontend which will return JSON formatted data. Then I thought wouldn’t it be useful to let other people use this as well, so I modified it and it can now cope with JSONP requests with a “_callback” parameter.

OK, so what does this all mean.

The PHP

The class is called gamertag and the usage is very simple:

<?php
// include the class file
require "gamertag.php";

//instantiate
$G = new Gamertag('thechriswalker');

//get data
$data = $G->getArray();

print_r($G);

which outputs something like this:

Array
(
    [Gamertag] => thechriswalker
    [AccountStatus] => Silver
    [State] => Valid
    [ProfileUrl] => http://live.xbox.com/member/thechriswalker
    [TileUrl] => http://avatar.xboxlive.com/avatar/thechriswalker/avatarpic-l.png
    [AvatarFullUrl] => http://avatar.xboxlive.com/avatar/thechriswalker/avatar-body.png
    [Country] => United Kingdom
    [Location] => Bradninch
    [Bio] =>
    [Reputation] => 58.72229
    [ReputationImageUrl] => http://live.xbox.com/xweb/lib/images/gc_repstars_external_12.gif
    [Zone] => Recreation
    [GamerScore] => 230
    [PresenceInfo] => Array
        (
            [Valid] => true
            [Info] => Last seen 12/29/09   playing Modern Warfare® 2
            [Info2] =>
            [LastSeen] => Tue, 29 Dec 2009 21:35:22 +0000
            [Online] => false
            [StatusText] => Offline
            [Title] => Modern Warfare® 2
        )

    [RecentGames] => Array
        (
            [0] => Array
                (
                    [Name] => Modern Warfare® 2
                    [TotalAchievements] => 50
                    [TotalGamerScore] => 1000
                    [Image32Url] => http://tiles.xbox.com/tiles/Z+/tF/12dsb2JgbA9ECgQJGgYfVl5UL2ljb24vMC84MDAwIAABAAAAAPhq63g=.jpg
                    [Image64Url] => http://tiles.xbox.com/tiles/CE/Vx/0Gdsb2JhbC9ECgQJGgYfVl5UL2ljb24vMC84MDAwAAAAAAAAAP9eRRc=.jpg
                    [LastPlayed] => Tue, 29 Dec 2009 21:32:52 +0000
                    [Achievements] => 9
                    [GamerScore] => 115
                    [DetailsURL] => http://live.xbox.com/en-US/profile/Achievements/ViewAchievementDetails.aspx?tid=%09%5d%3a%60m%2fl%3b%7cw&compareTo=thechriswalker
                )

            [1] => Array
                (
                    [Name] => PGR 4
                    [TotalAchievements] => 60
                    [TotalGamerScore] => 1250
                    [Image32Url] => http://tiles.xbox.com/tiles/Y1/qn/0Gdsb2JgbA9ECgR8GgMfWSlaL2ljb24vMC84MDAwIAABAAAAAP+IWnw=.jpg
                    [Image64Url] => http://tiles.xbox.com/tiles/DP/ST/12dsb2JhbC9ECgR8GgMfWSlaL2ljb24vMC84MDAwAAAAAAAAAPi89BM=.jpg
                    [LastPlayed] => Mon, 28 Dec 2009 16:59:25 +0000
                    [Achievements] => 5
                    [GamerScore] => 115
                    [DetailsURL] => http://live.xbox.com/en-US/profile/Achievements/ViewAchievementDetails.aspx?tid=%09%5d%3a%15%18*iAq%0b&compareTo=thechriswalker
                )

        )

)

So now we can easily get at the data. The source code for the class (which is not fully tested, but the basics work!) is at http://thechriswalker.net/xbox360/gamertag.source.php (NB it requires either PHP5 (for json_encode) or the PEAR Services_JSON class if you want to use the “getJSON()” method).

The JSON

PHP is well and good but what if I want to use a JSON/JSONP (JSONP is for cross-domain information requesting and is very useful for public information services, see http://en.wikipedia.org/wiki/JSON#JSONP) request, well, that can be done at http://thechriswalker.net/xbox360/?gamertag=YOUR_GAMERTAG for the straight JSON or http://thechriswalker.net/xbox360/?gamertag=YOUR_GAMERTAG&_callback=YOUR_CALLBACK_FUNCTION_NAME for JSONP.

The first returns just JSON with a content type “application/json” and the second returns a javascript function call to your callback function with the JSON object as the only parameter and a content type of “text/javascript”.

These enabled me to build a simple Google Gadget to display a Gamercard:


Written by Chris

December 31st, 2009 at 11:34 am

Posted in Code

Tagged with , , , ,

QR Code for Permalink
More WebKit Goodies - CSS Transforms and Transitions - the OSX Dock example

with 2 comments

As promised last time, I here we will discuss the transforms in WebKit, and how they can be used to create interactive applications without Javascript (for animation that is – we still need it for AJAX, etc.)

Tranforms have been implemented on a few browser using proprietary syntax, and the same is true of WebKit. As we shall see further down the article though, the WebKit transitions make them so much more powerful.

But what are they? They modify an element, without displacing it’s original setting within the document, which means we can move it about and the spacing doesn’t change.

Remember these will only work in WebKit based browsers, for example Safari for Mac, Chrome for Windows or Midori for Linux

An example: how about rotation.

element:hover {
  -webkit-transform:rotate(180deg);
}

Not very exciting, but combine this with a transition! (Try putting you mouse in the middle of the box for best effect)

element:hover {
  -webkit-transform:rotate(180deg);
}
element {
  -webkit-transition:-webkit-transform 1s linear
}

Much more useful! But there’s more, we can scale, we can translate (change its position on the screen) and also we can change the “center” for the transform. Usually the rotation happens from the center like above, but we could do it from closer to the left:

element:hover {
  -webkit-transform:rotate(180deg);
  -webkit-transform-origin:30% 50%;
}
element {
  -webkit-transition:-webkit-transform 1s linear;
  -webkit-transform-origin:30% 50%;
}

Or we could scale and move and rotate! (you might need to track it with you mouse to keep the animation! this is a demo after all!)

element:hover {
  -webkit-transform:rotate(180deg) scale(2) translate(-100%,0);
  -webkit-transform-origin:30% 50%;
}
element {
  -webkit-transition:-webkit-transform 1s linear;
  -webkit-transform-origin:30% 50%;
}

As the above eaxmple showed, hover is not always the best trigger for this. So lets use the :target pseudo-class. This is the pseudo-class that is applied when the element is the ‘target’ of an anchor/url hash. e.g:

<div id='hey-look-at-me'> <div id='untarget'> <pre>
CSS:
#hey-look-at-me:target pre {
  outline:2px solid red;
  color:#f0f;
}
#hey-look-at-me pre {
  -webkit-transition-property:outline, color;
  -webkit-transition-duration:500ms;
}
</pre> </div> </div>

target me! untarget me!

NB: Notice how I nested the PRE to stop unwanted excessive screen movement.

So, what can we do with all this? Well, the culmination of the post, the Mac OSX style Dock menu, using no Javascript. Yes, that’s right a bulging docked menu, with no javascript.

Just so you remember, there no javascript in the demo.

Check out the Javascript free OSX Dock Menu Demo.

Written by Chris

March 12th, 2009 at 7:44 pm

Posted in Code

Tagged with ,

QR Code for Permalink
Webkit CSS Transitions - pretty cool stuff

with 3 comments

I recently read somewhere about developing web applications for the iPhone / Android browsers that you shouldn’t use Javascript Frameworks (e.g. jQuery) for animation in your web apps but instead use CSS3 transitions. I had no idea what these where, so had to look it up. Turns out it’s pretty much a WebKit only thing, but that’s fine for iPhone (Safari) and Android (Chrome) Browsers.

But what is it? Simply put, it’s a way to create a transition between to CSS states (hope that cleared everything up for you!)

Better, an example: You have two CSS rules for an element, say a link, and for it’s :hover state. like this:

a {
    background:#eee;
    color:#333;
    text-decoration:none;
    padding:5px 10px;
    border:2px solid #333;
    border-radius: 5px;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
}
a:hover {
    background:#333;
    color:#eee;
}

Now usually, the browser would switch instantly between these two states, but with transitions we can slow it down into a smooth animation.

We can specify which propertys to transition and which to allow to change instantly. Here we can transition in the background and color properties.

a {
    background:#eee;
    color:#333;
    text-decoration:none;
    padding:5px 10px;
    border:2px solid #333;
    border-radius: 5px;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
     
    /* Add the transition properties! */
    -webkit-transition-property: background-color, color;
    -webkit-transition-duration: 600ms;
    /* you can control the acceleration curve here */
    -webkit-transition-timing-function: ease-in-out;
}
a:hover {
    background:#333;
    color:#eee;
}

Here’s two links, the they are identical except that the second has the transisions applied and if you’re using a WebKit based browser then it will fade nicely between states.

I will flick between states. Do I fade or do I flick?

Next time I’ll go into a bit more detail and show how using CSS Transforms as well we can make an OSX Dock style menu using CSS alone!

Written by Chris

March 10th, 2009 at 10:11 pm

Posted in Code

Tagged with ,

QR Code for Permalink
Multiple Drag and Drop between two lists with jQuery

with 77 comments

I wanted this functionality for a project a while ago. I google’d and found that lots of others did too, but no one had done it. Or at least not in a way that I could understand. In fact, I’m not sure I completely understand it anymore. It works very well, but also it could have some improvement. I would like to be able to drag the mouse to create a selection, but this in itself poses the difficultly of how to distinguish a “drag-to-move” from a “drag-to-select”.

Still I found it an interesting proof-of-concept and maybe you will too. The test can be found here: Select and Drag Demo.

Written by Chris

February 10th, 2009 at 12:26 pm

Posted in Code

Tagged with ,