Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Front-End Web Development

341 Articles
article-image-feeds-facebook-applications
Packt
16 Oct 2009
7 min read
Save for later

Feeds in Facebook Applications

Packt
16 Oct 2009
7 min read
{literal} What Are Feeds? Feeds are the way to publish news in Facebook. As we have already mentioned before, there are two types of feeds in Facebook, News feed and Mini feed. News feed instantly tracks activities of a user's online friends, ranging from changes in relationship status to added photos to wall comments. Mini feed appears on individuals' profiles and highlights recent social activity. You can see your news feed right after you log in, and point your browser to http://www.facebook.com/home.php. It looks like the following, which is, in fact, my news feed. Mini feeds are seen in your profile page, displaying your recent activities and look like the following one: Only the last 10 entries are being displayed in the mini feed section of the profile page. But you can always see the complete list of mini feeds by going to http://www.facebook.com/minifeed.php. Also the mini feed of any user can be accessed from http://www.facebook.com/minifeed.php?id=userid. There is another close relation between news feed and mini feed. When applications publish a mini feed in your profile, it will also appear in your friend's news feed page. How to publish Feeds Facebook provides three APIs to publish mini feeds and news feeds. But these are restricted to call not more than 10 times for a particular user in a 48 hour cycle. This means you can publish a maximum of 10 feeds in a specific user's profile within 48 hours. The following three APIs help to publish feeds: feed_publishStoryToUser—this function publishes the story to the news feed of any user (limited to call once every 12 hours). feed_publishActionOfUser—this one publishes the story to a user's mini feed, and to his or her friend's news feed (limited to call 10 times in a rolling 48 hour slot). feed_publishTemplatizedAction—this one also publishes mini feeds and news feeds, but in an easier way (limited to call 10 times in a rolling 48 hour slot). You can test this API also from http://developers.facebook.com/tools.php?api, and by choosing Feed Preview Console, which will give you the following interface: And once you execute the sample, like the previous one, it will preview the sample of your feed. Sample application to play with Feeds Let's publish some news to our profile, and test how the functions actually work. In this section, we will develop a small application (RateBuddies) by which we will be able to send messages to our friends, and then publish our activities as a mini feed. The purpose of this application is to display friends list and rate them in different categories (Awesome, All Square, Loser, etc.). Here is the code of our application: index.php<?include_once("prepend.php"); //the Lib and key container?><div style="padding:20px;"><?if (!empty($_POST['friend_sel'])){ $friend = $_POST['friend_sel']; $rating = $_POST['rate']; $title = "<fb:name uid='{$fbuser}' useyou='false' /> just <a href='http://apps.facebook.com/ratebuddies/'>Rated</a> <fb:name uid='{$friend}' useyou='false' /> as a '{$rating}' "; $body = "Why not you also <a href='http://apps.facebook.com/ratebuddies/'>rate your friends</a>?";try{//now publish the story to user's mini feed and on his friend's news feed $facebook->api_client->feed_publishActionOfUser($title, $body, null, $null,null, null, null, null, null, null, 1); } catch(Exception $e) { //echo "Error when publishing feeds: "; echo $e->getMessage(); }}?> <h1>Welcome to RateBuddies, your gateway to rate your friends</h1> <div style="padding-top:10px;"> <form method="POST"> Seect a friend: <br/><br/> <fb:friend-selector uid="<?=$fbuser;?>" name="friendid" idname="friend_sel" /> <br/><br/><br/> And your friend is: <br/> <table> <tr> <td valign="middle"><input name="rate" type="radio" value="funny" /></td> <td valign="middle">Funny</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="hot tempered" /></td> <td valign="middle">Hot Tempered</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="awesome" /></td> <td valign="middle">Awesome</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="naughty professor" /></td> <td valign="middle">Naughty Professor</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="looser" /></td> <td valign="middle">Looser</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="empty veseel" /></td> <td valign="middle">Empty Vessel</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="foxy" /></td> <td valign="middle">Foxy</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="childish" /></td> <td valign="middle">Childish</td> </tr> </table> &nbsp; <input type="submit" value="Rate Buddy"/> </form> </div></div> index.php includes another file called prepend.php. In that file, we initialized the facebook api client using the API key and Secret key of the current application. It is a good practice to keep them in separate file because we need to use them throughout our application, in as many pages as we have. Here is the code of that file: prepend.php<?php// this defines some of your basic setupinclude 'client/facebook.php'; // the facebook API library// Get these from ?http://www.facebook.com/developers/apps.phphttp://www.facebook.com/developers/apps.php$api_key = 'your api key';//the api ket of this application$secret = 'your secret key'; //the secret key$facebook = new Facebook($api_key, $secret); //catch the exception that gets thrown if the cookie has an invalid session_key in it try { if (!$facebook->api_client->users_isAppAdded()) { $facebook->redirect($facebook->get_add_url()); } } catch (Exception $ex) { //this will clear cookies for your application and redirect them to a login prompt $facebook->set_user(null, null); $facebook->redirect($appcallbackurl); }?> The client is a standard Facebook REST API client, which is available directly from Facebook. If you are not sure about these API keys, then point your browser to http://www.facebook.com/developers/apps.php and collect the API key and secret key from there. Here is a screenshot of that page: Just collect your API key and Secret Key from this page, when you develop your own application. Now, when you point your browser to http://apps.facebooks.com/ratebuddies and successfully add that application, it will look like this: To see how this app works, type a friend in the box, Select a friend, and click on any rating such as Funny or Foxy. Then click on the Rate Buddy button. As soon as the page submits, open your profile page and you will see that it has published a mini feed in your profile.
Read more
  • 0
  • 0
  • 4646

article-image-building-facebook-application-part-2
Packt
16 Oct 2009
11 min read
Save for later

Building a Facebook Application: Part 2

