Passing parameters to cappuccino applications that will last the infamous "Reload" button

Well, when I was asked the question "how can we save some variables when the user click on the "Reload" button", I had to scratch my head. I was also asking myself the question "How can I pass my cappuccino application some parameters when the application launch". On the desktop, we could use some command line parameters, but with web application, I had to read the CPApplication and CPCookie code to discover some hints.

CPApplication has support for "args" and "namedArguments"

What does this means ? arguments and named arguments ? Well, you should first read this page about window.location on the mozilla site.

I learned than :

The search part comes first, then comes the hash part. Both are naturally optionals.

index.html?test=1&cool=YES&cool=NO#param1%3Dvalue1/param2/param3%3DCappuccino%20%26%20Objective-J

With javascript we can have access to these variables with "window.location.hash" and "window.location.search". You have now eanough background to read the CPApplication code that deals with these magick variables.

In the cappuccino web framework, the "search" parameters are the "namedArguments" (a CPDictionary) and the "hash" part are the "args" (a CPArray).

You will discover in the source that you can register for logging by just adding "#debug" to your cappuccino application url, like: index.html#debug. Very efficient, modify the url and reload your application.

// Code from CPApplication if([args containsObject:"debug"]) CPLogRegister(CPLogPopup);

Retrieving args

Well you work hard and now your url contain a "hash" part. You can parse your hash in two line of code !

-(void)getArguments:(id)sender { var sharedApplication = [CPApplication sharedApplication]; var args = [sharedApplication arguments]; var enumerator = [args objectEnumerator]; var arg; while ((arg = [enumerator nextObject]) != nil) { console.log(arg); } }

Modifying args

Suppose that you want to store some variables in your application than can survive the fact that the user click on the "Reload" button. One of your option can be to use some cookies (more on than in the following chapters). The other option can be to use the hash part of the url. Another use of the hash could be to pass some parameters between your numerous cappuccino applications (for example in a link from one application to the other).

For this example, we will store "param1=value1", "param2" and "param3=Cappuccino & Objective-J". This will generate this url: index.html#param1%3Dvalue1/param2/param3%3DCappuccino%20%26%20Objective-J

-(void)setArguments:(id)sender { var sharedApplication = [CPApplication sharedApplication]; var args = [CPArray arrayWithObjects:@"param1=value1", @"param2", "param3=Cappuccino & Objective-J", nil]; [sharedApplication setArguments:args]; }

Retrieving namedArguments

Hey hey, if you store twice the same key in the "search" (like in index.html?test=1&cool=YES&cool=NO), you will have the last value. The keys will be "test" and "cool" with the following values : "1" and "NO".

-(void)getNamedArguments:(id)sender { var sharedApplication = [CPApplication sharedApplication]; var namedArguments = [sharedApplication namedArguments]; var enumerator = [namedArguments keyEnumerator]; var key; while ((key = [enumerator nextObject]) != nil) { var value = [namedArguments objectForKey:key]; console.log(key + " = " + value); } }

CPCookie, the small nasty thing in your browser

The cappuccino web framework has support for cookies. You shoud read the code in the CPCookie class. If you do so, you will discover a link to a web site describing how to use some cookie in your application. Read this information and you will known more about the cookie format, cookie domain and path, cookie expiration date. The domain is important, remember than "http://www.nice-panorama.com" and "http://nice-panorama.com" are NOT the same domain.

When I decided to test the CPCookie code, I also wanted to simplify the access to domain, path, expiration date. I also wanted to have the possibility to remove the cookies I created. So I wrote a small category to increase the behaviour of the current CPCookie class. You can found the small improvments in the file "CPCookie_Additions.j". You are free to use this source code, if you want, as it is under the double MIT and LGPL licence.

To create a new cookie that will last for some days, you can use these class methods (note the + for class methods):

// This will create a new cookie which will last for some days + (CPCookie)cookieWithName:(CPString)aName andValue:(CPString)aValue forDays:(int)days inDomain:(CPString)domain atPath:(CPString)path + (CPCookie)cookieWithName:(CPString)aName andValue:(CPString)aValue forDays:(int)days inDomain:(CPString)domain + (CPCookie)cookieWithName:(CPString)aName andValue:(CPString)aValue forDays:(int)days // This will create a new cookie which will last until the user quit the browser + (CPCookie)cookieWithName:(CPString)aName andValue:(CPString)aValue inDomain:(CPString)domain

To read some of your favourite cookies, you can use this method:

// This will create a cookie with the current stored value (if present) or an empty string (if not present) + (CPCookie) cookieWithName:(CPString)aName

To remove your old cookies, you can use this method:

// This will remove the cookie + (void) removeCookieWithName:(CSString)aName inDomain:(CPString)domain atPath:(CPString)path + (void) removeCookieWithName:(CSString)aName inDomain:(CPString)domain + (void) removeCookieWithName:(CSString)aName

On thing to remember is to create/remove the cookies in the same domain. If you create the cookie in one domain and try to remove it on another domain, well your cookie will still be there !

//Read the cookie var cookie1 = [[CPCookie alloc] initWithName:@"key1"]; // Modify the cookie var date = [CPDate dateWithTimeIntervalSinceNow:2*60*60]; // 2 hours in seconds [cookie1 setValue:@"value1" expires:date domain:@"nice-panorama.com"]; // Create a new cookie with the category method var cookie2 = [CPCookie cookieWithName:@"key2" andValue:@"value2" forDays:2 inDomain:@"nice-panorama.com"]; // Default domain (the one for the html page hosting the cappuccino application) // Default path "/" : the cookie will be accessible for the whole domain var cookie3 = [CPCookie cookieWithName:@"key3" andValue:@"value3" forDays:2]; // Read the cookie with the category method var cookie1 = [CPCookie cookieWithName:@"key1"]; console.log([cookie1 value]); // Remove the cookies [CPCookie removeCookieWithName:@"key1" inDomain:@"nice-panorama.com"]; [CPCookie removeCookieWithName:@"key2" inDomain:@"nice-panorama.com"]; [CPCookie removeCookieWithName:@"key3"];

Well enough of cookies, let's drink some cappuccino.

Support code and live application

I hope that you enjoyed discovering a new part of the cappuccino web framework.

If you'd like to see the complete code listing from the tutorial, you can download it all in a single file: Tutorial-CPCookie.zip. The web application is available online: Tutorial-CPCookie

Copyright © 2009 - Philippe Laval. Cappuccino and Objective-J are registered Trademarks of 280 North.