Packt
16 Oct 2009
11 min read
Mock AJAX and your Facebook profile I'm sure that you've heard of AJAX (Asynchronous JavaScript and XML) with which you can build interactive web pages. Well, Facebook has Mock AJAX, and with this you can create interactive elements within a profile page. Mock AJAX has three attributes that you need to be aware of: clickwriteform: The form to be used to process any data. clickwriteid: The id of a component to be used to display our data. clickwriteurl: The URL of the application that will process the data. When using Mock AJAX, our application must do two things: Return the output of any processed data (and we can do that by using either echo or print). Define a form with which we'll enter any data, and a div to receive the processed data Using a form on your profile Since we want to make our application more interactive, one simple way is to add a form. So, for our first example we can add a function (or in this case a set of functions) to appinclude.php that will create a form containing a simple combo-box: function country_combo () {/*You use this function to display a combo-box containing a list of countries. It's in its own function so that we can use it in other forms without having to add any extra code*/$country_combo = <<<EndOfText<select name=sel_country><option>England</option><option>India</option></select>EndOfText;return $country_combo;}function country_form () {/*Like country_combo-box we can use this form where ever needed because we've encapsulated it in its own function */global $appcallbackurl;$country_form = "<form>";$country_form .= country_combo ();$country_form .= <<<EndOfText<input type="submit" clickrewriteurl="$appcallbackurl" clickrewriteid="info_display" value="View Country"/><div id="info_display" style="border-style: solid; border-color: black; border-width: 1px; padding: 5px;">No country selected</div></form>EndOfText;return $country_form;}function display_simple_form () {/*This function displays the country form with a nice subtitle (on the Profile page)*/global $facebook, $_REQUEST;#Return any processed dataif (isset($_REQUEST['sel_country'])) { echo $_REQUEST['sel_country'] . " selected"; exit;}#Define the form and the div$fbml_text = <<<EndOfText<fb:subtitle><fb:name useyou=false uid=$user firstnameonly=true possessive=true> </fb:name> Suspect List</fb:subtitle>EndOfText;$fbml_text .= country_form ();$facebook->api_client->profile_setFBML($fbml_text, $user);echo $fbml_text;} And, of course, you'll need to edit index.php: display_simple_form (); You'll notice from the code that we need to create a div with the id info_display, and that this is what we use for the clickrewriteid of the submit button. You'll also notice that we're using $appcallbackurl for the clickrewriteurl ($appcallbackurl is defined in appinclude.php). Now, it's just a matter of viewing the new FMBL (by clicking on the application URL in the left-navigation panel): If you select a country, and then click on View Country, you'll see: I'm sure that you can see where we're going with this. The next stage is to incorporate this form into our Suspect Tracker application. And the great thing now is that because of the functions that we've already added to appinclude.php, this is now a very easy job: function first_suspect_tracker () {global $facebook, $_REQUEST;if (isset($_REQUEST['sel_country'])) { $friend_details = get_friends_details_ by_country ($_REQUEST['sel_country']); foreach ($friend_details as $friend) { $div_text .= "<fb:name uid=" . $friend['uid'] . " firstnameonly=false></fb:name>, "; } echo $div_text; exit;}$fbml_text .= country_form ();$facebook->api_client->profile_setFBML($fbml_text, $user);$facebook->redirect($facebook->get_facebook_url() . '/profile.php');} You may also want to change the country_form function, so that the submit button reads View Suspects. And, of course, we'll also need to update index.php. Just to call our new function: <?phprequire_once 'appinclude.php';first_suspect_tracker ();?> This time, we'll see the list of friends in the selected country: or: OK, I know what you're thinking, this is fine if all of your friends are in England and India, but what if they're not? And you don't want to enter the list of countries manually, do you? And what happens if someone from a country not in the list becomes your friend? Obviously, the answer to all of these questions is to create the combo-box dynamically. Creating a dynamic combo-box I'm sure that from what we've done so far, you can work out how to extract a list of countries from Facebook: function country_list_sql () {/*We're going to be using this piece of SQL quite often so it deserves its own function*/global $user;$country_list_sql = <<<EndSQLSELECT hometown_location.countryFROM userWHERE uid IN (SELECT uid1FROM friendWHERE uid2=$user)EndSQL;return $country_list_sql;}function full_country_list () {/*With the SQL in a separate function this one is very short and simple*/global $facebook;$sql = country_list_sql ();$full_country_list = $facebook-> api_client->fql_query($sql);print_r ($full_country_list);} However, from the output, you can see that there's a problem with the data: If you look through the contents of the array, you'll notice that some of the countries are listed more than once—you can see this even more clearly if we simulate building the combo-box: function options_country_list () {global $facebook;$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);foreach ($country_list as $country){ echo "option:" . $country['hometown_location']['country'] ."<br>";}} From which, we'd get the output: This is obviously not what we want in the combo-box. Fortunately, we can solve the problem by making use of the array_unique method, and we can also order the list by using the sort function: function filtered_country_list () {global $facebook;$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);$combo_full = array();foreach ($country_list as $country){ array_push($combo_full, $country['hometown_location']['country']);}$combo_list = array_unique($combo_full);sort($combo_list);foreach ($combo_list as $combo){ echo "option:" . $combo ."<br>";}} And now, we can produce a usable combo-box: Once we've added our code to include the dynamic combo-box, we've got the workings for a complete application, and all we have to do is update the country_combo function: function country_combo () {/*The function now produces a combo-box derived from the friends' countries */global $facebook;$country_combo = "<select name=sel_country>";$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);$combo_full = array();foreach ($country_list as $country){ array_push($combo_full, $country['hometown_location']['country']);}$combo_list = array_unique($combo_full);sort($combo_list);foreach ($combo_list as $combo){ $country_combo .= "<option>" . $combo ."</option>";}$country_combo .= "</select>";return $country_combo;} Of course, you'll need to reload the application via the left-hand navigation panel for the result: Limiting access to the form You may have spotted a little fly in the ointment at this point. Anyone who can view your profile will also be able to access your form and you may not want that (if they want a form of their own they should install the application!). However, FBML has a number of if (then) else statements, and one of them is <fb:if-is-own-profile>: <?phprequire_once 'appinclude.php';$fbml_text = <<<EndOfText<fb:if-is-own-profile>Hi <fb:name useyou=false uid=$user firstnameonly=true></fb:name>, welcome to your Facebook Profile page.<fb:else>Sorry, but this is not your Facebook Profile page - it belongs to <fb:name useyou=false uid=$user firstnameonly=false> </fb:name>,</fb:else></fb:if-is-own-profile>EndOfText;$facebook->api_client->profile_setFBML($fbml_text, $user);echo "Profile updated";?> So, in this example, if you were logged on to Facebook, you'd see the following on your profile page: But anyone else viewing your profile page would see: And remember that the FBML is cached when you run: $facebook->api_client->profile_setFBML($fbml_text, $user); Also, don't forget, it is not dynamic that is it's not run every time that you view your profile page. You couldn't, for example, produce the following for a user called Fred Bloggs: Sorry Fred, but this is not Your Facebook Profile page - it belongs to Mark Bain That said, you are now able to alter what's seen on the screen, according to who is logged on. Storing data—keeping files on your server From what we've looked at so far, you already know that you not only have, but need, files stored on your server (the API libraries and your application files). However, there are other instances when it is useful to store files there. Storing FBML on your server In all of the examples that we've worked on so far, you've seen how to use FBML mixed into your code. However, you may be wondering if it's possible to separate the two. After all, much of the FBML is static—the only reason that we include it in the code is so that we can produce an output. As well as there may be times when you want to change the FBML, but you don't want to have to change your code every time you do that (working on the principle that the more times you edit the code the more opportunity there is to mess it up). And, of course, there is a simple solution. Let's look at a typical form: <form><div id="info_display" style="border-style: solid; border-color: black; border-width: 1px; padding: 5px;"></div><input name=input_text><input type="submit" clickrewriteurl="http://213.123.183.16/f8/penguin_pi/" clickrewriteid="info_display" value="Write Result"></form> Rather than enclosing this in $fbml_text = <<<EndOfText ... EndOfText; as we have done before, you can save the FBML into a file on your server, in a subdirectory of your application. For example /www/htdocs/f8/penguin_pi/fbml/form_input_text.fbml. "Aha" I hear your say, "won't this invalidate the caching of FBML, and cause Facebook to access my server more often than it needs?" Well, no, it won't. It's just that we need to tell Facebook to update the cache from our FBML file. So, first we need to inform FBML that some external text needs to be included, by making use of the <fb:ref> tag, and then we need to tell Facebook to update the cache by using the fbml_refreshRefUrl method: function form_from_server () {global $facebook, $_REQUEST, $appcallbackurl, $user;$fbml_file = $appcallbackurl . "fbml/form_input_text.fbml";if (isset($_REQUEST['input_text'])) { echo $_REQUEST['input_text']; exit;}$fbml_text .= "<fb:ref url='" . $fbml_file . "' />";$facebook->api_client->profile_setFBML($fbml_text, $user);$facebook->api_client->fbml_refreshRefUrl($fbml_file);echo $fbml_text;} As far as your users are concerned, there is no difference. They'll just see another form on their profile page: Even if your users don't appreciate this leap forward, it will make a big difference to your coding—you're now able to isolate any static FBML from your PHP (if you want). And now, we can turn our attention to one of the key advantages of having your own server—your data. Storing data on your server So far, we've concentrated on how to extract data from Facebook and display it on the profile page. You've seen, for example, how to list all of your friends from a given country. However, that's not how Pygoscelis' list would work in reality. In reality, you should be able to select one of your friends and add them to your suspect list. We will, therefore, spend just a little time on looking at creating and using our own data. We're going to be saving our data in files, and so your first job must be to create a directory in which to save those files. Your new directory needs to be a subdirectory of the one containing your application. So, for example, on my Linux server I would do: cd /www/htdocs/f8/penguin_pi       #Move to the application directory mkdir data #Create a new directory chgrp www-data data                          #Change the group of the directory chmod g+w data                                  #Ensure that the group can write to data
Read more
  • 0
  • 0
  • 1140

article-image-find-closest-mashup-plugin-ruby-rails
Packt
16 Oct 2009
10 min read
Save for later

Find closest mashup plugin with Ruby on Rails

Packt
16 Oct 2009
10 min read
Building a kiosk locator feature for your site Your company has just deployed 500 multi-purpose payment kiosks around the country, cash cows for the milking. Another 500 more are on the way, promising to bring in the big bucks for all the hardworking employees in the company. Naturally your boss wants as many people as possible to know about them and use them. The problem is that while the marketing machine churns away on the marvels and benefits of the kiosks, the customers need to know where they are located to use them. He commands you: "Find a way to show our users where the nearest kiosks to him are, and directions to reach them!" What you have is a database of all the 500 locations where the kiosks are located, by their full address. What can you do? Requirements overview Quickly gathering your wits, you penned down the following quick requirements: Each customer who comes to your site needs to be able to find the closest kiosk to his or her current location. He or she might also want to know the closest kiosk to any location. You want to let the users determine the radius of the search. Finding the locations of the closest kiosks, you need to show him how to reach them. You have 500 kiosks now, (and you need to show where they are) but another 500 will be coming, in 10s and 20s, so the location of the kiosks need to be specified during the entry of the kiosks. You want to put all of these on some kind of map. Sounds difficult? Only if you didn't know about web mashups! Design The design for this first project is rather simple. We will build a simple database application using Rails and create a main Kiosk class in which to store the kiosk information including its address, longitude, and latitude information. After populating the database with the kiosk information and address, we will use a geolocation service to discover its longitude and latitude. We store the information in the same table. Next, we will take the kiosk information and mash it up with Google Maps and display the kiosks as pushpins on the online map and place its information inside an info box attached to each pushpin. Mashup APIs on the menu In this article we will be using the following services to create a 'find closest' mashup plugin: Google Maps APIs including geocoding services Yahoo geocoding services (part of Yahoo Maps APIs) Geocoder.us geocoding services Geocoder.ca geocoding services Hostip.info Google Maps Google Maps is a free web-based mapping service provided by Google. It provides a map that can be navigated by dragging the mouse across it and zoomed in and out using the mouse wheel or a zoom bar. It has three forms of views—map, satellite and a hybrid of map and satellite. Google Maps is coded almost entirely in JavaScript and XML and Google provides a free JavaScript API library that allows developers to integrate Google Maps into their own applications. Google Maps APIs also provide geocoding capabilities, that is, they able to convert addresses to longitude and latitude coordinates. We will be using two parts of Google Maps: Firstly to geocode addresses as part of GeoKit's APIs Secondly to display the found kiosk on a customized Google Maps map Yahoo Maps Yahoo Maps is a free mapping service provided by Yahoo. Much like Google Maps it also provides a map that is navigable in a similar way and also provides an extensive set of APIs. Yahoo's mapping APIs range from simply including the map directly from the Yahoo Maps website, to Flash APIs and JavaScript APIs. Yahoo Maps also provides geocoding services. We will be using Yahoo Maps geocoding services as part of GeoKit's API to geocode addresses. Geocoder.us Geocoder.us is a website that provides free geocoding of addresses and intersections in the United States. It relies on Geo::Coder::US, a Perl module available for download from the CPAN and derives its data from the TIGER/Line data set, public-domain data from the US Census Bureau. Its reliability is higher in urban areas but lower in the other parts of the country. We will be using Geocoder.us as part of GeoKit's API to geocode addresses. Geocoder.ca Geocoder.ca is a website that provides free geocoding of addresses in the United States and Canada. Like Geocoder.us. it uses data from TIGER/Line but in addition, draws data from GeoBase, the Canadian government-related initiative that provides geospatial information on Canadian territories. We will be using Geocoder.ca as part of GeoKit's API to geocode addresses. Hostip.info Hostip.info is a website that provides free geocoding of IP addresses. Hostip.info offers an HTTP-based API as well as its entire database for integration at no cost. We will be using Hostip.info as part of GeoKit's API to geocode IP addresses. GeoKit GeoKit is a Rails plugin that enables you to build location-based applications. For this article we will be using GeoKit for its geocoding capabilities in two ways: To determine the longitude and latitude coordinates of the kiosk from its given address To determine the longitude and latitude coordinates of the user from his or her IP address GeoKit is a plugin to your Rails application so installing it means more or less copying the source files from the GeoKit Subversion repository and running through an installation script that adds certain default parameters in your environment.rb file. To install the GeoKit, go to your Rails application folder and execute this at the command line: $./script/plugin install svn://rubyforge.org/var/svn/geokit/trunk This will copy the necessary files to your RAILS_ROOT/vendor/plugins folder and run the install.rb script. Configuring GeoKit After installing GeoKit you will need to configure it properly to allow it to work. GeoKit allows you to use a few sets of geocoding APIs, including Yahoo, Google, Geocoder.us, and Geocoder.ca. These geocoding providers can be used directly or through a cascading failover sequence. Using Yahoo or Google requires you to register for an API key but they are free. Geocoder.us is also free under certain terms and conditions but both Geocoder.us and Geocoder.ca have commercial accounts. In this article I will briefly go through how to get an application ID from Yahoo and a Google Maps API key from Google. Getting an application ID from Yahoo Yahoo's application ID is needed for any Yahoo web service API calls. You can use the same application ID for all services in the same application or multiple applications or one application ID per service. To get the Yahoo application ID, go to https://developer.yahoo.com/wsregapp/index.php and provide the necessary information. Note that for this application you don't need user authentication. Once you click on submit, you will be provided an application ID. Getting a Google Maps API key from Google To use Google Maps you will need to have a Google Maps API key. Go to http://www.google.com/apis/maps/signup.html. After reading the terms and conditions you will be asked to give a website URL that will use the Google Maps API. For geocoding purposes, this is not important (anything will do) but to display Google Maps on a website, this is important because Google Maps will not display if the URL doesn't match. However all is not lost if you have provided the wrong URL at first; you can create any number of API keys from Google. Configuring evironment.rb Now that you have a Yahoo application ID and a Google Maps API key, go to environment.rb under the RAILS_ROOT/config folder. Installing GeoKit should have added the following to your environment.rb file: # Include your application configuration below # These defaults are used in GeoKit::Mappable.distance_to and in acts_as_mappable GeoKit::default_units = :miles GeoKit::default_formula = :sphere # This is the timeout value in seconds to be used for calls to the geocoder web # services. For no timeout at all, comment out the setting. The timeout unit is in seconds. # GeoKit::Geocoders::timeout = 3 # These settings are used if web service calls must be routed through a proxy. # These setting can be nil if not needed, otherwise, addr and port must be filled in at a minimum. If the proxy requires authentication, the username and password can be provided as well. GeoKit::Geocoders::proxy_addr = nil GeoKit::Geocoders::proxy_port = nil GeoKit::Geocoders::proxy_user = nil GeoKit::Geocoders::proxy_pass = nil # This is your yahoo application key for the Yahoo Geocoder # See http://developer.yahoo.com/faq/index.html#appid and http://developer.yahoo.com/maps/rest/V1/geocode.html GeoKit::Geocoders::yahoo = <YOUR YAHOO APP ID> # This is your Google Maps geocoder key. # See http://www.google.com/apis/maps/signup.html and http://www.google.com/apis/maps/documentation/#Geocoding_Examples GeoKit::Geocoders::google = <YOUR GOOGLE MAPS KEY> # This is your username and password for geocoder.us # To use the free service, the value can be set to nil or false. For usage tied to an account, the value should be set to username:password. # See http://geocoder.us and http://geocoder.us/user/signup GeoKit::Geocoders::geocoder_us = false # This is your authorization key for geocoder.ca. # To use the free service, the value can be set to nil or false. For usage tied to an account, set the value to the key obtained from Geocoder.ca # See http://geocoder.ca and http://geocoder.ca/?register=1 GeoKit::Geocoders::geocoder_ca = false # This is the order in which the geocoders are called in a failover scenario # If you only want to use a single geocoder, put a single symbol in the array. # Valid symbols are :google, :yahoo, :us, and :ca # Be aware that there are Terms of Use restrictions on how you can use the various geocoders. Make sure you read up on relevant Terms of Use for each geocoder you are going to use. GeoKit::Geocoders::provider_order = [:google,:yahoo] Go to the lines where you are asked to put in the Yahoo and Google keys and change the values accordingly. Make sure the keys are within apostrophes. Then go to the provider order and put in the order you want (the first will be tried; if that fails it will go to the next until all are exhausted): GeoKit::Geocoders::provider_order = [:google,:yahoo] This completes the configuration of GeoKit. YM4R/GM YM4R/GM is another Rails plugin, one that facilitates the use of Google Maps APIs. We will be using YM4R/GM to display the kiosk locations on a customized Google Map. This API essentially wraps around the Google Maps APIs but also provides additional features to make it easier to use from Ruby. To install it, go to your Rails application folder and execute this at the command line: $./script/plugin install svn://rubyforge.org/var/svn/ym4r/Plugins/GM/trunk/ym4r_gm During the installation, the JavaScript files found in the RAILS_ROOT/vendors/plugin/javascript folder will be copied to the RAILS_ROOT/public/javascripts folder. A gmaps_api_key.yml file is also created in the RAILS_ROOT/config folder. This file is a YAML representation of a hash, like the database.yml file in which you can set up a test, development, and production environment. This is where you will put in your Google Maps API key (in addition to the environment.rb you have changed earlier). For your local testing you will not need to change the values but once you deploy this in production on an Internet site you will need to put in a real value according to your domain.
Read more
  • 0
  • 0
  • 1822
Banner background image
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at £15.99/month. Cancel anytime
article-image-creating-administration-interface-django
Packt
16 Oct 2009
5 min read
Save for later

Creating an Administration Interface in Django

Packt
16 Oct 2009
5 min read
Activating the Administration Interface The administration interface comes as a Django application. To activate it, we will follow a simple procedure that is similar to how we enabled the user authentication system. The admininistration application is located in the django.contrib.admin package. So the first step is adding the path of this package to the INSTALLED_APPS variable. Open settings.py, locate INSTALLED_APPS and edit it as follows: INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.comments', 'django_bookmarks.bookmarks',) Next, run the following command to create the necessary tables for the administration application: $ python manage.py syncdb Now we need to make the administration interface accessible from within our site by adding URL entries for it. The administration application defines many views, so manually adding a separate entry for each view can become a tedious task. Therefore, Django provides a shortcut for this. The administration interface defines all of its URL entries in a module located at django.contrib.admin.urls, and we can include these entries in our project under a particular path by using a function called include(). Open urls.py and add the following URL entry to it: urlpatterns = ( # Admin interface (r'^admin/', include('django.contrib.admin.urls')),) This looks different from how we usually define URL entries. We are basically telling Django to retrieve all of the URL entries in the django.contrib.admin.urls module, and to include them in our application under the path ^admin/. This will make the views of the administration interface accessible from within our project. One last thing remains before we see the administration page in action. We need to tell Django what models can be managed in the administration interface. This is done by defining a class called Admin inside each model. Open bookmarks/models.py and add the highlighted section to the Link model: class Link(models.Model): url = models.URLField(unique=True) def __str__(self): return self.url class Admin: pass The Admin class defined inside the model effectively tells Django to enable the Link model in the administration interface. The keyword pass means that the class is empty. Later, we will use this class to customize the administration page, so it won't remain empty. Do the same to the Bookmark, Tag and SharedBookmark models; append an empty class called Admin to each of them. The User model is provided by Django and therefore we don't have control over it. Fortunately however, it already contains an Admin class so it's available in the administration interface by default. Next, launch the development server and direct your browser to http://127.0.0.1:8000/admin/. You will be greeted by a login page. Remember we need to create a superuser account after writing the database model. This is the account that you have to use in order to log in: Next, you will see a list of the models that are available to the administration interface. As discussed earlier, only models with a class named Admin inside them will appear on this page: If you click on a model name, you will get a list of the objects that are stored in the database under this model. You can use this page to view or edit a particular object, or to add a new one. The figure below shows the listing page for the Link model. The edit form is generated according to the fields that exist in the model. The Link form, for example, contains a single text field called Url. You can use this form to view and change the URL of a Link object. In addition, the form performs proper validation of fields before saving the object. So if you try to save a Link object with an invalid URL, you will receive an error message asking you to correct the field. The figure below shows a validation error when trying to save an invalid link: Fields are mapped to form widgets according to their type. Date fields are edited using a calendar widget for example, whereas foreign key fields are edited using a list widget, and so on. The figure below shows a calendar widget from the user edit page. Django uses it for date and time fields: As you may have noticed, the administration interface represents models by using the string returned by the __str__ method. It was indeed a good idea to replace the generic strings returned by the default __str__ method with more helpful ones. This greatly helps when working with the administration page, as well as with debugging. Experiment with the administration pages; try to create, edit and delete objects. Notice how changes made in the administration interface are immediately reflected on the live site. Also, the administration interface keeps track of the actions that you make, and lets you review the history of changes for each object. This section has covered most of what you need to know in order to use the administration interface provided by Django. This feature is actually one of the main advantages of using Django; you get a fully featured administration interface from writing only a few lines of code! Next, we will see how to tweak and customize the administration pages. And as a bonus, we will learn more about the permissions system offered by Django.
Read more
  • 0
  • 0
  • 2378

article-image-building-facebook-application-part-1
Packt
14 Oct 2009
4 min read
Save for later

Building a Facebook Application: Part 1

Packt
14 Oct 2009
4 min read
A simple Facebook application Well, with the Facebook side of things set up, it's now over to your server to build the application itself. The server could of course be: Your web host's server – This must support PHP, and it may be worthwhile for you to check if you have any bandwidth limits. Your own server – Obviously, you'll need Apache and PHP (and you'll also need a fixed IP address). Getting the server ready for action Once you have selected your server, you'll need to create a directory in which you'll build your application, for example: mkdir -p /www/htdocs/f8/penguin_picd /www/htdocs/f8/penguin_pi If you haven't already done so, then this is the time to download and uncompress the Facebook Platform libraries: wget http://developers.facebook.com/clientlibs/facebook-platform.tar.gztar -xvzf facebook-platform.tar.gz We're not actually going to use all of the files in the library, so you can copy the ones that you're going to use into your application directory: cp facebook-platform/client/facebook.phpcp facebook-platform/client/facebookapi_php5_restlib.php And once that's done, you can delete the unwanted files: rm -rf facebook-platform.tar.gz facebook-platform Now, you're ready to start building your application. Creating your first Facebook application Well, you're nearly ready to start building your application. First, you'll need to create a file (let's call it appinclude.php) that initiates the application. The application initiation code We've got some code that needs to be executed every time our application is accessed, and that code is: <?phprequire_once 'facebook.php'; #Load the Facebook API$appapikey = '322d68147c78d2621079317b778cfe10'; #Your API Key$appsecret = '0a53919566eeb272d7b96a76369ed90c'; #Your Secret$facebook = new Facebook($appapikey, $appsecret); #A Facebook object$user = $facebook->require_login(); #get the current user$appcallbackurl = 'http://213.123.183.16/f8/penguin_pi/'; #callback Url#Catch an invalid session_keytry { if (!$facebook->api_client->users_isAppAdded()) { $facebook->redirect($facebook->get_add_url()); }} catch (Exception $ex) { #If invalid then redirect to a login prompt $facebook->set_user(null, null); $facebook->redirect($appcallbackurl);}?> You'll notice that the code must include your API Key and your secret (they were created when you set up your application in Facebook). The PHP file also handles any invalid sessions. Now, you're ready to start building your application, and your code must be written into a file named index.php. The application code Our application code needs to call the initiation file, and then we can do whatever we want: <?phprequire_once 'appinclude.php'; #Your application initiation fileecho "<p>Hi $user, ";echo "welcome to Pygoscelis P. Ellsworthy's Suspect Tracker</p>";?> Of course, now that you've written the code for the application, you'll want to see what it looks like. Viewing the new application Start by typing your Canvas Page URL into a browser (you'll need to type in your own, but in the case of Pygoscelis P. Ellesworthy's Suspect Tracker, this would be http://apps.facebook.com/penguin_pi/): You can then add the application just as you would add any other application: And at last, you can view your new application: It is worth noting, however, that you won't yet be able to view your application on your profile. For the time being, you can only access the application by typing in your Canvas Page URL. That being said, your profile will register the fact that you've added your application: That's the obligatory "Hello World" done. Let's look at how to further develop the application.
Read more
  • 0
  • 0
  • 1214

article-image-seam-data-validation
Packt
09 Oct 2009
8 min read
Save for later

Seam Data Validation

Packt
09 Oct 2009
8 min read
Data validation In order to perform consistent data validation, we would ideally want to perform all data validation within our data model. We want to perform data validation in our data model so that we can then keep all of the validation code in one place, which should then make it easier to keep it up-to-date if we ever change our minds about allowable data values. Seam makes extensive use of the Hibernate validation tools to perform validation of our domain model. The Hibernate validation tools grew from the Hibernate project (http://www.hibernate.org) to allow the validation of entities before they are persisted to the database. To use the Hibernate validation tools in an application, we need to add hibernate-validator.jar into the application's class path, after which we can use annotations to define the validation that we want to use for our data model. Let's look at a few validations that we can add to our sample Seam Calculator application. In order to implement data validation with Seam, we need to apply annotations either to the member variables in a class or to the getter of the member variables. It's good practice to always apply these annotations to the same place in a class. Hence, throughout this article, we will always apply our annotation to the getter methods within classes. In our sample application, we are allowing numeric values to be entered via edit boxes on a JSF form. To perform data validation against these inputs, there are a few annotations that can help us. Annotation Description @Min The @Min annotation allows a minimum value for a numeric variable to be specified. An error message to be displayed if the variable's value is less than the specified minimum can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be greater than or equal to ...). @Min(value=0, message="...") @Max The @Max annotation allows a maximum value for a numeric variable to be specified. An error message to be displayed if the variable's value is greater than the specified maximum can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be less than or equal to ...). @Max(Value=100, message="...") @Range The @Range annotation allows a numeric range-that is, both minimum and maximum values-to be specified for a variable. An error message to be displayed if the variable's value is outside the specified range can also be specified. The message parameter is optional. If it is not specified, then a sensible error message will be generated (similar to must be between ... and ...). @Range(min=0, max=10, message="...") At this point, you may be wondering why we need to have an @Range validator, when by combining the @Min and @Max validators, we can get a similar effect. If you want a different error message to be displayed when a variable is set above its maximum value as compared to the error message that is displayed when it is set below its minimum value, then the @Min and @Max annotations should be used. If you are happy with the same error message being displayed when a variable is set outside its minimum or maximum values, then the @Range validator should be used. Effectively, the @Min and @Max validators are providing a finer level of error message provision than the @Range validator. The following code sample shows how these annotations can be applied to a sample application, to add basic data validation to our user inputs. package com.davidsalter.seamcalculator; import java.io.Serializable; import org.jboss.seam.annotations.Name; import org.jboss.seam.faces.FacesMessages; import org.hibernate.validator.Max;import org.hibernate.validator.Min;import org.hibernate.validator.Range; @Name("calculator") public class Calculator implements Serializable { private double value1; private double value2; private double answer; @Min(value=0) @Max(value=100) public double getValue1() { return value1; } public void setValue1(double value1) { this.value1 = value1; } @Range(min=0, max=100) public double getValue2() { return value2; } public void setValue2(double value2) { this.value2 = value2; } public double getAnswer() { return answer; } ... } Displaying errors to the user In the previous section, we saw how to add data validation to our source code to stop invalid data from being entered into our domain model. Now that we have reached a level of data validation, we need to provide feedback to the user to inform them of any invalid data that they have entered. JSF applications have the concept of messages that can be displayed associated with different components. For example, if we have a form asking for a date of birth to be entered, we could display a message next to the entry edit box if an invalid date were entered. JSF maintains a collection of these error messages, and the simplest way of providing feedback to the user is to display a list of all of the error messages that were generated as a part of the previous operation. In order to obtain error messages within the JSF page, we need to tell JSF which components we want to be validated against the domain model. This is achieved by using the <s:validate/> or <s:validateAll/> tags. These are Seam-specific tags and are not a part of the standard JSF runtime. In order to use these tags, we need to add the following taglib reference to the top of the JSF page. <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %> In order to use this tag library, we need to add a few additional JAR files into the WEB-INF/lib directory of our web application, namely: jboss-el.jar jboss-seam-ui.jar jsf-api.jar jsf-impl.jar This tag library allows us to validate all of the components (<s:validateAll/>) within a block of JSF code, or individual components (<s:validate/>) within a JSF page. To validate all components within a particular scope, wrap them all with the <s:validateAll/> tag as shown here: <h:form> <s:validateAll> <h:inputText value="..." /> <h:inputText value="..." /> </s:validateAll> </h:form> To validate individual components, embed the <s:validate/> tag within the component, as shown in the following code fragment. <h:form> <h:inputText value="..." > <s:validate/> </h:inputText> <h:inputText value="..." > <s:validate/> </h:inputText> </h:form> After specifying that we wish validation to occur against a specified set of controls, we can display error messages to the user. JSF maintains a collection of errors on a page, which can be displayed in its entirety to a user via the <h:messages/> tag. It can sometimes be useful to show a list of all of the errors on a page, but it isn't very useful to the user as it is impossible for them to say which error relates to which control on the form. Seam provides some additional support at this point to allow us to specify the formatting of a control to indicate error or warning messages to users. Seam provides three different JSF facets (<f:facet/>) to allow HTML to be specified both before and after the offending input, along with a CSS style for the HTML. Within these facets, the <s:message/> tag can be used to output the message itself. This tag could be applied either before or after the input box, as per requirements. Facet Description beforeInvalidField This facet allows HTML to be displayed before the input that is in error. This HTML could contain either text or images to notify the user that an error has occurred. <f:facet name="beforeInvalidField"> ... </f:facet> afterInvalidField This facet allows HTML to be displayed after the input that is in error. This HTML could contain either text or images to notify the user that an error has occurred. <f:facet name="afterInvalidField"> ... </f:facet> aroundInvalidField This facet allows the CSS style of the text surrounding the input that is in error to be specified. <f:facet name="aroundInvalidField"> ... </f:facet> In order to specify these facets for a particular field, the <s:decorate/>  tag must be specified outside the facet scope. <s:decorate> <f:facet name="aroundInvalidField"> <s:span styleClass="invalidInput"/> </f:facet> <f:facet name="beforeInvalidField"> <f:verbatim>**</f:verbatim> </f:facet> <f:facet name="afterInvalidField"> <s:message/> </f:facet> <h:inputText value="#{calculator.value1}" required="true" > <s:validate/> </h:inputText> </s:decorate> In the preceding code snippet, we can see that a CSS style called invalidInput is being applied to any error or warning information that is to be displayed regarding the <inputText/> field. An erroneous input field is being adorned with a double asterisk (**) preceding the edit box, and the error message specific to the inputText field after is displayed in the edit box.
Read more
  • 0
  • 0
  • 1593
article-image-slider-dynamic-applications-using-scriptaculous-part-1
Packt
08 Oct 2009
5 min read
Save for later

Slider for Dynamic Applications using script.aculo.us (part 1)

Packt
08 Oct 2009
5 min read
Before we start exploring the slider, let me try to give you a complete picture of its functionality with a simple example. Google Finance uses a horizontal slider, showing the price at a given day, month, and year. Although this particular module is built in Flash, we can build a similar module using the script.aculo.us slider too. To understand the concept and how it works, look at the following screenshot: Now that we have a clear understanding of what the slider is and how it appears in UI, let's get started! First steps with slider As just explained, a slider can handle a single value or a set of values. It's important to understand at this point of time that unlike other features of script.aculo.us, a slider is used in very niche applications for a specific functionality. The slider is not just mere functionality, but is the behavior of the users and the application. A typical constructor syntax definition for the slider is shown as follows: new Control.Slider(handle, track [ , options ] ); Track mostly represents the <div> element. Handle represents the element inside the track and, as usual, a large number of options for us to fully customize our slider. For now, we will focus on understanding the concepts and fundamentals of the slider. We will surely have fun playing with code in our Code usage for the slider section. Parameters for the slider definition In this section we will look at the parameters required to define the slider constructor: track in a slider represents a range handle in a slider represents the sliding along the track, that is, within a particular range and holding the current value options in a slider are provided to fully customize our slider's look and feel as well as functionality It's time to put the theory into action. We need the appropriate markup for working with the slider. We have <div> for the track and one <div> for each handle. The resulting code should look like the snippet shown as follows: <div id="track"><div id="handle1"></div></div> It is possible to have multiple handles inside a single track. The following code snippet is a simple example: <div id="track"><div id="handle1"></div><div id="handle2"></div></div> Options with the slider Like all the wonderful features of script.aculo.us, the slider too comes with a large number of options that allow us to create multiple behaviours for the slider. They are: Axis: This defines the orientation of the slider. The direction of movement could be horizontal or vertical. By default it is horizontal. Increment: This defines the relation between value and pixels. Maximum: This is the maximum value set for the slider to move to. While using a vertical slider from top-to-bottom, the bottom most value will be the maximum. And for a horizontal slider from left-to-right, the right most value will be the maximum value. Minimum: This is the minimum value set for the slider to move to. While using a vertical slider from top-to-bottom, the top most value will be the minimum. And for a horizontal slider from left-to-right, the left most value will be the minimum value approach for horizontal slider. Range: This is the fixed bandwidth allowed for the values. Define the minimum and maximum values. Values: Instead of a range, pass a set of values as an array. SliderValue: This sets the initial value of the slider. If not set, will take the extreme value of the slide as the default value. Disabled: As the name suggests, this disables the slider functionality. Some of the functions offered by the slider are: setValue:This will set the value of the slider directly and move it to the value position. setDisabled: This defines that the slider is disabled at runtime. setEnabled: This can enable the slider at runtime. Some of the callbacks supported by the slider are: onSlide: This is initiated on every slide movement. The called function would get the current slider value as parameter onChange: Whenever the value of the slider is changed, the called function is invoked. The value can change due to the slider movement or by passing the setValue function. Types of slider script.aculo.us provides us the flexibility and comfort of two different orientations for the slider: Vertical slider Horizontal slider Vertical slider When the axis orientation of a slider is defined as vertical, the slider becomes and acts as a vertical slider. Horizontal slider When the axis orientation of a slider is defined as horizontal, the slider becomes and acts as a horizontal slider. So let's get our hands dirty with code and start defining the constructors for horizontal and vertical slider with options. Trust me this will be fun.
Read more
  • 0
  • 0
  • 1440

article-image-slider-dynamic-applications-using-scriptaculous-part-2
Packt
08 Oct 2009
4 min read
Save for later

Slider for Dynamic Applications using script.aculo.us (part 2)

Packt
08 Oct 2009
4 min read
Code usage for sliders with options We are now done with the most important part of the slider: the implementation of the slider in our applications. But wait, we need the slider to suit our applications, right? So let's customize our slider with options. We have mentioned earlier that track is the range of values. So let's first define the range for our slider. window.onload = function() { new Control.Slider('handle1' , 'track1', { axis:'vertical', range:$R(1,100)} The range option uses the Prototypes' objectRange instance. Hence, we declare it using $R (minimum, Maximum). Everything looks neat until here. Let's add some more options to our constructor, onSlide(). Using the onSlide() callback every time, we drag the slider and the callback is invoked. The default parameter passed to onSlide() is the current slider value. window.onload = function() { new Control.Slider('handle1' , 'track1', { axis:'vertical', range:$R(1,100), onSlide: function(v) { $('value1').innerHTML = "New Slide Value="+v;} }} We have added a div called value1 in our HTML code. On dragging the slider, we will update the value1 with the current slider value. OK, so let's see what happened to our slider to this point. Check out the following screenshot: Impressed? And, we are not done yet. Let's add more options to the slider now. You may ask me, what if the slider in the application needs to be at a particular value by default? And I will say use the sliderValue option. Let's make our slider value 10 by default. Here is the snippet for the same: window.onload = function() {      new Control.Slider('handle1' , 'track1',     {   axis:'vertical',   range:$R(1,100),   sliderValue: 10,   onSlide: function(v) { $('value1').innerHTML = "New Slide                                                 Value="+v;}} And, you should see the slider value at 10 when you run the code. Now your dear friend will ask, what if we don't want to give the range, but we need to pass the fixed set of values? And you proudly say, use the values option. Check out the usage of the values options in the constructor. window.onload = function() { new Control.Slider('handle1' , 'track1', { range:$R(1,25), values:[1, 5,10,15,20,25], onSlide:function(v){ $('value1').innerHTML = "New Slide Value="+v;} } );} We have added a set of values in the array form and passed it to our constructor. Let's see what it looks like. Tips and tricks with the slider After covering all the aspects of the slider feature, here is a list of simple tips and tricks which we can make use of in our applications with ease. Reading the current value of the slider script.aculo.us "genie" provides us with two callbacks for the slider to read the current value of the slider. They are: onSlide onChange Both these callbacks are used as a part of options in the slider. onSlide contains the current sliding value while the drag is on. The callback syntax is shown as follows: onSlide: function(value) {// do something with the value while sliding. Write or Edit thevalue //of current slider value while sliding} onChange callback will contain the value of the slider while the sliding or the drag event ends. After the drag is completed and if the value of the slider has changed then the onChange function will be called. For example, if the slider's current value is set to 10 and after sliding we change it to 15, then the onChange callback will be fired. The callback syntax is shown as follows: onChange: function(value){// do anything with the "changed" and current value} Multiple handles in the slider Now, a thought comes to our mind at this point: Is it possible for us to have two handles in one track? And, the mighty script.aculo.us library says yes! Check out the following code snippet and screenshot for a quick glance of having two handles in one track: HTML code<div id="track1"><div id="handle1"></div><div id="handle2"></div></div> JavaScript code for the same: window.onload = function() { new Control.Slider(['handle1','handle2'] , 'track1');} Now, check out the resulting screenshot having two handles and one track: The same can also be applied for the vertical slider too.
Read more
  • 0
  • 0
  • 1085

article-image-developing-seam-applications
Packt
08 Oct 2009
10 min read
Save for later

Developing Seam Applications

Packt
08 Oct 2009
10 min read
Seam application architecture As most enterprise Java developers are probably familiar with JSF and JSP, we will be using this as the view technology for our sample applications. Facelets is the recommended view technology for Seam-based applications once we have a solid understanding of Seam. In a standard Java EE application, Enterprise Application Resource (EAR) files contain one or more Web Application Resource (WAR) files and one or more sets of Java Archive (JAR) files containing Enterprise JavaBeans (EJB) functionality. Seam applications are generally deployed in exactly the same manner as depicted in the following diagram. It is possible to deploy Seam onto a servlet-only container (for example, Tomcat) and use POJOs as the server-side Seam components. However, in this situation, we don't get any of the benefits that EJBs provide, such as security, transaction handling, management, or pooling. Seam components Within Seam, components are simple POJOs. There is no need to implement any interfaces or derive classes from a Seam-specific base class to make Seam components classes. For example, a Seam component could be: A simple POJO a stateless Session Bean a stateful Session Bean a JPA entity and so on Seam components are defined by adding the @Name annotation to a class definition. The @Name annotation takes a single parameter to define the name of the Seam component. The following example shows how a stateless Session Bean is defined as a Seam component called calcAction. package com.davidsalter.seamcalculator; @Stateless @Name("calcAction") public class CalcAction implements Calc { ... } When a Seam application is deployed to JBoss, the log output at startup lists what Seam components are deployed, and what type they are. This can be useful for diagnostic purposes, to ensure that your components are deployed correctly. Output similar to the following will be shown in the JBoss console log when the CalcAction class is deployed: 21:24:24,097 INFO [Initialization] Installing components...21:24:24,121 INFO [Component] Component: calcAction, scope: STATELESS, type: STATELESS_SESSION_BEAN, class: com.davidsalter.seamcalculator.CalcAction, JNDI: SeamCalculator/CalcAction/local Object Injection and Outjection One of the benefits of using Seam is that it acts as the "glue" between the web technology and the server-side technology. By this we mean that the Seam Framework allows us to use enterprise beans (for example, Session Beans) directly within the Web tier without having to use Data Transfer Object (DTO) patterns and without worrying about exposing server-side functionality on the client. Additionally, if we are using Session Beans for our server-side functionality, we don't really have to develop an additional layer of JSF backing beans, which are essentially acting as another layer between our web page and our application logic. In order to fully understand the benefits of Seam, we need to first describe what we mean by Injection and Outjection. Injection is the process of the framework setting component values before an object is created. With injection, the framework is responsible for setting components (or injecting them) within other components. Typically, Injection can be used to allow component values to be passed from the web page into Seam components. Outjection works in the opposite direction to Injection. With Outjection, components are responsible for setting component values back into the framework. Typically, Outjection is used for setting component values back into the Seam Framework, and these values can then be referenced via JSF Expression Language (EL) within JSF pages. This means that Outjection is typically used to allow data values to be passed from Seam components into web pages. Seam allows components to be injected into different Seam components by using the @In annotation and allows us to outject them by using the @Out annotation. For example, if we have some JSF code that allows us to enter details on a web form, we may use an <h:inputText …/> tag such as this: <h:inputText value="#{calculator.value1}" required="true"/> The Seam component calculator could then be injected into a Seam component using the @In annotation as follows: @In private Calculator calculator; With Seam, all of the default values on annotations are the most likely ones to be used. In the preceding example therefore, Seam will look up a component called calculator and inject that into the calculator variable. If we wanted Seam to inject a variable with a different name to the variable that it is being injected into, we can adorn the @In annotation with the value parameter. @In (value="myCalculator") private Calculator calculator; In this example, Seam will look up a component called myCalculator and inject it into the variable calculator. Similarly, if we want to outject a variable from a Seam component into a JSF page, we would use the @Out annotation. @Out private Calculator calculator; The outjected calculator object could then be used in a JSF page in the following manner: <h:outputText value="#{calculator.answer}"/> Example application To see these concepts in action, and to gain an understanding of how Seam components are used instead of JSF backing beans, let us look at a simple calculator web application. This simple application allows us to enter two numbers on a web page. Clicking the Add button on the web page will cause the sum of the numbers to be displayed. This basic application will give us an understanding of the layout of a Seam application and how we can inject and outject components between the business layer and the view. The application functionality is shown in the following screenshot. The sample code for this application can be downloaded from the Packt web site, at http://www.packtpub.com/support. For this sample application, we have a single JSF page that is responsible for: Reading two numeric values from the user Invoking business logic to add the numbers together Displaying the results of adding the numbers together <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <html> <head> <title>Seam Calculator</title> </head> <body> <f:view> <h:form> <h:panelGrid columns="2"> Value 1: <h:inputText value="#{calculator. value1}" /> Value 2: <h:inputText value="#{calculator. value2}" /> Add them together gives: <h:outputText value=" #{calculator.answer} "/> </h:panelGrid> <h:commandButton value="Add" action= "#{calcAction.calculate}"/> </h:form> </f:view> </body> </html> We can see that there is nothing Seam-specific in this JSF page. However, we are binding two inputText areas, one outputText area, and a button action to Seam components by using standard JSF Expression Language. JSF EL Seam Binding calculator.value1 This is bound to the member variable value1 on the Seam component called calculator. This value will be injected into the Seam component. calculator.value2 This is bound to the member variable value2 on the Seam component called calculator. This value will be injected into the Seam component. calculator.answer This is bound to the member variable answer on the Seam component called calculator. This value will be outjected from the Seam component. calcAction.calculate This will invoke the method calculate() on the Seam component called calcAction. Our business logic for this sample application is performed in a simple POJO class called Calculator.java. package com.davidsalter.seamcalculator; import java.io.Serializable; import org.jboss.seam.annotations.Name;@Name("calculator") public class Calculator { private double value1; private double value2; private double answer; public double getValue1() { return value1; } public void setValue1(double value1) { this.value1 = value1; } public double getValue2() { return value2; } public void setValue2(double value2) { this.value2 = value2; } public double getAnswer() { return answer; } public void add() { this.answer = value1 + value2; } } This class is decorated with the @Name("calculator") annotation, which causes it to be registered to Seam with the name, "calculator". The @Name annotation causes this object to be registered as a Seam component that can subsequently be used within other Seam components via Injection or Outjection by using the @In and @Out annotations. Finally, we need to have a class that is acting as a backing bean for the JSF page that allows us to invoke our business logic. In this example, we are using a Stateless Session Bean. The Session Bean and its local interface are as follows. In the Java EE 5 specification, a Stateless Session Bean is used to represent a single application client's communication with an application server. A Stateless Session Bean, as its name suggests, contains no state information; so they are typically used as transaction façades. A Façade is a popular design pattern, which defines how simplified access to a system can be provided. For more information about the Façade pattern, check out the following link: http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html Defining a Stateless Session Bean using Java EE 5 technologies requires an interface and an implementation class to be defined. The interface defines all of the methods that are available to clients of the Session Bean, whereas the implementation class contains a concrete implementation of the interface. In Java EE 5, a Session Bean interface is annotated with either the @Local or @Remote or both annotations. An @Local interface is used when a Session Bean is to be accessed locally within the same JVM as its client (for example, a web page running within an application server). An @Remote interface is used when a Session Bean's clients are remote to the application server that is running within a different JVM as the application server. There are many books that cover Stateless Session Beans and EJB 3 in depth, such as EJB 3 Developer's Guide by Michael Sikora, published by Packt Publishing. For more information on this book, check out the following link: http://www.packtpub.com/developer-guide-for-ejb3 In the following code, we are registering our CalcAction class with Seam under the name calcAction. We are also Injecting and Outjecting the calculator variable so that we can use it both to retrieve values from our JSF form and pass them back to the form. package com.davidsalter.seamcalculator; import javax.ejb.Stateless; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Name; @Stateless @Name("calcAction") public class CalcAction implements Calc { @In @Out private Calculator calculator; public String calculate() { calculator.add(); return ""; } } package com.davidsalter.seamcalculator; import javax.ejb.Local; @Local public interface Calc { public String calculate(); } That's all the code we need to write for our sample application. If we review this code, we can see several key points where Seam has made our application development easier: All of the code that we have developed has been written as POJOs, which will make unit testing a lot easier. We haven't extended or implemented any special Seam interfaces. We've not had to define any JSF backing beans explicitly in XML. We're using Java EE Session Beans to manage all of the business logic and web-tier/business-tier integration. We've not used any DTO objects to transfer data between the web and the business tiers. We're using a Seam component that contains both state and behavior. If you are familiar with JSF, you can probably see that adding Seam into a fairly standard JSF application has already made our development simpler. Finally, to enable Seam to correctly find our Seam components and deploy them correctly to the application server, we need to create an empty file called seam.properties and place it within the root of the classpath of the EJB JAR file. Because this file is empty, we will not discuss it further here. To deploy the application as a WAR file embedded inside an EAR file, we need to write some deployment descriptors.
Read more
  • 0
  • 0
  • 1630
article-image-using-themes-lwuit-11-part-1-2
Packt
30 Sep 2009
6 min read
Save for later

Using Themes in LWUIT 1.1: Part 1

Packt
30 Sep 2009
6 min read
Working with theme files A theme file is conceptually similar to CSS while its implementation is like that of a Java properties file. Essentially a theme is a list of key-value pairs with an attribute being a key and its value being the second part of the key-value pair An entry in the list may be Form.bgColor= 555555. This entry specifies that the background color of all forms in the application will be (hex) 555555 in the RGB format. The list is implemented as a hashtable. Viewing a theme file A theme is packaged into a resource file that can also hold, as we have already seen, other items like images, animations, bitmap fonts, and so on. The fact that a theme is an element in a resource bundle means it can be created, viewed, and edited using the LWUIT Designer. The following screenshot shows a theme file viewed through the LWUIT Designer: The first point to note is that there are five entries at the bottom, which appear in bold letters. All such entries are the defaults. To take an example, the only component-specific font setting in the theme shown above is for the soft button. The font for the form title, as well as that for the strings in other components is not defined. These strings will be rendered with the default font. A theme file can contain images, animations, and fonts—both bitmap and system—as values. Depending on the type of key, values can be numbers, filenames or descriptions along with thumbnails where applicable. Editing a theme file In order to modify an entry in the theme file, select the row, and click on the Edit button. The dialog for edit will open, as shown in the following screenshot: Clicking Clicking on the browse button (the button with three dots and marked by the arrow) will open a color chooser from which the value of the selected color will be directly entered into the edit dialog. The edit dialog has fields corresponding to various keys, and depending on the one selected for editing, the relevant field will be enabled. Once a value is edited, click on the OK button to enter the new value into the theme file. In order to abort editing, click on the Cancel button. Populating a theme We shall now proceed to build a new theme file and see how it affects the appearance of a screen. The application used here is DemoTheme, and the code snippet below shows that we have set up a form with a label, a button, and a radio button. //create a new formForm demoForm = new Form("Theme Demo");//demoForm.setLayout(new BorderLayout());demoForm.setLayout(new BoxLayout(BoxLayout.Y_AXIS));//create and add 'Exit' command to the form//the command id is 0demoForm.addCommand(new Command("Exit", 1));//this MIDlet is the listener for the form's commanddemoForm.setCommandListener(this);//labelLabel label = new Label("This is a Label");//buttonButton button = new Button("An ordinary Button");//radiobuttonRadioButton rButton = new RadioButton("Just a RadioButton");//timeteller -- a custom component//TimeTeller timeTeller = new TimeTeller();//set style for timeLabel and titleLabel(in TimeViewer)//these parts of TimeTeller cannot be themed//because they belong to TimeViewer which does not//have any UIID/*Style tStyle = new Style();tStyle.setBgColor(0x556b3f);tStyle.setFgColor(0xe8dd21);tStyle.setBorder(Border.createRoundBorder(5, 5));timeTeller.setTitleStyle(tStyle);Style tmStyle = timeTeller.getTimeStyle();tmStyle.setBgColor(0xff0000);tmStyle.setFgColor(0xe8dd21);tmStyle.setBgTransparency(80);tmStyle.setBorder(Border.createRoundBorder(5, 5));*///add the widgets to demoFormdemoForm.addComponent(label);demoForm.addComponent(button);demoForm.addComponent(rButton);//demoForm.addComponent(timeTeller);//show the formdemoForm.show(); The statements for TimeTeller have been commented out. They will have to be uncommented to produce the screenshots in the section dealing with setting a theme for a custom component. The basic structure of the code is the same as that in the examples that we have come across so far, but with one difference—we do not have any statement for style setting this time around. That is because we intend to use theming to control the look of the form and the components on it. If we compile and run the code in its present form, then we get the following (expected) look. All the components have now been rendered with default attributes. In order to change the way the form looks, we are going to build a theme file—SampleTheme—that will contain the attributes required. We start by opening the LWUIT Designer through the SWTK. Had a resource file been present in the res folder of the project, we could have opened it in the LWUIT Designer by double-clicking on that file in the SWTK screen. In this case, as there is no such file, we launch the LWUIT Designer through the SWTK menu. The following screenshot shows the result of selecting Themes, and then clicking on the Add button: The name of the theme is typed in, as shown in the previous screenshot. Clicking on the OK button now creates an empty theme file, which is shown under Themes. Our first target for styling will be the form including the title and menu bars. If we click on the Add button in the right panel, the Add dialog will open. We can see this dialog below with the drop-down list for the Component field. Form is selected from this list. Similarly, the drop-down list for Attribute shows all the attributes that can be set. From this list we select bgImage, and we are prompted to enter the name for the image, which is bgImage in our case. The next step is to close the Add Image dialog by clicking on the OK button. As we have not added any image to this resource file as yet, the Image field above is blank. In order to select an image, we have to click on the browse button on the right of the Image field to display the following dialog. Again, the browse button has to be used to locate the desired image file. We confirm our selection through the successive dialogs to add the image as the one to be shown on the background of the form.
Read more
  • 0
  • 0
  • 1461

article-image-painters-lwuit-11-2
Packt
25 Sep 2009
6 min read
Save for later

Painters in LWUIT 1.1

Packt
25 Sep 2009
6 min read
The Painter interface Painter defnes the fundamental interface for all objects that are meant to draw backgrounds or to render on a glass pane. This interface declares  only one method—public void paint(Graphics g, Rectangle rect)—for drawing inside the bounding rectangle (specifed by rect) of a component. The library provides a class that implements Painter and is used as a default background painter for widgets and containers. This is the BackgroundPainter class that has (you guessed it) just the one method paint, which either paints the background image if one has been assigned or fills in the bounding rectangle of the component with the color set in its style. When we want to paint a background ourselves, we can write our own class that implements Painter, and set it as the background painter for the relevant component. The DemoPainter MIDlet, discussed in the next section, shows how this is done. The DemoPainter application This application creates a combo box and uses a theme to set the style for the various elements that are displayed. When the application is compiled without setting a custom background painter, the combo box looks as shown in the following screenshot: The MIDlet code has the following statement commented out in the MIDlet. When uncommented, this statement sets an instance of ComboBgPainter as the background painter for the combo box. combobox.getStyle().setBgPainter(new ComboBgPainter(0x4b338c)); The recompiled application produces the following display showing the new background color: The class responsible for drawing the background is ComboBgPainter, which implements Painter. The constructor for this class takes the color to be used for background painting as its only parameter. The paint method determines the coordinates of the top-left corner of the rectangle to be painted and its dimensions. The rectangle is then flled using the color that was set through the constructor. class ComboBgPainter implements Painter{ private int bgcolor; public ComboBgPainter(int bgcolor) { this.bgcolor = bgcolor; } public void paint(Graphics g, Rectangle rect) { g.setColor(bgcolor); int x = rect.getX(); int y = rect.getY(); int wd = rect.getSize().getWidth(); int ht = rect.getSize().getHeight(); g.fillRect(x, y, wd, ht); }} Drawing a multi-layered background In actual practice, there is hardly any point in using a custom painter just to paint a background color, because the setBgColor method of Style will usually do the job. Themes too can be used for setting background colors. However, painters are very useful when intricate background patterns need to be drawn, and especially if multiple layers are involved. PainterChain, described in the next section, is a class designed for handling such requirements. The PainterChain class It is possible to use more than one painter to render different layers of a background. Such a set of painters can be chained together through the PainterChain class. The only constructor of this class has the form public PainterChain(Painter[] chain) where the parameter chain is an array of painters. The contents of chain will be called sequentially during the painting of a background, starting from the element at index 0 to the last one. There are two methods of the PainterChain class that provide support for adding painters to the array underlying the chain. A new painter can be added either to the top (the prependPainter method) or at the end (the addPainter method) of the array. The array itself can be accessed through the getChain method. PainterChain implements Painter so that the setBgPainter method can be used to set a PainterChain as well as a lone painter, which means the paint method also is present here. The function of paint in PainterChain is to call the paint methods of the painter array elements one by one starting at index 0. The DemoPainterChain application that comes up next shows how a chain of painters can be used to draw the multiple layers of a background. The DemoPainterChain application The DemoPainterChain example uses alphaList to show a painter chain in action. After organizing the form and the list, we set up a painter array to hold the three painters that we shall deploy. Painter[] bgPainters = new Painter[3]; Once we have the array, we create three painters and load them into the array. The frst (lowest) painter, which will fll the bounding rectangle for the list with a designated color, goes in at index 0. The next (middle) layer, at index 1, will draw an image at the center of the list. Finally, the topmost layer for writing a text a little below the center line of the list is inserted at index 2. bgPainters[0] = new Eraser(0x334026);try{ bgPainters[1] = new ImagePainter(Image.createImage( "/a.png"));}catch(java.io.IOException ioe){}bgPainters[2] = new TextPainter("This is third layer"); Now we are ready to instantiate a PainterChain object, and install it as a background painter for the list. PainterChain bgChain = new PainterChain(bgPainters);alphaList.getStyle().setBgPainter(bgChain); The list itself will be drawn on top of these three layers, and the background layers will be visible only because the list is translucent as determined by the transparencyvalue 100, set by the AlphaListRenderer instance used to render alphaList. The list now looks as shown in the following screenshot: A close inspection of the screenshot that we have just seen will show that the layers have indeed been drawn in the same sequence as we had intended. The three painters are very similar in structure to the ComboBgPainter class we came across in the previous example. The Eraser class here is virtually identical to ComboBgPainter. The other two classes work in the same way, except for the fact that TextPainter draws a line of text, while ImagePainter draws an image. class TextPainter implements Painter{ private String text; TextPainter(String text) { //set the text to be written this.text = text; } public void paint(Graphics g, Rectangle rect) { //get the dimension //of background int wd = rect.getSize().getWidth(); int ht = rect.getSize().getHeight(); //create and set font for text Font textFont = Font.createSystemFont( Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE); g.setFont(textFont); //set text color g.setColor(0x0000aa); //position text slightly below centerline int textX = wd/2 - textFont.stringWidth(text)/2; int textY = ht/2 - textFont.getHeight()/2 + 3; //write text g.drawString(text, textX, textY); }}class ImagePainter implements Painter{ private Image bImage; ImagePainter(Image bImage) { //set the image to be drawn this.bImage = bImage; } public void paint(Graphics g, Rectangle rect) { //get the dimensions //of background int wd = rect.getSize().getWidth(); int ht = rect.getSize().getHeight(); //position image at center int imageX = wd/2 - bImage.getWidth()/2; int imageY = ht/2 - bImage.getHeight()/2; //draw image g.drawImage(bImage, imageX, imageY); }} When an image is used on the background of a form, we have seen that it is scaled to occupy the entire form real estate. But if the same image is used as an icon for a label, then it is drawn in its actual size. This task of scaling the image for backgrounds is taken care of by BackgroundPainter, which is used as the default bgPainter.
Read more
  • 0
  • 0
  • 1842