Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon

How-To Tutorials - Full-Stack Web Development

52 Articles
article-image-enhancing-your-site-php-and-jquery
Packt
29 Dec 2010
12 min read
Save for later

Enhancing your Site with PHP and jQuery

Packt
29 Dec 2010
12 min read
  PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery Create rich and interactive web applications with PHP and jQuery Debug and execute jQuery code on a live site Design interactive forms and menus Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery         Read more about this book       (For more resources on this subject, see here.) Introduction In this article, we will look at some advanced techniques that can be used to enhance the functionality of web applications. We will create a few examples where we will search for images the from Flickr and videos from YouTube using their respective APIs. We will parse a RSS feed XML using jQuery and learn to create an endless scrolling page like Google reader or the new interface of Twitter. Besides this, you will also learn to create a jQuery plugin, which you can use independently in your applications. Sending cross-domain requests using server proxy Browsers do not allow scripts to send cross-domain requests due to security reasons. This means a script at domain http://www.abc.com cannot send AJAX requests to http://www.xyz.com. This recipe will show how you can overcome this limitation by using a PHP script on the server side. We will create an example that will search Flickr for images. Flickr will return a JSON, which will be parsed by jQuery and images will be displayed on the page. The following screenshot shows a JSON response from Flickr: Getting ready Create a directory for this article and name it as Article9. In this directory, create a folder named Recipe1. Also get an API key from Flickr by signing up at http://www.flickr.com/services/api/keys/. How to do it... Create a file inside the Recipe1 folder and name it as index.html. Write the HTML code to create a form with three fields: tag, number of images, and image size. Also create an ul element inside which the results will be displayed. <html> <head> <title>Flickr Image Search</title> <style type="text/css"> body { font-family:"Trebuchet MS",verdana,arial;width:900px; } fieldset { width:333px; } ul{ margin:0;padding:0;list-style:none; } li{ padding:5px; } span{ display:block;float:left;width:150px; } #results li{ float:left; } .error{ font-weight:bold; color:#ff0000; } </style> </head> <body> <form id="searchForm"> <fieldset> <legend>Search Criteria</legend> <ul> <li> <span>Tag</span> <input type="text" name="tag" id="tag"/> </li> <li> <span>Number of images</span> <select name="numImages" id="numImages"> <option value="20">20</option> <option value="30">30</option> <option value="40">40</option> <option value="50">50</option> </select> </li> <li> <span>Select a size</span> <select id="size"> <option value="s">Small</option> <option value="t">Thumbnail</option> <option value="-">Medium</option> <option value="b">Large</option> <option value="o">Original</option> </select> </li> <li> <input type="button" value="Search" id="search"/> </li> </ul> </fieldset> </form> <ul id="results"> </ul> </body> </html> The following screenshot shows the form created: Include the jquery.js file. Then, enter the jQuery code that will send the AJAX request to a PHP file search.php. Values of form elements will be posted with an AJAX request. A callback function showImages is also defined that actually reads the JSON response and displays the images on the page. <script type="text/javascript" src="../jquery.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#search').click(function() { if($.trim($('#tag').val()) == '') { $('#results').html('<li class="error">Please provide search criteria</li>'); return; } $.post( 'search.php', $('#searchForm').serialize(), showImages, 'json' ); }); function showImages(response) { if(response['stat'] == 'ok') { var photos = response.photos.photo; var str= ''; $.each(photos, function(index,value) { var farmId = value.farm; var serverId = value.server; var id = value.id; var secret = value.secret; var size = $('#size').val(); var title = value.title; var imageUrl = 'http://farm' + farmId + '.static.flickr.com/' + serverId + '/' + id + '_' + secret + '_' + size + '.jpg'; str+= '<li>'; str+= '<img src="' + imageUrl + '" alt="' + title + '" />'; str+= '</li>'; }); $('#results').html(str); } else { $('#results').html('<li class="error">an error occured</li>'); } } }); </script> Create another file named search.php. The PHP code in this file will contact the Flickr API with specified search criteria. Flickr will return a JSON that will be sent back to the browser where jQuery will display it on the page. <?php define('API_KEY', 'your-API-key-here'); $url = 'http://api.flickr.com/services/rest/?method=flickr. photos.search'; $url.= '&api_key='.API_KEY; $url.= '&tags='.$_POST['tag']; $url.= '&per_page='.$_POST['numImages']; $url.= '&format=json'; $url.= '&nojsoncallback=1'; header('Content-Type:text/json;'); echo file_get_contents($url); ?> Now, run the index.html file in your browser, enter a tag to search in the form, and select the number of images to be retrieved and image size. Click on the Search button. A few seconds later you will see the images from Flickr displayed on the page: <html> <head> <title>Youtube Video Search</title> <style type="text/css"> body { font-family:"Trebuchet MS",verdana,arial;width:900px; } fieldset { width:333px; } ul{ margin:0;padding:0;list-style:none; } li{ padding:5px; } span{ display:block;float:left;width:150px; } #results ul li{ float:left; background-color:#483D8B; color:#fff;margin:5px; width:120px; } .error{ font-weight:bold; color:#ff0000; } img{ border:0} </style> </head> <body> <form id="searchForm"> <fieldset> <legend>Search Criteria</legend> <ul> <li> <span>Enter query</span> <input type="text" id="query"/> </li> <li> <input type="button" value="Search" id="search"/> </li> </ul> </fieldset> </form> <div id="results"> </div> </body> </html> How it works... On clicking the Search button, form values are sent to the PHP file search.php. Now, we have to contact Flickr and search for images. Flickr API provides several methods for accessing images. We will use the method flickr.photos.search to search by tag name. Along with method name we will have to send the following parameters in the URL: api_key: An API key is mandatory. You can get one from: http://www.flickr.com/services/api/keys/. tags: The tags to search for. These can be comma-separated. This value will be the value of textbox tag. per_page: Number of images in a page. This can be a maximum of 99. Its value will be the value of select box numImages. format: It can be JSON, XML, and so on. For this example, we will use JSON. nojsoncallback: Its value will be set to 1 if we don't want Flickr to wrap the JSON in a function wrapper. Once the URL is complete we can contact Flickr to get results. To get the results' we will use the PHP function file_get_contents, which will get the results JSON from the specified URL. This JSON will be echoed to the browser. jQuery will receive the JSON in callback function showImages. This function first checks the status of the response. If the response is OK, we get the photo elements from the response and we can iterate over them using jQuery's $.each method. To display an image, we will have to get its URL first, which will be created by combining different values of the photo object. According to Flickr API specification, an image URL can be constructed in the following manner: http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[size].jpg So we get the farmId, serverId, id, and secret from the photo element. The size can be one of the following: s (small square) t (thumbnail) - (medium) b (large) o (original image) We have already selected the image size from the select box in the form. By combining all these values, we now have the Flickr image URL. We wrap it in a li element and repeat the process for all images. Finally, we insert the constructed images into the results li. Making cross-domain requests with jQuery The previous recipe demonstrated the use of a PHP file as a proxy for querying cross-domain URLs. This recipe will show the use of JSONP to query cross-domain URLs from jQuery itself. We will create an example that will search for the videos from YouTube and will display them in a list. Clicking on a video thumbnail will open a new window that will take the user to the YouTube website to show that video. The following screenshot shows a sample JSON response from YouTube: Getting ready Create a folder named Recipe2 inside the Article9 directory. How to do it... Create a file inside the Recipe2 folder and name it as index.html. Write the HTML code to create a form with a single field query and a DIV with results ID inside which the search results will be displayed. <script type="text/javascript" src="../jquery.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#search').click(function() { var query = $.trim($('#query').val()); if(query == '') { $('#results').html('<li class="error">Please enter a query.</li>'); return; } $.get( 'http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script', {}, showVideoList, 'jsonp' ); }); }); function showVideoList(response) { var totalResults = response['feed']['openSearch$totalResults']['$t']; if(parseInt(totalResults,10) > 0) { var entries = response.feed.entry; var str = '<ul>'; for(var i=1; i< entries.length; i++) { var value = entries[i]; var title = value['title']['$t']; var mediaGroup = value['media$group']; var videoURL = mediaGroup['media$player'][0]['url']; var thumbnail = mediaGroup['media$thumbnail'][0]['url']; var thumbnailWidth = mediaGroup['media$thumbnail'][0]['width']; var thumbnailHeight = mediaGroup['media$thumbnail'][0]['height']; var numComments = value['gd$comments']['gd$feedLink']['countHint']; var rating = parseFloat(value['gd$rating']['average']).toFixed(2); str+= '<li>'; str+= '<a href="' + videoURL + '" target="_blank">'; str+= '<img src="'+thumbNail+'" width="'+thumbNailWidth+'" height="'+thumbNailWidth+'" title="' + title + '" />'; str+= '</a>'; str+= '<hr>'; str+= '<p style="width: 120px; font-size: 12px;">Comments: ' + numComments + ''; str+= '<br/>'; str+= 'Rating: ' + rating; str+= '</p>'; str+= '</li>'; } str+= '</ul>'; $('#results').html(str); } else { $('#results').html('<li class="error">No results.</li>'); } } </script> Include the jquery.js file before closing the &ltbody> tag. Now, write the jQuery code that will take the search query from the textbox and will try to retrieve the results from YouTube. A callback function called showVideoList will get the response and will create a list of videos from the response. http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script All done, and we are now ready to search YouTube. Run the index.html file in your browser and enter a search query. Click on the Search button and you will see a list of videos with a number of comments and a rating for each video. How it works... script tags are an exception to cross-browser origin policy. We can take advantage of this by requesting the URL from the src attribute of a script tag and by wrapping the raw response in a callback function. In this way the response becomes JavaScript code instead of data. This code can now be executed on the browser. The URL for YouTube video search is as follows: http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script Parameter q is the query that we entered in the textbox and alt is the type of response we want. Since we are using JSONP instead of JSON, the value for alt is defined as json-in-script as per YouTube API specification. On getting the response, the callback function showVideoList executes. It checks whether any results are available or not. If none are found, an error message is displayed. Otherwise, we get all the entry elements and iterate over them using a for loop. For each video entry, we get the videoURL, thumbnail, thumbnailWidth, thumbnailHeight, numComments, and rating. Then we create the HTML from these variables with a list item for each video. For each video an anchor is created with href set to videoURL. The video thumbnail is put inside the anchor and a p tag is created where we display the number of comments and rating for a particular video. After the HTML has been created, it is inserted in the DIV with ID results. There's more... About JSONP You can read more about JSONP at the following websites: http://remysharp.com/2007/10/08/what-is-jsonp/ http://en.wikipedia.org/wiki/JSON#JSONP
Read more
  • 0
  • 0
  • 2082

article-image-working-xml-documents-php-jquery
Packt
23 Dec 2010
8 min read
Save for later

Working with XML Documents in PHP jQuery

Packt
23 Dec 2010
8 min read
PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery Create rich and interactive web applications with PHP and jQuery Debug and execute jQuery code on a live site Design interactive forms and menus Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery Introduction Extensible Markup Language—also known as XML—is a structure for representation of data in human readable format. Contrary to its name, it's actually not a language but a markup which focuses on data and its structure. XML is a lot like HTML in syntax except that where HTML is used for presentation of data, XML is used for storing and data interchange. Moreover, all the tags in an XML are user-defined and can be formatted according to one's will. But an XML must follow the specification recommended by W3C. With a large increase in distributed applications over the internet, XML is the most widely used method of data interchange between applications. Web services use XML to carry and exchange data between applications. Since XML is platform-independent and is stored in string format, applications using different server-side technologies can communicate with each other using XML. Consider the following XML document: From the above document, we can infer that it is a list of websites containing data about the name, URL, and some information about each website. PHP has several classes and functions available for working with XML documents. You can read, write, modify, and query documents easily using these functions. In this article, we will discuss SimpleXML functions and DOMDocument class of PHP for manipulating XML documents. You will learn how to read and modify XML files, using SimpleXML as well as DOM API. We will also explore the XPath method, which makes traversing documents a lot easier. Note that an XML must be well-formed and valid before we can do anything with it. There are many rules that define well-formedness of XML out of which a few are given below: An XML document must have a single root element.   There cannot be special characters like <, >, and soon.   Each XML tag must have a corresponding closing tag.   Tags are case sensitive To know more about validity of an XML, you can refer to this link: http://en.wikipedia.org/wiki/XML#Schemas_and_validation For most of the recipes in this article, we will use an already created XML file. Create a new file, save it as common.xml in the Article3 directory. Put the following contents in this file. <?xml version="1.0"?> <books> <book index="1"> <name year="1892">The Adventures of Sherlock Holmes</name> <story> <title>A Scandal in Bohemia</title> <quote>You see, but you do not observe. The distinction is clear.</quote> </story> <story> <title>The Red-headed League</title> <quote>It is quite a three pipe problem, and I beg that you won't speak to me for fifty minutes.</quote> </story> <story> <title>The Man with the Twisted Lip</title> <quote>It is, of course, a trifle, but there is nothing so important as trifles.</quote> </story> </book> <book index="2"> <name year="1927">The Case-book of Sherlock Holmes</name> <story> <title>The Adventure of the Three Gables</title> <quote>I am not the law, but I represent justice so far as my feeble powers go.</quote> </story> <story> <title>The Problem of Thor Bridge</title> <quote>We must look for consistency. Where there is a want of it we must suspect deception.</quote> </story> <story> <title>The Adventure of Shoscombe Old Place</title> <quote>Dogs don't make mistakes.</quote> </story> </book> <book index="3"> <name year="1893">The Memoirs of Sherlock Holmes</name> <story> <title>The Yellow Face</title> <quote>Any truth is better than indefinite doubt.</quote> </story> <story> <title>The Stockbroker's Clerk</title> <quote>Results without causes are much more impressive. </quote> </story> <story> <title>The Final Problem</title> <quote>If I were assured of your eventual destruction I would, in the interests of the public, cheerfully accept my own.</quote> </story> </book> </books> Loading XML from files and strings using SimpleXML True to its name, SimpleXML functions provide an easy way to access data from XML documents. XML files or strings can be converted into objects, and data can be read from them. We will see how to load an XML from a file or string using SimpleXML functions. You will also learn how to handle errors in XML documents. Getting ready Create a new directory named Article3. This article will contain sub-folders for each recipe. So, create another folder named Recipe1 inside it. How to do it... Create a file named index.php in Recipe1 folder. In this file, write the PHP code that will try to load the common.xml file. On loading it successfully, it will display a list of book names. We have also used the libxml functions that will detect any error and will show its detailed description on the screen. <?php libxml_use_internal_errors(true); $objXML = simplexml_load_file('../common.xml'); if (!$objXML) { $errors = libxml_get_errors(); foreach($errors as $error) { echo $error->message,'<br/>'; } } else { foreach($objXML->book as $book) { echo $book->name.'<br/>'; } } ?> Open your browser and point it to the index.php file. Because we have already validated the XML file, you will see the following output on the screen: The Adventures of Sherlock Holmes The Case-book of Sherlock Holmes The Memoirs of Sherlock Holmes Let us corrupt the XML file now. For this, open the common.xml file and delete any node name. Save this file and reload index.php on your browser. You will see a detailed error description on your screen: How it works... In the first line, passing a true value to the libxml_use_internal_errors function will suppress any XML errors and will allow us to handle errors from the code itself. The second line tries to load the specified XML using the simplexml_load_file function. If the XML is loaded successfully, it is converted into a SimpleXMLElement object otherwise a false value is returned. We then check for the return value. If it is false, we use the libxml_get_errors() function to get all the errors in the form of an array. This array contains objects of type LibXMLError. Each of these objects has several properties. In the previous code, we iterated over the errors array and echoed the message property of each object which contains a detailed error message. If there are no errors in XML, we get a SimpleXMLElement object which has all the XML data loaded in it. There's more... Parameters for simplexml_load_file More parameters are available for the simplexml_load_file method, which are as follows: filename: This is the first parameter that is mandatory. It can be a path to a local XML file or a URL. class_name: You can extend the SimpleXMLElement class. In that case, you can specify that class name here and it will return the object of that class. This parameter is optional. options: This third parameter allows you to specify libxml parameters for more control over how the XML is handled while loading. This is also optional. simplexml_load_string Similar to simplexml_load_file is simplexml_load_string, which also creates a SimpleXMLElement on successful execution. If a valid XML string is passed to it we get a SimpleXMLElement object or a false value otherwise. $objXML = simplexml_load_string('<?xml version="1.0"?><book><name> Myfavourite book</name></book>'); The above code will return a SimpleXMLElement object with data loaded from the XML string. The second and third parameters of this function are same as that of simplexml_load_file. Using SimpleXMLElement to create an object You can also use the constructor of the SimpleXMLElement class to create a new object. $objXML = new SimpleXMLElement('<?xml version="1.0"?><book><name> Myfavourite book</name></book>'); More info about SimpleXML and libxml You can read about SimpleXML in more detail on the PHP site at http://php.net/manual/en/book.simplexml.php and about libxml at http://php.net/manual/en/book.libxml.php.
Read more
  • 0
  • 0
  • 2639

article-image-working-json-php-jquery
Packt
20 Dec 2010
5 min read
Save for later

Working with JSON in PHP jQuery

Packt
20 Dec 2010
5 min read
  PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery Create rich and interactive web applications with PHP and jQuery Debug and execute jQuery code on a live site Design interactive forms and menus Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery         Read more about this book       In this article, by Vijay Joshi, author of PHP jQuery Cookbook, we will cover: Creating JSON in PHP Reading JSON in PHP Catching JSON parsing errors Accessing data from a JSON in jQuery (For more resources on this subject, see here.) Introduction Recently, JSON (JavaScript Object Notation) has become a very popular data interchange format with more and more developers opting for it over XML. Even many web services nowadays provide JSON as the default output format. JSON is a text format that is programming-language independent and is a native data form of JavaScript. It is lighter and faster than XML because it needs less markup compared to XML. Because JSON is the native data form of JavaScript, it can be used on the client side in an AJAX application more easily than XML. A JSON object starts with { and ends with }. According to the JSON specification, the following types are allowed in JSON: Object: An object is a collection of key-value pairs enclosed between { and } and separated by a comma. The key and the value themselves are separated using a colon (:). Think of objects as associative arrays or hash tables. Keys are simple strings and values can be an array, string, number, boolean, or null. Array: Like other languages, an array is an ordered pair of data. For representing an array, values are comma separated and enclosed between [ and ]. String: A string must be enclosed in double quotes The last type is a number A JSON can be as simple as: { "name":"Superman", "address": "anywhere"} An example using an array is as follows: { "name": "Superman", "phoneNumbers": ["8010367150", "9898989898", "1234567890" ]} A more complex example that demonstrates the use of objects, arrays, and values is as follows:   { "people": [ { "name": "Vijay Joshi", "age": 28, "isAdult": true }, { "name": "Charles Simms", "age": 13, "isAdult": false } ]} An important point to note: { 'name': 'Superman', 'address': 'anywhere'} Above is a valid JavaScript object but not a valid JSON. JSON requires that the name and value must be enclosed in double quotes; single quotes are not allowed. Another important thing is to remember the proper charset of data. Remember that JSON expects the data to be UTF-8 whereas PHP adheres to ISO-8859-1 encoding by default. Also note that JSON is not a JavaScript; it is basically a specification or a subset derived from JavaScript. Now that we are familiar with JSON, let us proceed towards the recipes where we will learn how we can use JSON along with PHP and jQuery. Create a new folder and name it as Chapter 4. We will put all the recipes of this article together in this folder. Also put the jquery.js file inside this folder. To be able to use PHP's built-in JSON functions, you should have PHP version 5.2 or higher installed. Creating JSON in PHP This recipe will explain how JSON can be created from PHP arrays and objects Getting ready Create a new folder inside the Chapter4 directory and name it as Recipe1. How to do it... Create a file and save it by the name index.php in the Recipe1 folder. Write the PHP code that creates a JSON string from an array. <?php $travelDetails = array( 'origin' => 'Delhi', 'destination' => 'London', 'passengers' => array ( array('name' => 'Mr. Perry Mason', 'type' => 'Adult', 'age'=> 28), array('name' => 'Miss Irene Adler', 'type' => 'Adult', 'age'=> 28) ), 'travelDate' => '17-Dec-2010' ); echo json_encode($travelDetails);?> Run the file in your browser. It will show a JSON string as output on screen. After indenting the result will look like the following: { "origin":"Delhi","destination":"London","passengers":[ { "name":"Mr. Perry Mason", "type":"Adult", "age":28 }, { "name":"Miss Irene Adler", "type":"Adult", "age":28 }],"travelDate":"17-Dec-2010"} How it works... PHP provides the function json_encode() to create JSON strings from objects and arrays. This function accepts two parameters. First is the value to be encoded and the second parameter includes options that control how certain special characters are encoded. This parameter is optional. In the previous code we created a somewhat complex associative array that contains travel information of two passengers. Passing this array to json_encode() creates a JSON string. There's more... Predefined constants Any of the following constants can be passed as a second parameter to json_encode(). JSON_HEX_TAG: Converts < and > to u003C and u003E JSON_HEX_AMP: Converts &s to u0026 JSON_HEX_APOS: Converts ' to u0027 JSON_HEX_QUOT: Converts " to u0022 JSON_FORCE_OBJECT: Forces the return value in JSON string to be an object instead of an array These constants require PHP version 5.3 or higher.
Read more
  • 0
  • 0
  • 4712
Banner background image

article-image-data-binding-expression-blend-4-silverlight-4
Packt
13 May 2010
7 min read
Save for later

Data binding from Expression Blend 4 in Silverlight 4

Packt
13 May 2010
7 min read
Using the different modes of data binding to allow persisting data Until now, the data has flowed from the source to the target (the UI controls). However, it can also flow in the opposite direction, that is, from the target towards the source. This way, not only can data binding help us in displaying data, but also in persisting data. The direction of the flow of data in a data binding scenario is controlled by the Mode property of the Binding. In this recipe, we'll look at an example that uses all the Mode options and in one go, we'll push the data that we enter ourselves to the source. Getting ready This recipe builds on the code that was created in the previous recipes, so if you're following along, you can keep using that codebase. You can also follow this recipe from the provided start solution. It can be found in the Chapter02/SilverlightBanking_Binding_ Modes_Starter folder in the code bundle that is available on the Packt website. The Chapter02/SilverlightBanking_Binding_Modes_Completed folder contains the finished application of this recipe. How to do it... In this recipe, we'll build the "edit details" window of the Owner class. On this window, part of the data is editable, while some isn't. The editable data will be bound using a TwoWay binding, whereas the non-editable data is bound using a OneTime binding. The Current balance of the account is also shown—which uses the automatic synchronization—based on the INotifyPropertyChanged interface implementation. This is achieved using OneWay binding. The following is a screenshot of the details screen: Let's go through the required steps to work with the different binding modes: Add a new Silverlight child window called OwnerDetailsEdit.xaml to the Silverlight project. In the code-behind of this window, change the default constructor—so that it accepts an instance of the Owner class—as shown in the following code: private Owner owner; public OwnerDetailsEdit(Owner owner) { InitializeComponent(); this.owner = owner; } In MainPage.xaml, add a Click event on the OwnerDetailsEditButton: <Button x_Name="OwnerDetailsEditButton" Click="OwnerDetailsEditButton_Click" > In the event handler, add the following code, which will create a new instance of the OwnerDetailsEdit window, passing in the created Owner instance: private void OwnerDetailsEditButton_Click(object sender, RoutedEventArgs e) { OwnerDetailsEdit ownerDetailsEdit = new OwnerDetailsEdit(owner); ownerDetailsEdit.Show(); } The XAML of the OwnerDetailsEdit is pretty simple. Take a look at the completed solution (Chapter02/SilverlightBanking_Binding_Modes_Completed)for a complete listing. Don't forget to set the passed Owner instance as the DataContext for the OwnerDetailsGrid. This is shown in the following code: OwnerDetailsGrid.DataContext = owner; For the OneWay and TwoWay bindings to work, the object to which we are binding should be an instance of a class that implements the INotifyPropertyChanged interface. In our case, we are binding an Owner instance. This instance implements the interface correctly. The following code illustrates this: public class Owner : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; ... } Some of the data may not be updated on this screen and it will never change. For this type of binding, the Mode can be set to OneTime. This is the case for the OwnerId field. The users should neither be able to change their ID nor should the value of this field change in the background, thereby requiring an update in the UI. The following is the XAML code for this binding: <TextBlock x_Name="OwnerIdValueTextBlock" Text="{Binding OwnerId, Mode=OneTime}" > </TextBlock> The CurrentBalance TextBlock at the bottom does not need to be editable by the user (allowing a user to change his or her account balance might not be benefi cial for the bank), but it does need to change when the source changes. This is the automatic synchronization working for us and it is achieved by setting the Binding to Mode=OneWay. This is shown in the following code: <TextBlock x_Name="CurrentBalanceValueTextBlock" Text="{Binding CurrentBalance, Mode=OneWay}" > </TextBlock> The final option for the Mode property is TwoWay. TwoWay bindings allow us to persist data by pushing data from the UI control to the source object. In this case, all other fields can be updated by the user. When we enter a new value, the bound Owner instance is changed. TwoWay bindings are illustrated using the following code: <TextBox x_Name="FirstNameValueTextBlock" Text="{Binding FirstName, Mode=TwoWay}" > </TextBox> We've applied all the different binding modes at this point. Notice that when you change the values in the pop-up window, the details on the left of the screen are also updated. This is because all controls are in the background bound to the same source object as shown in the following screenshot: How it works... When we looked at the basics of data binding, we saw that a binding always occurs between a source and a target. The first one is normally an in-memory object, but it can also be a UI control. The second one will always be a UI control. Normally, data flows from source to target. However, using the Mode property, we have the option to control this. A OneTime binding should be the default for data that does not change when displayed to the user. When using this mode, the data flows from source to target. The target receives the value initially during loading and the data displayed in the target will never change. Quite logically, even if a OneTime binding is used for a TextBox, changes done to the data by the user will not flow back to the source. IDs are a good example of using OneTime bindings. Also, when building a catalogue application, OneTime bindings can be used, as we won't change the price of the items that are displayed to the user (or should we...?). We should use a OneWay binding for binding scenarios in which we want an up-to-date display of data. Data will flow from source to target here also, but every change in the values of the source properties will propagate to a change of the displayed values. Think of a stock market application where updates are happening every second. We need to push the updates to the UI of the application. The TwoWay bindings can help in persisting data. The data can now flow from source to target, and vice versa. Initially, the values of the source properties will be loaded in the properties of the controls. When we interact with these values (type in a textbox, drag a slider, and so on), these updates are pushed back to the source object. If needed, conversions can be done in both directions. There is one important requirement for the OneWay and TwoWay bindings. If we want to display up-to-date values, then the INotifyPropertyChanged interface should be implemented. The OneTime and OneWay bindings would have the same effect, even if this interface is not implemented on the source. The TwoWay bindings would still send the updated values if the interface was not implemented; however, they wouldn't notify about the changed values. It can be considered as a good practice to implement the interface, unless there is no chance that the updates of the data would be displayed somewhere in the application. The overhead created by the implementation is minimal. There's more... Another option in the binding is the UpdateSourceTrigger. It allows us to specify when a TwoWay binding will push the data to the source. By default, this is determined by the control. For a TextBox, this is done on the LostFocus event; and for most other controls, it's done on the PropertyChanged event. The value can also be set to Explicit. This means that we can manually trigger the update of the source. BindingExpression expression = this.FirstNameValueTextBlock. GetBindingExpression(TextBox.TextProperty); expression.UpdateSource(); See also Changing the values that flow between source and target can be done using converters. Data binding from Expression Blend 4 While creating data bindings is probably a task mainly reserved for the developer(s) in the team, Blend 4—the design tool for Silverlight applications—also has strong support for creating and using bindings. In this recipe, we'll build a small data-driven application that uses data binding. We won't manually create the data binding expressions; we'll use Blend 4 for this task.
Read more
  • 0
  • 0
  • 1482

article-image-working-dataform-microsoft-silverlight-4
Packt
10 May 2010
9 min read
Save for later

Working with DataForm in Microsoft Silverlight 4

Packt
10 May 2010
9 min read
Displaying and editing an object using the DataForm Letting a user work with groups of related data is a requirement of almost every application. It includes displaying a group of people, editing product details, and so on. These groups of data are generally contained in forms and the Silverlight DataForm (from the Silverlight Toolkit) is just that—a form. In the next few recipes, you'll learn how to work with this DataForm. As of now, let's start off with the basics, that is, displaying and editing the data. Getting ready For this recipe, we're starting with a blank solution, but you do need to install the Silverlight Toolkit as the assemblies containing the DataForm are offered through this. You can download and install it from http://www.codeplex.com/Silverlight/. You can find the completed solution in the Chapter05/Dataform_DisplayAndEdit_Completed folder in the code bundle that is available on the Packt website. How to do it... We're going to create a Person object, which will be displayed through a DataForm. To achieve this, we'll carry out the following steps: Start a new Silverlight solution, name it DataFormExample, and add a reference to System.Windows.Controls.Data.DataForm.Toolkit (from the Silverlight Toolkit). Alternatively, you can drag the DataForm from the Toolbox to the design surface. Open MainPage.xaml and add a namespace import statement at the top of this fi le (in the tag) as shown in the following code. This will allow us to use the DataForm, which resides in the assembly that we've just referenced. Add a DataForm to MainPage.xaml and name it as myDataForm. In the DataForm, set AutoEdit to False and CommandButtonsVisibility to All as shown in the following code: <Grid x_Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="40" ></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="Working with the DataForm" Margin="10" FontSize="14" > </TextBlock> <df:DataForm x_Name="myDataForm" AutoEdit="False" CommandButtonsVisibility="All" Grid.Row="1" Width="400" Height="300" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top" > </df:DataForm> </Grid> Add a new class named Person to the Silverlight project having ID, FirstName, LastName, and DateOfBirth as its properties. This class is shown in the following code. We will visualize an instance of the Person class using the DataForm. public class Person { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } } Open MainPage.xaml.cs and add a person property of the Person type to it. Also, create a method named InitializePerson in which we'll initialize this property as shown in the following code: public Person person { get; set; } private void InitializePerson() { person = new Person() { ID = 1, FirstName = "Kevin", LastName = "Dockx", DateOfBirth = new DateTime(1981, 5, 5) }; } Add a call to InitializePerson in the constructor of MainPage.xaml.cs and set the CurrentItem property of the DataForm to a person as shown in the following code: InitializePerson(); myDataForm.CurrentItem = person; You can now build and run your solution. When you do this, you'll see a DataForm that has automatically generated the necessary fields in order to display a person. This can be seen in the following screenshot: How it works... To start off, we needed something to display in our DataForm: a Person entity. This is why we've created the Person class: it will be bound to the DataForm by setting the CurrentItem property to an object of type Person. Doing this will make sure that the DataForm automatically generates the necessary fi elds. It looks at all the public properties of our Person object and generates the correct control depending on the type. A string will be displayed as a TextBox, a Boolean value will be displayed as a CheckBox, and so on. As we have set the CommandButtonsVisibility property on the DataForm to All, we get an Edit icon in the command bar at the top of the DataForm. (Setting AutoEdit to False makes sure that we start in the display mode, rather than the edit mode). When you click on the Edit icon, the DataForm shows the person in the editable mode (using the EditItemTemplate) and an OK button appears. Clicking on the OK button will revert the form to the regular displaying mode. Do keep in mind that the changes you make to the person are persisted immediately in memory (in the case of a TextBox, when it loses focus). If necessary, you can write extra code to persist the Person object from the memory to an underlying datastore by handling the ItemEditEnded event on the DataForm. There's more... At this moment, we've got a DataForm displaying a single item that you can either view or edit. But what if you want to cancel your edit? As of now, the Cancel button appears to be disabled. As the changes you make in the DataForm are immediately persisted to the underlying object in the memory, cancelling the edit would require some extra business logic. Luckily, it's not hard to do. First of all, you'll want to implement the IEditableObject interface on the Person class, which will make sure that cancelling is possible. As a result, the Cancel button will no longer be disabled. The following code is used to implement this: public class Person : IEditableObject { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } public void BeginEdit() {} public void CancelEdit() {} public void EndEdit() {} } This interface exposes three methods: BeginEdit, CancelEdit, and EndEdit. If needed, you can write extra business logic in these methods, which is exactly what we need to do. For most applications, you might want to implement only CancelEdit, which would then refetch the person from the underlying data store. In our example, we're going to solve this problem by using a different approach. (You can use this approach if you haven't got an underlying database from which your data can be refetched, or if you don't want to access the database again.) In the BeginEdit method, we save the current property values of the person. When the edit has been cancelled, we put them back to the way they were before. This is shown in the following code: public void BeginEdit() { // save current values tmpPerson = new Person() { ID = this.ID, FirstName = this.FirstName, LastName = this.LastName, DateOfBirth = this.DateOfBirth }; } public void CancelEdit() { // reset values ID = tmpPerson.ID; FirstName = tmpPerson.FirstName; LastName = tmpPerson.LastName; DateOfBirth = tmpPerson.DateOfBirth; } Now, cancelling an edit is possible and it actually reverts to the previous property values. More on DataForm behavior The DataForm exposes various events such as BeginningEdit (when you begin to edit an item), EditEnding (occurs just before an item is saved), and EditEnded (occurs after an item has been saved). It also exposes properties that you can use to defi ne how the DataForm behaves. Validating a DataForm or a DataGrid As you might have noticed, the DataForm includes validation on your fields automatically. For example, try inputting a string value into the ID field. You'll see that an error message appears. This is beyond the scope of this recipe, but more on this will be discussed in the Validating the DataForm recipe. Managing the editing of an object on different levels There are different levels of managing the editing of an object. You can manage this on the control level itself by handling events such as BeginningEdit or ItemEditEnded in the DataForm. Besides that, you can also handle editing on a business level by implementing the IEditableObject interface and providing custom code for the BeginEdit, CancelEdit, or EndEdit methods in the class itself. Depending on the requirements of your application, you can use either of the levels or even both together. See also In this recipe, we've seen how the DataForm is created automatically. For most applications, you require more control over how your fi elds, for example, are displayed. The DataForm is highly customizable, both on a template level (through template customization) and on how the data is generated (through data annotations). If you want to learn about using the DataForm to display or edit a list of items rather than just one, have a look at the next recipe, Displaying and editing a collection using the DataForm. Displaying and editing a collection using the DataForm In the previous recipe, you learned how to work with the basic features of the DataForm. You can now visualize and edit an entity. But in most applications, this isn't enough. Often, you'll want to have an application that shows you a list of items with the ability to add a new item or delete an item from the list. You'll want the application to allow you to edit every item and provide an easy way of navigating between them. A good example of this would be an application that allows you to manage a list of employees. The DataForm can do all of this and most of it is built-in. In this recipe, you'll learn how to achieve this. Getting ready For this recipe, we're starting with the basic setup that we completed in the previous recipe. If you didn't complete that recipe, you can find a starter solution in the Chapter05/ Dataform_Collection_Starter folder in the code bundle that is available on the Packt website. The finished solution for this recipe can be found in the Chapter05/Dataform_ Collection_Completed folder. In any case, you'll need to install the Silverlight Toolkit as the assemblies containing the DataForm are offered through it. You can download and install it from http://www.codeplex.com/Silverlight/.
Read more
  • 0
  • 0
  • 5376

article-image-introduction-data-binding
Packt
10 May 2010
10 min read
Save for later

Introduction to Data Binding

Packt
10 May 2010
10 min read
Introduction Data binding allows us to build data-driven applications in Silverlight in a much easier and much faster way compared to old-school methods of displaying and editing data. This article and the following one take a look at how data binding works. We'll start by looking at the general concepts of data binding in Silverlight 4 in this article. Analyzing the term data binding immediately reveals its intentions. It is a technique that allows us to bind properties of controls to objects or collections thereof. The concept is, in fact, not new. Technologies such as ASP.NET, Windows Forms, and even older technologies such as MFC (Microsoft Foundation Classes) include data binding features. However, WPF's data binding platform has changed the way we perform data binding; it allows loosely coupled bindings. The BindingsSource control in Windows Forms has to know of the type we are binding to, at design time. WPF's built-in data binding mechanism does not. We simply defi ne to which property of the source the target should bind. And at runtime, the actual data—the object to which we are binding—is linked. Luckily for us, Silverlight inherits almost all data binding features from WPF and thus has a rich way of displaying data. A binding is defined by four items: The source or source object: This is the data we are binding to. The data that is used in data binding scenarios is in-memory data, that is, objects. Data binding itself has nothing to do with the actual data access. It works with the objects that are a result of reading from a database or communicating with a service. A typical example is a Customer object. A property on the source object: This can, for example, be the Name property of the Customer object. The target control: This is normally a visual control such as a TextBox or a ListBox control. In general, the target can be a DependencyObject. In Silverlight 2 and Silverlight 3, the target had to derive from FrameworkElement; this left out some important types such as transformations. A property on the target control: This will, in some way—directly or after a conversion—display the data from the property on the source. The data binding process can be summarized in the following image: In the previous image, we can see that the data binding engine is also capable of synchronization. This means that data binding is capable of updating the display of data automatically. If the value of the source changes, Silverlight will change the value of the target as well without us having to write a single line of code. Data binding isn't a complete black box either. There are hooks in the process, so we can perform custom actions on the data fl owing from source to target, and vice versa. These hooks are the converters. Our applications can still be created without data binding. However, the manual process—that is getting data and setting all values manually on controls from code-behind—is error prone and tedious to write. Using the data-binding features in Silverlight, we will be able to write more maintainable code faster. In this article, we'll explore how data binding works. We'll start by building a small data-driven application, which contains the most important data binding features, to get a grasp of the general concepts. We'll also see that data binding isn't tied to just binding single objects to an interface; binding an entire collection of objects is supported as well. We'll also be looking at the binding modes. They allow us to specify how the data will flow (from source to target, target to source, or both). We'll finish this article series by looking at the support that Blend 4 provides to build applications that use data binding features. In the recipes of this article and the following one, we'll assume that we are building a simple banking application using Silverlight. Each of the recipes in this article will highlight a part of this application where the specific feature comes into play. The following screenshot shows the resulting Silverlight banking application: Displaying data in Silverlight applications When building Silverlight applications, we often need to display data to the end user. Applications such as an online store with a catalogue and a shopping cart, an online banking application and so on, need to display data of some sort. Silverlight contains a rich data binding platform that will help us to write data-driven applications faster and using less code. In this recipe, we'll build a form that displays the data of the owner of a bank account using data binding. Getting ready To follow along with this recipe, you can use the starter solution located in the Chapter02/ SilverlightBanking_Displaying_Data_Starter folder in the code bundle available on the Packt website. The finished application for this recipe can be found in the Chapter02/SilverlightBanking_Displaying_Data_Completed folder. How to do it... Let's assume that we are building a form, part of an online banking application, in which we can view the details of the owner of the account. Instead of wiring up the fields of the owner manually, we'll use data binding. To get data binding up and running, carry out the following steps: Open the starter solution, as outlined in the Getting Ready section. The form we are building will bind to data. Data in data binding is in-memory data, not the data that lives in a database (it can originate from a database though). The data to which we are binding is an instance of the Owner class. The following is the code for the class. Add this code in a new class fi le called Owner in the Silverlight project. public class Owner{public int OwnerId { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public string Address { get; set; }public string ZipCode { get; set; }public string City { get; set; }public string State { get; set; }public string Country { get; set; }public DateTime BirthDate { get; set; }public DateTime CustomerSince { get; set; }public string ImageName { get; set; }public DateTime LastActivityDate { get; set; }public double CurrentBalance { get; set; }public double LastActivityAmount { get; set; }} Now that we've created the class, we are able to create an instance of it in the MainPage.xaml.cs file, the code-behind class of MainPage.xaml. In the constructor, we call the InitializeOwner method, which creates an instance of the Owner class and populates its properties. private Owner owner;public MainPage(){InitializeComponent();//initialize owner dataInitializeOwner();}private void InitializeOwner(){owner = new Owner();owner.OwnerId = 1234567;owner.FirstName = "John";owner.LastName = "Smith";owner.Address = "Oxford Street 24";owner.ZipCode = "W1A";owner.City = "London";owner.Country = "United Kingdom";owner.State = "NA";owner.ImageName = "man.jpg";owner.LastActivityAmount = 100;owner.LastActivityDate = DateTime.Today;owner.CurrentBalance = 1234.56;owner.BirthDate = new DateTime(1953, 6, 9);owner.CustomerSince = new DateTime(1999, 12, 20);} Let's now focus on the form itself and build its UI. For this sample, we're not making the data editable. So for every field of the Owner class, we'll use a TextBlock. To arrange the controls on the screen, we'll use a Grid called OwnerDetailsGrid. This Grid can be placed inside the LayoutRoot Grid.We will want the Text property of each TextBlock to be bound to a specifi c property of the Owner instance. This can be done by specifying this binding using the Binding "markup extension" on this property. <Grid x_Name="OwnerDetailsGrid"VerticalAlignment="Stretch"HorizontalAlignment="Left"Background="LightGray"Margin="3 5 0 0"Width="300" ><Grid.RowDefinitions><RowDefinition Height="100"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="30"></RowDefinition><RowDefinition Height="*"></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition></ColumnDefinition><ColumnDefinition></ColumnDefinition></Grid.ColumnDefinitions><Image x_Name="OwnerImage"Grid.Row="0"Width="100"Height="100"Stretch="Uniform"HorizontalAlignment="Left"Margin="3"Source="/CustomerImages/man.jpg"Grid.ColumnSpan="2"></Image><TextBlock x_Name="OwnerIdTextBlock"Grid.Row="1"FontWeight="Bold"Margin="2"Text="Owner ID:"></TextBlock><TextBlock x_Name="FirstNameTextBlock"Grid.Row="2"FontWeight="Bold"Margin="2"Text="First name:"></TextBlock><TextBlock x_Name="LastNameTextBlock"Grid.Row="3"FontWeight="Bold"Margin="2"Text="Last name:"></TextBlock><TextBlock x_Name="AddressTextBlock"Grid.Row="4"FontWeight="Bold"Margin="2"Text="Adress:"></TextBlock><TextBlock x_Name="ZipCodeTextBlock"Grid.Row="5"FontWeight="Bold"Margin="2"Text="Zip code:"></TextBlock><TextBlock x_Name="CityTextBlock"Grid.Row="6"FontWeight="Bold"Margin="2"Text="City:"></TextBlock><TextBlock x_Name="StateTextBlock"Grid.Row="7"FontWeight="Bold"Margin="2"Text="State:"></TextBlock><TextBlock x_Name="CountryTextBlock"Grid.Row="8"FontWeight="Bold"Margin="2"Text="Country:"></TextBlock><TextBlock x_Name="BirthDateTextBlock"Grid.Row="9"FontWeight="Bold"Margin="2"Text="Birthdate:"></TextBlock><TextBlock x_Name="CustomerSinceTextBlock"Grid.Row="10"FontWeight="Bold"Margin="2"Text="Customer since:"></TextBlock><TextBlock x_Name="OwnerIdValueTextBlock"Grid.Row="1"Grid.Column="1"Margin="2"Text="{Binding OwnerId}"></TextBlock><TextBlock x_Name="FirstNameValueTextBlock"Grid.Row="2"Grid.Column="1"Margin="2"Text="{Binding FirstName}"></TextBlock><TextBlock x_Name="LastNameValueTextBlock"Grid.Row="3"Grid.Column="1"Margin="2"Text="{Binding LastName}"></TextBlock><TextBlock x_Name="AddressValueTextBlock"Grid.Row="4"Grid.Column="1"Margin="2"Text="{Binding Address}"></TextBlock><TextBlock x_Name="ZipCodeValueTextBlock"Grid.Row="5"Grid.Column="1"Margin="2"Text="{Binding ZipCode}"></TextBlock><TextBlock x_Name="CityValueTextBlock"Grid.Row="6"Grid.Column="1"Margin="2"Text="{Binding City}"></TextBlock><TextBlock x_Name="StateValueTextBlock"Grid.Row="7"Grid.Column="1"Margin="2"Text="{Binding State}"></TextBlock><TextBlock x_Name="CountryValueTextBlock"Grid.Row="8"Grid.Column="1"Margin="2"Text="{Binding Country}"></TextBlock><TextBlock x_Name="BirthDateValueTextBlock"Grid.Row="9"Grid.Column="1"Margin="2"Text="{Binding BirthDate}"></TextBlock><TextBlock x_Name="CustomerSinceValueTextBlock"Grid.Row="10"Grid.Column="1"Margin="2"Text="{Binding CustomerSince}"></TextBlock><Button x_Name="OwnerDetailsEditButton"Grid.Row="11"Grid.ColumnSpan="2"Margin="3"Content="Edit details..."HorizontalAlignment="Right"VerticalAlignment="Top"></Button><TextBlock x_Name="CurrentBalanceValueTextBlock"Grid.Row="12"Grid.Column="1"Margin="2"Text="{Binding CurrentBalance}" ></TextBlock><TextBlock x_Name="LastActivityDateValueTextBlock"Grid.Row="13"Grid.Column="1"Margin="2"Text="{Binding LastActivityDate}" ></TextBlock><TextBlock x_Name="LastActivityAmountValueTextBlock"Grid.Row="14"Grid.Column="1"Margin="2"Text="{Binding LastActivityAmount}" ></TextBlock></Grid> At this point, all the controls know what property they need to bind to. However, we haven't specifi ed the actual link. The controls don't know about the Owner instance we want them to bind to. Therefore, we can use DataContext. We specify the DataContext of the OwnerDetailsGrid to be the Owner instance. Each control within that container can then access the object and bind to its properties . Setting the DataContext in done using the following code: public MainPage(){InitializeComponent();//initialize owner dataInitializeOwner();OwnerDetailsGrid.DataContext = owner;} The result can be seen in the following screenshot:
Read more
  • 0
  • 0
  • 1588
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 $19.99/month. Cancel anytime
article-image-working-binding-data-and-ui-elements-silverlight-4
Packt
10 May 2010
6 min read
Save for later

Working with Binding data and UI elements in Silverlight 4

Packt
10 May 2010
6 min read
Binding data to another UI element Sometimes, the value of the property of an element is directly dependent on the value of the property of another element. In this case, you can create a binding in XAML called an element binding or element-to-element binding . This binding links both values. If needed, the data can flow bidirectionally. In the banking application, we can add a loan calculator that allows the user to select an amount and the number of years in which they intend to pay the loan back to the bank, including (of course) a lot of interest. Getting ready To follow this recipe, you can either continue with your solution from the previous recipe or use the provided solution that can be found in the Chapter02/SilverlightBanking_ Element_Binding_Starter folder in the code bundle that is available on the Packt website. The finished application for this recipe can be found in the Chapter02/SilverlightBanking_Element_Binding_Completed folder. How to do it... To build the loan calculator, we'll use Slider controls. Each Slider is bound to a TextBlock using an element-to-element binding to display the actual value. Let's take a look at the steps we need to follow to create this binding: We will build the loan calculator as a separate screen in the application. Add a new child window called LoanCalculation.xaml. To do so, right-click on the Silverlight project in the Solution Explorer, select Add | New Item..., and choose Silverlight Child Window under Visual C#. Within MainPage.xaml, add a Click event on the LoanCalculationButton as shown in the following code: <Button x_Name="LoanCalculationButton" Click="LoanCalculationButton_Click" /> In the code-behind's event handler for this Click event, we can trigger the display of this new screen with the following code: private void LoanCalculationButton_Click(object sender, RoutedEventArgs e) { LoanCalculation loanCalculation = new LoanCalculation(); loanCalculation.Show(); } The UI of the LoanCalculation.xaml is quite simple—it contains two Slider controls. Each Slider control has set values for its Minimum and Maximum values (not all UI code is included here; the complete listing can be found in the finished sample code) as shown in the following code: <Slider x_Name="AmountSlider" Minimum="10000" Maximum="1000000" SmallChange="10000" LargeChange="10000" Width="300" > </Slider> <Slider x_Name="YearSlider" Minimum="5" Maximum="30" SmallChange="1" LargeChange="1" Width="300" UseLayoutRounding="True"> </Slider> As dragging a Slider does not give us proper knowledge of where we are exactly between the two values, we add two TextBlock controls. We want the TextBlock controls to show the current value of the Slider control, even while dragging. This can be done by specifying an element-to-element binding as shown in the following code: <TextBlock x_Name="AmountTextBlock" Text="{Binding ElementName=AmountSlider, Path=Value}"> </TextBlock> <TextBlock x_Name="MonthTextBlock" Text="{Binding ElementName=YearSlider, Path=Value}"> </TextBlock> Add a Button that will perform the actual calculation called CalculateButton and a TextBlock called PaybackTextBlock to show the results. This can be done using the following code: <Button x_Name="CalculateButton" Content="Calculate" Click="CalculateButton_Click"> </Button> <TextBlock x_Name="PaybackTextBlock"></TextBlock> The code for the actual calculation that is executed when the Calculate button is clicked uses the actual value for either the Slider or the TextBlock. This is shown in the following code: private double percentage = 0.0345; private void CalculateButton_Click(object sender, RoutedEventArgs e) { double requestedAmount = AmountSlider.Value; int requestedYears = (int)YearSlider.Value; for (int i = 0; i < requestedYears; i++) { requestedAmount += requestedAmount * percentage; } double monthlyPayback = requestedAmount / (requestedYears * 12); PaybackTextBlock.Text = "€" + Math.Round(monthlyPayback, 2); } Having carried out the previous steps, we now have successfully linked the value of the Slider controls and the text of the TextBlock controls. The following screenshot shows the LoanCalculation.xaml screen as it is included in the finished sample code containing some extra markup: How it works... An element binding links two properties of two controls directly from XAML. It allows creating a Binding where the source object is another control. For this to work, we need to create a Binding and specify the source control using the ElementName property. This is shown in the following code: <TextBlock Text="{Binding ElementName=YearSlider, Path=Value}" > </TextBlock> Element bindings were added in Silverlight 3. Silverlight 2 did not support this type of binding. There's more... An element binding can also work in both directions, that is, from source to target and vice versa. This can be achieved by specifying the Mode property on the Binding and setting it to TwoWay. The following is the code for this. In this code, we replaced the TextBlock by a TextBox. When entering a value in the latter, the Slider will adjust its position: <TextBox x_Name="AmountTextBlock" Text="{Binding ElementName=AmountSlider, Path=Value, Mode=TwoWay}" > </TextBox> Element bindings without bindings Achieving the same effect in Silverlight 2—which does not support this feature—is also possible, but only through the use of an event handler as shown in the following code. Element bindings eliminate this need: private void AmountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { AmountSlider.Value = Math.Round(e.NewValue); AmountTextBlock.Text = AmountSlider.Value.ToString(); } See also Element-to-element bindings can be easily extended to use converters. For more information on TwoWay bindings, take a look at the Using the different modes of data binding to allow persisting data recipe in this article. Binding collections to UI elements Often, you'll want to display lists of data in your application such as a list of shopping items, a list of users, a list of bank accounts, and so on. Such a list typically contains a bunch of items of a certain type that have the same properties and need to be displayed in the same fashion. We can use data binding to easily bind a collection to a Silverlight control (such as a ListBox or DataGrid) and use the same data binding possibilities to defi ne how every item in the collection should be bound. This recipe will show you how to achieve this. Getting ready For this recipe, you can fi nd the starter solution in the Chapter02/SilverlightBanking_ Binding_Collections_Starter folder and the completed solution in the Chapter02/SilverlightBanking_Binding_Collections_Completed folder in the code bundle that is available on the Packt website.
Read more
  • 0
  • 0
  • 1507

article-image-data-manipulation-silverlight-4-data-grid
Packt
26 Apr 2010
9 min read
Save for later

Data Manipulation in Silverlight 4 Data Grid

Packt
26 Apr 2010
9 min read
Displaying data in a customized DataGrid Displaying data is probably the most straightforward task we can ask the DataGrid to do for us. In this recipe, we'll create a collection of data and hand it over to the DataGrid for display. While the DataGrid may seem to have a rather fixed layout, there are many options available on this control that we can use to customize it. In this recipe, we'll focus on getting the data to show up in the DataGrid and customize it to our likings. Getting ready In this recipe, we'll start from an empty Silverlight application. The finished solution for this recipe can be found in the Chapter04/Datagrid_Displaying_Data_Completed folder in the code bundle that is available on the Packt website. How to do it... We'll create a collection of Book objects and display this collection in a DataGrid. However,we want to customize the DataGrid. More specifically, we want to make the DataGridfixed. In other words, we don't want the user to make any changes to the bound data or move the columns around. Also, we want to change the visual representation of the DataGrid by changing the background color of the rows. We also want the vertical column separators to be hidden and the horizontal ones to get a different color. Finally, we'll hook into the LoadingRow event, which will give us access to the values that are bound to a row and based on that value, the LoadingRow event will allow us to make changes to the visual appearance of the row. To create this DataGrid, you'll need to carry out the following steps: Start a new Silverlight solution called DatagridDisplayingData in Visual Studio. We'll start by creating the Book class. Add a new class to the Silverlight project in the solution and name this class as Book. Note that this class uses two enumerations—one for the Category and the other for the Language. These can be found in the sample code. The following is the code for the Book class: public class Book { public string Title { get; set; } public string Author { get; set; } public int PageCount { get; set; } public DateTime PurchaseDate { get; set; } public Category Category { get; set; } public string Publisher { get; set; } public Languages Language { get; set; } public string ImageName { get; set; } public bool AlreadyRead { get; set; } } In the code-behind of the generated MainPage.xaml file, we need to create a generic list of Book instances (List) and load data into this collection.This is shown in the following code: private List<Book> bookCollection; public MainPage() { InitializeComponent(); LoadBooks(); } private void LoadBooks() { bookCollection = new List<Book>(); Book b1 = new Book(); b1.Title = "Book AAA"; b1.Author = "Author AAA"; b1.Language = Languages.English; b1.PageCount = 350; b1.Publisher = "Publisher BBB"; b1.PurchaseDate = new DateTime(2009, 3, 10); b1.ImageName = "AAA.png"; b1.AlreadyRead = true; b1.Category = Category.Computing; bookCollection.Add(b1); ... } Next, we'll add a DataGrid to the MainPage.xaml file. For now, we won't add any extra properties on the DataGrid. It's advisable to add it to the page by dragging it from the toolbox, so that Visual Studio adds the correct references to the required assemblies in the project, as well as adds the namespace mapping in the XAML code. Remove the AutoGenerateColumns="False" for now so that we'll see all the properties of the Book class appear in the DataGrid. The following line of code shows a default DataGrid with its name set to BookDataGrid: <sdk:DataGrid x_Name="BookDataGrid"></sdk:DataGrid> Currently, no data is bound to the DataGrid. To make the DataGrid show the book collection, we set the ItemsSource property from the code-behind in the constructor. This is shown in the following code: public MainPage() { InitializeComponent(); LoadBooks(); BookDataGrid.ItemsSource = bookCollection; } Running the code now shows a default DataGrid that generates a column for each public property of the Book type. This happens because the AutoGenerateColumns property is True by default. Let's continue by making the DataGrid look the way we want it to look. By default, the DataGrid is user-editable, so we may want to change this feature. Setting the IsReadOnly property to True will make it impossible for a user to edit the data in the control. We can lock the display even further by setting both the CanUserResizeColumns and the CanUserReorderColumns properties to False. This will prohibit the user from resizing and reordering the columns inside the DataGrid, which are enabled by default. This is shown in the following code: <sdk:DataGrid x_Name="BookDataGrid" AutoGenerateColumns="True" CanUserReorderColumns="False" CanUserResizeColumns="False" IsReadOnly="True"> </sdk:DataGrid> The DataGrid also offers quite an impressive list of properties that we can use to change its appearance. By adding the following code, we specify alternating the background colors (the RowBackground and AlternatingRowBackground properties), column widths (the ColumnWidth property), and row heights (the RowHeight property). We also specify how the gridlines should be displayed (the GridLinesVisibility and HorizontalGridLinesBrushs properties). Finally, we specify that we also want a row header to be added (the HeadersVisibility property ). <sdk:DataGrid x_Name="BookDataGrid" AutoGenerateColumns="True" CanUserReorderColumns="False" CanUserResizeColumns="False" RowBackground="#999999" AlternatingRowBackground="#CCCCCC" ColumnWidth="90" RowHeight="30" GridLinesVisibility="Horizontal" HeadersVisibility="All" HorizontalGridLinesBrush="Blue"> </sdk:DataGrid> We can also get a hook into the loading of the rows. For this, the LoadingRow event has to be used. This event is triggered when each row gets loaded. Using this event, we can get access to a row and change its properties based on custom code. In the following code, we are specifying that if the book is a thriller, we want the row to have a red background: private void BookDataGrid_LoadingRow(object sender, DataGridRowEventArgs e) { Book loadedBook = e.Row.DataContext as Book; if (loadedBook.Category == Category.Thriller) { e.Row.Background = new SolidColorBrush(Colors.Red); //It's a thriller! e.Row.Height = 40; } else { e.Row.Background = null; } } After completing these steps, we have the DataGrid that we wanted. It displays the data (including headers), fixes the columns and makes it impossible for the user to edit the data. Also, the color of the rows and alternating rows is changed, the vertical grid lines are hidden, and a different color is applied to the horizontal grid lines. Using the LoadingRow event, we have checked whether the book being added is of the "Thriller" category, and if so, a red color is applied as the background color for the row. The result can be seen in the following screenshot: How it works... The DataGrid allows us to display the data easily, while still offering us many customization options to format the control as needed. The DataGrid is defined in the System.Windows.Controls namespace, which is located in the System.Windows.Controls.Data assembly. By default, this assembly is not referenced while creating a new Silverlight application. Therefore, the following extra references are added while dragging the control from the toolbox for the first time: System.ComponentModel.DataAnnotations System.Windows.Controls.Data System.Windows.Controls.Data.Input System.Windows.Data While compiling the application, the corresponding assemblies are added to the XAP file (as can be seen in the following screenshot, which shows the contents of the XAP file). These assemblies need to be added because while installing the Silverlight plugin, they aren't installed as a part of the CLR. This is done in order to keep the plugin size small. However, when we use them in our application, they are embedded as part of the application. This results in an increase of the download size of the XAP file. In most circumstances, this is not a problem. However, if the file size is an important requirement, then it is essential to keep an eye on this. Also, Visual Studio will include the following namespace mapping into the XAML file: From then on, we can use the control as shown in the following line of code: <sdk:DataGrid x_Name="BookDataGrid"> </sdk:DataGrid> Once the control is added on the page, we can use it in a data binding scenario. To do so, we can point the ItemsSource property to any IEnumerable implementation. Each row in the DataGrid will correspond to an object in the collection. When AutoGenerateColumns is set to True (the default), the DataGrid uses a refl ection on the type of objects bound to it. For each public property it encounters, it generates a corresponding column. Out of the box, the DataGrid includes a text column, a checkbox column, and a template column. For all the types that can't be displayed, it uses the ToString method and a text column. If we want the DataGrid to feature automatic synchronization, the collection should implement the INotifyCollectionChanged interface. If changes to the objects are to be refl ected in the DataGrid, then the objects in the collection should themselves implement the INotifyPropertyChanged interface. There's more While loading large amounts of data into the DataGrid, the performance will still be very good. This is the result of the DataGrid implementing UI virtualization, which is enabled by default. Let's assume that the DataGrid is bound to a collection of 1,000,000 items (whether or not this is useful is another question). Loading all of these items into memory would be a time-consuming task as well as a big performance hit. Due to UI virtualization, the control loads only the rows it's currently displaying. (It will actually load a few more to improve the scrolling experience.) While scrolling, a small lag appears when the control is loading the new items. Since Silverlight 3, the ListBox also features UI virtualization. Inserting, updating, and deleting data in a DataGrid The DataGrid is an outstanding control to use while working with large amounts of data at the same time. Through its Excel-like interface, not only can we easily view the data, but also add new records or update and delete existing ones. In this recipe, we'll take a look at how to build a DataGrid that supports all of the above actions on a collection of items. Getting ready This recipe builds on the code that was created in the previous recipe. To follow along with this recipe, you can keep using your code or use the starter solution located in the Chapter04/Datagrid_Editing_Data_Starter folder in the code bundle available on the Packt website. The finished solution for this recipe can be found in the Chapter04/Datagrid_Editing_Data_Completed folder.
Read more
  • 0
  • 0
  • 2039

article-image-building-simple-address-book-application-jquery-and-php
Packt
19 Feb 2010
14 min read
Save for later

Building a Simple Address Book Application with jQuery and PHP

Packt
19 Feb 2010
14 min read
Let's get along. The application folder will be made up of five files: addressbook.css addressbook.html addressbook.php addressbook.js jquery.js Addressbook.css will contain the css for the interface styling, addressbook.html will contain the html source, addressbook.js contains  javascript codes, addressbook.php will mostly contain the server side code that will store the contacts to database, delete the contacts, provide updates and fetch the list of the contacts. Let's look through the HTML We include the scripts and the css file in the head tag in addressbook.html file. <title>sample address book</title> <link rel="stylesheet" type="text/css" href="addressbook.css"> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="addressbook.js"></script> The code above includes the css for styling the application, jquery library for cross browser javascript and easy DOM access, and the addressbook.js contains functions that help user actions translated via javascript and ajax calls. The Body tag should contain this: <div id="Layer1"> <h1>Simple Address Book</h1> <div id="addContact">               <a href="#add-contact" id="add-contact-btn">Add Contact</a>               <table id="add-contact-form">               <tr>               <td>Names:</td><td><input type="text" name="names" id="names"  /></td>               </tr>               <tr>               <td>Phone Number:</td><td><input type="text" name="phone" id="phone"  /></td>               </tr>               <tr>               <td>&nbsp;</td><td>               <a href="#save-contact" id="save-contact-btn">Save Contact</a>               <a href="#cancel" id="cancel-btn">Cancel</a>               </td>               </tr>               </table> </div> <div id="notice">               notice box </div> <div id="list-title">My Contact List</div> <ul id="contacts-lists">         <li>mambe nanje [+23777545907] - <a href="#delete-id" class="deletebtn" contactid='1'> delete contact </a></li>         <li>mambe nanje [+23777545907] - <a href="#delete-id" class="deletebtn" contactid='2'> delete contact</a></li>         <li>mambe nanje [+23777545907] - <a  href="#delete-id" class="deletebtn" contactid='3'> delete contact</a></li> </ul> </div> The above code creates an html form that provides input fields to insert new address book entries. It also displays a button to make it appear via javascript functions. It also creates a notification div and goes to display the contact list with delete button on each entry. With the above code, the application will now look like this:   /* CSS Document */   body {               background-color: #000000; } #Layer1 {               margin:auto;               width:484px;               height:308px;               z-index:1; } #add-contact-form{               color:#FF9900;               font-weight:bold;               font-family:Verdana, Arial, Helvetica, sans-serif;               background-color:#333333;               margin-top:5px;               padding:10px; } #add-contact-btn{               background-color:#FF9900;               font-weight:bold;               font-family:Verdana, Arial, Helvetica, sans-serif;               border:1px solid #666666;               color:#000;               text-decoration:none;               padding:2px;               font-weight:bold; } #save-contact-btn{               background-color:#FF9900;               font-weight:bold;               font-family:Verdana, Arial, Helvetica, sans-serif;               border:1px solid #666666;               color:#000;               text-decoration:none;               padding:2px;               font-weight:bold; } #cancel-btn{               background-color:#FF9900;               font-weight:bold;               font-family:Verdana, Arial, Helvetica, sans-serif;               border:1px solid #666666;               color:#000;               text-decoration:none;               padding:2px;               font-weight:bold; } h1{               color:#FFFFFF;               font-family:Arial, Helvetica, sans-serif; } #list-title{               color:#FFFFFF;               font-weight:bold;               font-size:14px;               font-family:Arial, Helvetica, sans-serif;               margin-top:10px; } #contacts-lists{               color:#FF6600;               font-weight:bold;               font-family:Verdana, Arial, Helvetica, sans-serif;               font-size:12px; } #contacts-lists a{               background-color:#FF9900;               text-decoration:none;                            padding:2px;               color:#000;               margin-bottom:2px; } #contacts-lists li{               list-style:none;               border-bottom:1px dashed #666666;               margin-bottom:10px;               padding-bottom:5px; } #notice{               width:400px;               margin:auto;               background-color:#FFFF99;               border:1px solid #FFCC99;               font-weight:bold;               font-family:verdana;               margin-top:10px;               padding:4px; } The CSS code styles the HTML above and it ends up looking like this: Now that we have our html and css perfectly working, we need to setup the database and the PHP server codes that will handle the AJAX requests from the jquery functions. Create a MySQL database and executing the following SQL code will create the contacts table. This is the only table this application needs. CREATE TABLE `contacts` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `names` VARCHAR( 200 ) NOT NULL , `phone` VARCHAR( 100 ) NOT NULL ); Let's analyse the php codes. Remember, this code will be located in addressbook.php. The database connection code # FileName="Connection_php_mysql.htm" # Type="MYSQL" # HTTP="true" //configure the database paramaters $hostname_packpub_addressbook = "YOUR-DATABASE-HOST"; $database_packpub_addressbook = "YOUR-DATABASE-NAME"; $username_packpub_addressbook = "YOUR-DATABASE-USERNAME"; $password_packpub_addressbook = "YOUR-DATABASE-PASSWORD"; //connect to the database server $packpub_addressbook = mysql_pconnect($hostname_packpub_addressbook, $username_packpub_addressbook,  $password_packpub_addressbook) or trigger_error(mysql_error(),E_USER_ERROR); //selete the database mysql_select_db($database_packpub_addressbook); the above code sets the parameters required for the database connection, then establishes a connection to the server and selects your database. The PHP codes will then contain functions SAVECONTACTS, DELETECONTACTS, GETCONTACTS. These functions will do exactly as their name implies. Save the contact from AJAX call to the database, delete contact via AJAX request or get the contacts. The functions are as show below: //function to save new contact /** * @param <string> $name //name of the contact * @param <string> $phone //the telephone number of the contact */ function saveContact($name,$phone){               $sql="INSERT INTO contacts (names , phone ) VALUES ('".$name."','".$phone."');";               $result=mysql_query($sql)or die(mysql_error()); } //lets write a function to delete contact /** * @param <int> id //the contact id in database we wish to delete */ function deleteContact($id){               $sql="DELETE FROM contacts where id=".$id;               $result=mysql_query($sql); }   //lets get all the contacts function getContacts(){               //execute the sql to get all the contacts in db               $sql="SELECT * FROM contacts";               $result=mysql_query($sql);               //store the contacts in an array of objects               $contacts=array();               while($record=mysql_fetch_object($result)){                             array_push($contacts,$record);               }               //return the contacts               return $contacts; } The codes above creates the functions but the functions are not called till the following code executes: //lets handle the Ajax calls now $action=$_POST['action']; //the action for now is either add or delete if($action=="add"){               //get the post variables for the new contact               $name=$_POST['name'];               $phone=$_POST['phone'];               //save the new contact               saveContact($name,$phone);               $output['msg']=$name." has been saved successfully";               //reload the contacts               $output['contacts']=getContacts();               echo json_encode($output); }else if($action=="delete"){               //collect the id we wish to delete               $id=$_POST['id'];               //delete the contact with that id               deleteContact($id);               $output['msg']="one entry has been deleted successfully";               //reload the contacts               $output['contacts']=getContacts();               echo json_encode($output); }else{               $output['contacts']=getContacts();               $output['msg']="list of all contacts";               echo json_encode($output); } The above code is the heart of the addressbook.php codes. It gets the action from post variables sent via AJAX call in addressbook.js file, interprets the action and executes the appropriate function for either add, delete or nothing which will just get the list of contacts. json_encode() function is used to encode the data in to Javascript Object Notation format; it will be easily interpreted by the javascript codes.
Read more
  • 0
  • 0
  • 9213

article-image-ajax-form-validation-part-2
Packt
19 Feb 2010
11 min read
Save for later

AJAX Form Validation: Part 2

Packt
19 Feb 2010
11 min read
How to implement AJAX form validation In this article, we redesigned the code for making AJAX requests when creating the XmlHttp class. The AJAX form validation application makes use of these techniques. The application contains three pages: One page renders the form to be validated Another page validates the input The third page is displayed if the validation is successful The application will have a standard structure, composed of these files: index.php: It is the file loaded initially by the user. It contains references to the necessary JavaScript files and makes asynchronous requests for validation to validate.php. index_top.php: It is a helper file loaded by index.php and contains several objects for rendering the HTML form. validate.css: It is the file containing the CSS styles for the application. json2.js: It is the JavaScript file used for handling JSON objects. xhr.js: It is the JavaScript file that contains our XmlHttp object used for making AJAX requests. validate.js: It is the JavaScript file loaded together with index.php on the client side. It makes asynchronous requests to a PHP script called validate.php to perform the AJAX validation. validate.php: It is a PHP script residing on the same server as index.php, and it offers the server-side functionality requested asynchronously by the JavaScript code in index.php. validate.class.php: It is a PHP script that contains a class called Validate, which contains the business logic and database operations to support the functionality of validate.php. config.php: It will be used to store global configuration options for your application, such as database connection data, and so on. error_handler.php: It contains the error-handling mechanism that changes the text of an error message into a human-readable format. allok.php: It is the page to be displayed if the validation is successful. Time for action – AJAX form validation Connect to the ajax database and create a table named users with the following code: CREATE TABLE users ( user_id INT UNSIGNED NOT NULL AUTO_INCREMENT, user_name VARCHAR(32) NOT NULL, PRIMARY KEY (user_id) ); Execute the following INSERT commands to populate your users table with some sample data: INSERT INTO users (user_name) VALUES ('bogdan'); INSERT INTO users (user_name) VALUES ('audra'); INSERT INTO users (user_name) VALUES ('cristian'); Let's start writing the code with the presentation tier. We'll define the styles for our form by creating a file named validate.css, and adding the following code to it: body { font-family: Arial, Helvetica, sans-serif; font-size: 0.8em; color: #000000; } label { float: left; width: 150px; font-weight: bold; } input, select { margin-bottom: 3px; } .button { font-size: 2em; } .left { margin-left: 150px; } .txtFormLegend { color: #777777; font-weight: bold; font-size: large; } .txtSmall { color: #999999; font-size: smaller; } .hidden { display: none; } .error { display: block; margin-left: 150px; color: #ff0000; } Now create a new file named index_top.php, and add the following code to it. This script will be loaded from the main page index.php. <?php // enable PHP session session_start(); // Build HTML <option> tags function buildOptions($options, $selectedOption) { foreach ($options as $value => $text) { if ($value == $selectedOption) { echo '<option value="' . $value . '" selected="selected">' . $text . '</option>'; } else { echo '<option value="' . $value . '">' . $text . '</option>'; } } } // initialize gender options array $genderOptions = array("0" => "[Select]", "1" => "Male", "2" => "Female"); // initialize month options array $monthOptions = array("0" => "[Select]", "1" => "January", "2" => "February", "3" => "March", "4" => "April", "5" => "May", "6" => "June", "7" => "July", "8" => "August", "9" => "September", "10" => "October", "11" => "November", "12" => "December"); // initialize some session variables to prevent PHP throwing // Notices if (!isset($_SESSION['values'])) { $_SESSION['values']['txtUsername'] = ''; $_SESSION['values']['txtName'] = ''; $_SESSION['values']['selGender'] = ''; $_SESSION['values']['selBthMonth'] = ''; $_SESSION['values']['txtBthDay'] = ''; $_SESSION['values']['txtBthYear'] = ''; $_SESSION['values']['txtEmail'] = ''; $_SESSION['values']['txtPhone'] = ''; $_SESSION['values']['chkReadTerms'] = ''; } if (!isset($_SESSION['errors'])) { $_SESSION['errors']['txtUsername'] = 'hidden'; $_SESSION['errors']['txtName'] = 'hidden'; $_SESSION['errors']['selGender'] = 'hidden'; $_SESSION['errors']['selBthMonth'] = 'hidden'; $_SESSION['errors']['txtBthDay'] = 'hidden'; $_SESSION['errors']['txtBthYear'] = 'hidden'; $_SESSION['errors']['txtEmail'] = 'hidden'; $_SESSION['errors']['txtPhone'] = 'hidden'; $_SESSION['errors']['chkReadTerms'] = 'hidden'; } ?> Now create index.php, and add the following code to it: <?php require_once ('index_top.php'); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www. w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html > <head> <title>Degradable AJAX Form Validation with PHP and MySQL</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link href="validate.css" rel="stylesheet" type="text/css" /> </head> <body onload="setFocus();"> <script type="text/javascript" src="json2.js"></script> <script type="text/javascript" src="xhr.js"></script> <script type="text/javascript" src="validate.js"></script> <fieldset> <legend class="txtFormLegend"> New User Registratio Form </legend> <br /> <form name="frmRegistration" method="post" action="validate.php"> <input type="hidden" name="validationType" value="php"/> <!-- Username --> <label for="txtUsername">Desired username:</label> <input id="txtUsername" name="txtUsername" type="text" onblur="validate(this.value, this.id)" value="<?php echo $_SESSION['values'] ['txtUsername'] ?>" /> <span id="txtUsernameFailed" class="<?php echo $_SESSION['errors']['txtUsername'] ?>"> This username is in use, or empty username field. </span> <br /> <!-- Name --> <label for="txtName">Your name:</label> <input id="txtName" name="txtName" type="text" onblur="validate(this.value, this.id)" value="<?php echo $_SESSION['values']['txtName'] ?>" /> <span id="txtNameFailed" class="<?php echo $_SESSION['errors']['txtName']?>"> Please enter your name. </span> <br /> <!-- Gender --> <label for="selGender">Gender:</label> <select name="selGender" id="selGender" onblur="validate(this.value, this.id)"> <?php buildOptions($genderOptions, $_SESSION['values']['selGender']); ?> </select> <span id="selGenderFailed" class="<?php echo $_SESSION['errors']['selGender'] ?>"> Please select your gender. </span> <br /> <!-- Birthday --> <label for="selBthMonth">Birthday:</label> <!-- Month --> <select name="selBthMonth" id="selBthMonth" onblur="validate(this.value, this.id)"> <?php buildOptions($monthOptions, $_SESSION['values']['selBthMonth']); ?> </select> &nbsp;-&nbsp; <!-- Day --> <input type="text" name="txtBthDay" id="txtBthDay" maxlength="2" size="2" onblur="validate(this.value, this.id)" value="<?php echo $_SESSION['values']['txtBthDay'] ?>" /> &nbsp;-&nbsp; <!-- Year --> <input type="text" name="txtBthYear" id="txtBthYear" maxlength="4" size="2" onblur="validate(document.getElementById ('selBthMonth').options[document.getElementById ('selBthMonth').selectedIndex].value + '#' + document.getElementById('txtBthDay').value + '#' + this.value, this.id)" value="<?php echo $_SESSION['values']['txtBthYear'] ?>" /> <!-- Month, Day, Year validation --> <span id="selBthMonthFailed" class="<?php echo $_SESSION['errors']['selBthMonth'] ?>"> Please select your birth month. </span> <span id="txtBthDayFailed" class="<?php echo $_SESSION['errors']['txtBthDay'] ?>"> Please enter your birth day. </span> <span id="txtBthYearFailed" class="<?php echo $_SESSION['errors']['txtBthYear'] ?>"> Please enter a valid date. </span> <br /> <!-- Email --> <label for="txtEmail">E-mail:</label> <input id="txtEmail" name="txtEmail" type="text" onblur="validate(this.value, this.id)" value="<?php echo $_SESSION['values']['txtEmail'] ?>" /> <span id="txtEmailFailed" class="<?php echo $_SESSION['errors']['txtEmail'] ?>"> Invalid e-mail address. </span> <br /> <!-- Phone number --> <label for="txtPhone">Phone number:</label> <input id="txtPhone" name="txtPhone" type="text" onblur="validate(this.value, this.id)" value="<?php echo $_SESSION['values']['txtPhone'] ?>" /> <span id="txtPhoneFailed" class="<?php echo $_SESSION['errors']['txtPhone'] ?>"> Please insert a valid US phone number (xxx-xxx-xxxx). </span> <br /> <!-- Read terms checkbox --> <input type="checkbox" id="chkReadTerms" name="chkReadTerms" class="left" onblur="validate(this.checked, this.id)" <?php if ($_SESSION['values']['chkReadTerms'] == 'on') echo 'checked="checked"' ?> /> I've read the Terms of Use <span id="chkReadTermsFailed" class="<?php echo$_SESSION['errors'] ['chkReadTerms'] ?>"> Please make sure you read the Terms of Use. </span> <!-- End of form --> <hr /> <span class="txtSmall">Note: All fields arerequired. </span> <br /><br /> <input type="submit" name="submitbutton" value="Register" class="left button" /> </form> </fieldset> </body> </html> Create a new file named allok.php, and add the following code to it: <?php // clear any data saved in the session session_start(); session_destroy(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html > <head> <title>AJAX Form Validation</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link href="validate.css" rel="stylesheet" type="text/css" /> </head> <body> Registration Successful!<br /> <a href="index.php" title="Go back">&lt;&lt; Go back</a> </body> </html> Copy json2.js (which you downloaded in a previous exercise from http://json.org/json2.js) to your ajax/validate folder. Create a file named validate.js. This file performs the client-side functionality, including the AJAX requests: // holds the remote server address var serverAddress = "validate.php"; // when set to true, display detailed error messages var showErrors = true; // the function handles the validation for any form field function validate(inputValue, fieldID) { // the data to be sent to the server through POST var data = "validationType=ajax&inputValue=" + inputValue + "&fieldID=" + fieldID; // build the settings object for the XmlHttp object var settings = { url: serverAddress, type: "POST", async: true, complete: function (xhr, response, status) { if (xhr.responseText.indexOf("ERRNO") >= 0 || xhr.responseText.indexOf("error:") >= 0 || xhr.responseText.length == 0) { alert(xhr.responseText.length == 0 ? "Server error." : response); } result = response.result; fieldID = response.fieldid; // find the HTML element that displays the error message = document.getElementById(fieldID + "Failed"); // show the error or hide the error message.className = (result == "0") ? "error" : "hidden"; }, data: data, showErrors: showErrors }; // make a server request to validate the input data var xmlHttp = new XmlHttp(settings); } // sets focus on the first field of the form function setFocus() { document.getElementById("txtUsername").focus(); } Now it's time to add the server-side logic. Start by creating config.php, with the following code in it: <?php // defines database connection data define('DB_HOST', 'localhost'); define('DB_USER', 'ajaxuser'); define('DB_PASSWORD', 'practical'); define('DB_DATABASE', 'ajax'); ?> Now create the error handler code in a file named error_handler.php: <?php // set the user error handler method to be error_handler set_error_handler('error_handler', E_ALL); // error handler function function error_handler($errNo, $errStr, $errFile, $errLine) { // clear any output that has already been generated if(ob_get_length()) ob_clean(); // output the error message $error_message = 'ERRNO: ' . $errNo . chr(10) . 'TEXT: ' . $errStr . chr(10) . 'LOCATION: ' . $errFile . ', line ' . $errLine; echo $error_message; // prevent processing any more PHP scripts exit; } ?> The PHP script that handles the client's AJAX calls, and also handles the validation on form submit, is validate.php: <?php // start PHP session session_start(); // load error handling script and validation class require_once ('error_handler.php'); require_once ('validate.class.php'); // Create new validator object $validator = new Validate(); // read validation type (PHP or AJAX?) $validationType = ''; if (isset($_POST['validationType'])) { $validationType = $_POST['validationType']; } // AJAX validation or PHP validation? if ($validationType == 'php') { // PHP validation is performed by the ValidatePHP method, //which returns the page the visitor should be redirected to //(which is allok.php if all the data is valid, or back to //index.php if not) header('Location:' . $validator->ValidatePHP()); } else { // AJAX validation is performed by the ValidateAJAX method. //The results are used to form a JSON document that is sent //back to the client $response = array('result' => $validator->ValidateAJAX ($_POST['inputValue'],$_POST['fieldID']), 'fieldid' => $_POST['fieldID'] ); // generate the response if(ob_get_length()) ob_clean(); header('Content-Type: application/json'); echo json_encode($response); } ?>
Read more
  • 0
  • 0
  • 1582
article-image-ajax-form-validation-part-1
Packt
18 Feb 2010
4 min read
Save for later

AJAX Form Validation: Part 1

Packt
18 Feb 2010
4 min read
The server is the last line of defense against invalid data, so even if you implement client-side validation, server-side validation is mandatory. The JavaScript code that runs on the client can be disabled permanently from the browser's settings and/or it can be easily modified or bypassed. Implementing AJAX form validation The form validation application we will build in this article validates the form at the server side on the classic form submit, implementing AJAX validation while the user navigates through the form. The final validation is performed at the server, as shown in Figure 5-1: Doing a final server-side validation when the form is submitted should never be considered optional. If someone disables JavaScript in the browser settings, AJAX validation on the client side clearly won't work, exposing sensitive data, and thereby allowing an evil-intentioned visitor to harm important data on the server (for example, through SQL injection). Always validate user input on the server. As shown in the preceding figure, the application you are about to build validates a registration form using both AJAX validation (client side) and typical server-side validation: AJAX-style (client side): It happens when each form field loses focus (onblur). The field's value is immediately sent to and evaluated by the server, which then returns a result (0 for failure, 1 for success). If validation fails, an error message will appear and notify the user about the failed validation, as shown in Figure 5-3. PHP-style (server side): This is the usual validation you would do on the server—checking user input against certain rules after the entire form is submitted. If no errors are found and the input data is valid, the browser is redirected to a success page, as shown in Figure 5-4. If validation fails, however, the user is sent back to the form page with the invalid fields highlighted, as shown in Figure 5-3. Both AJAX validation and PHP validation check the entered data against our application's rules: Username must not already exist in the database Name field cannot be empty A gender must be selected Month of birth must be selected Birthday must be a valid date (between 1-31) Year of birth must be a valid year (between 1900-2000) The date must exist in the number of days for each month (that is, there's no February 31) E-mail address must be written in a valid email format Phone number must be written in standard US form: xxx-xxx-xxxx The I've read the Terms of Use checkbox must be selected Watch the application in action in the following screenshots: XMLHttpRequest, version 2 We do our best to combine theory and practice, before moving on to implementing the AJAX form validation script, we'll have another quick look at our favorite AJAX object—XMLHttpRequest. On this occasion, we will step up the complexity (and functionality) a bit and use everything we have learned until now. We will continue to build on what has come before as we move on; so again, it's important that you take the time to be sure you've understood what we are doing here. Time spent on digging into the materials really pays off when you begin to build your own application in the real world. Our OOP JavaScript skills will be put to work improving the existing script that used to make AJAX requests. In addition to the design that we've already discussed, we're creating the following features as well: Flexible design so that the object can be easily extended for future needs and purposes The ability to set all the required properties via a JSON object We'll package this improved XMLHttpRequest functionality in a class named XmlHttp that we'll be able to use in other exercises as well. You can see the class diagram in the following screenshot, along with the diagrams of two helper classes: settings is the class we use to create the call settings; we supply an instance of this class as a parameter to the constructor of XmlHttp complete is a callback delegate, pointing to the function we want executed when the call completes The final purpose of this exercise is to create a class named XmlHttp that we can easily use in other projects to perform AJAX calls. With our goals in mind, let's get to it! Time for action – the XmlHttp object In the ajax folder, create a folder named validate, which will host the exercises in this article.
Read more
  • 0
  • 0
  • 3644

article-image-implementing-ajax-grid-using-jquery-data-grid-plugin-jqgrid
Packt
05 Feb 2010
9 min read
Save for later

Implementing AJAX Grid using jQuery data grid plugin jqGrid

Packt
05 Feb 2010
9 min read
In this article by Audra Hendrix, Bogdan Brinzarea and Cristian Darie, authors of AJAX and PHP: Building Modern Web Applications 2nd Edition, we will discuss the usage of an AJAX-enabled data grid plugin, jqGrid. One of the most common ways to render data is in the form of a data grid. Grids are used for a wide range of tasks from displaying address books to controlling inventories and logistics management. Because centralizing data in repositories has multiple advantages for organizations, it wasn't long before a large number of applications were being built to manage data through the Internet and intranet applications by using data grids. But compared to their desktop cousins, online applications using data grids were less than stellar - they felt cumbersome and time consuming, were not always the easiest things to implement (especially when you had to control varying access levels across multiple servers), and from a usability standpoint, time lags during page reloads, sorts, and edits made online data grids a bit of a pain to use, not to mention the resources that all of this consumed. As you are a clever reader, you have undoubtedly surmised that you can use AJAX to update the grid content; we are about to show you how to do it! Your grids can update without refreshing the page, cache data for manipulation on the client (rather than asking the server to do it over and over again), and change their looks with just a few keystrokes! Gone forever are the blinking pages of partial data and sessions that time out just before you finish your edits. Enjoy! In this article, we're going to use a jQuery data grid plugin named jqGrid. jqGrid is freely available for private and commercial use (although your support is appreciated) and can be found at: http://www.trirand.com/blog/. You may have guessed that we'll be using PHP on the server side but jqGrid can be used with any of the several server-side technologies. On the client side, the grid is implemented using JavaScript's jQuery library and JSON. The look and style of the data grid will be controlled via CSS using themes, which make changing the appearance of your grid easy and very fast. Let's start looking at the plugin and how easily your newly acquired AJAX skills enable you to quickly add functionality to any website. Our finished grid will look like the one in Figure 9-1:   Figure 9-1: AJAX Grid using jQuery Let's take a look at the code for the grid and get started building it. Implementing the AJAX data grid The files and folders for this project can be obtained directly from the code download(chap:9) for this article, or can be created by typing them in. We encourage you to use the code download to save time and for accuracy. If you choose to do so, there are just a few steps you need to follow: Copy the grid folder from the code download to your ajax folder. Connect to your ajax database and execute the product.sql script. Update config.php with the correct database username and password. Load http://localhost/ajax/grid to verify the grid works fine - it should look just like Figure 9-1. You can test the editing feature by clicking on a row, making changes, and hitting the Enter key. Figure 9-2 shows a row in editing mode:     Figure 9-2: Editing a row Code overview If you prefer to type the code yourself, you'll find a complete step-by-step exercise a bit later in this article. Before then, though, let's quickly review what our grid is made of. We'll review the code in greater detail at the end of this article. The editable grid feature is made up of a few components: product.sql is the script that creates the grid database config.php and error_handler.php are our standard helper scripts grid.php and grid.class.php make up the server-side functionality index.html contains the client-side part of our project The scripts folder contains the jQuery scripts that we use in index.html   Figure 9-3: The components of the AJAX grid The database Our editable grid displays a fictional database with products. On the server side, we store the data in a table named product, which contains the following fields: product_id: A unique number automatically generated by auto-increment in the database and used as the Primary Key name: The actual name of the product price: The price of the product for sale on_promotion: A numeric field that we use to store 0/1 (or true/false) values. In the user interface, the value is expressed via a checkbox The Primary Key is defined as the product_id, as this will be unique for each product it is a logical choice. This field cannot be empty and is set to auto-increment as entries are added to the database: CREATE TABLE product( product_id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL DEFAULT '', price DECIMAL(10,2) NOT NULL DEFAULT '0.00', on_promotion TINYINT NOT NULL DEFAULT '0', PRIMARY KEY (product_id)); The other fields are rather self-explanatory—none of the fields may be left empty and each field, with the exception of product_id, has been assigned a default value. The tinyint field will be shown as a checkbox in our grid that the user can simply set on or off. The on-promotion field is set to tinyint, as it will only need to hold a true (1) or false (0) value. Styles and colors Leaving the database aside, it's useful to look at the more pertinent and immediate aspects of the application code so as to get a general overview of what's going on here. We mentioned earlier that control of the look of the grid is accomplished through CSS. Looking at the index.html file's head region, we find the following code: <link rel="stylesheet" type="text/css" href="scripts/themes/coffee/grid.css" title="coffee" media="screen" /><link rel="stylesheet" type="text/css" media="screen" href="themes/jqModal.css" /> Several themes have been included in the themes folder; coffee is the theme being used in the code above. To change the look of the grid, you need only modify the theme name to another theme, green, for example, to modify the color theme for the entire grid. Creating a custom theme is possible by creating your own images for the grid (following the naming convention of images), collecting them in a folder under the themes folder, and changing this line to reflect your new theme name. There is one exception here though, and it affects which buttons will be used. The buttons' appearance is controlled by imgpath: 'scripts/themes/green/images', found in index.html; you must alter this to reflect the path to the proper theme. Changing the theme name in two different places is error prone and we should do this carefully. By using jQuery and a nifty trick, we will be able to define the theme as a simple variable. We will be able to dynamically load the CSS file based on the current theme and imgpath will also be composed dynamically. The nifty trick involves dynamically creating the < link > tag inside head and setting the appropriate href attribute to the chosen theme. Changing the current theme simply consists of changing the theme JavaScript variable. JqModal.css controls the style of our pop-up or overlay window and is a part of the jqModal plugin. (Its functionality is controlled by the file jqModal.js found in the scripts/js folder.) You can find the plugin and its associated CSS file at: http://dev.iceburg.net/jquery/jqModal/   In addition, in the head region of index.html, there are several script src declarations for the files used to build the grid (and jqModal.js for the overlay): <script src="scripts/jquery-1.3.2.js" type="text/javascript"></script><script src="scripts/jquery.jqGrid.js" type="text/javascript"></script><script src="scripts/js/jqModal.js" type="text/javascript"></script><script src="scripts/js/jqDnR.js" type="text/javascript"></script> There are a number of files that are used to make our grid function and we will talk about these scripts in more detail later. Looking at the body of our index page, we find the declaration of the table that will house our grid and the code for getting the grid on the page and populated with our product data. <script type="text/javascript">var lastSelectedId;$('#list').jqGrid({ url:'grid.php', //name of our server side script. datatype: 'json', mtype: 'POST', //specifies whether using post or get//define columns grid should expect to use (table columns) colNames:['ID','Name', 'Price', 'Promotion'], //define data of each column and is data editable? colModel:[ {name:'product_id',index:'product_id', width:55,editable:false}, //text data that is editable gets defined {name:'name',index:'name', width:100,editable:true, edittype:'text',editoptions:{size:30,maxlength:50}},//editable currency {name:'price',index:'price', width:80, align:'right',formatter:'currency', editable:true},// T/F checkbox for on_promotion {name:'on_promotion',index:'on_promotion', width:80, formatter:'checkbox',editable:true, edittype:'checkbox'} ],//define how pages are displayed and paged rowNum:10, rowList:[5,10,20,30], imgpath: 'scripts/themes/green/images', pager: $('#pager'), sortname: 'product_id',//initially sorted on product_id viewrecords: true, sortorder: "desc", caption:"JSON Example", width:600, height:250, //what will we display based on if row is selected onSelectRow: function(id){ if(id && id!==lastSelectedId){ $('#list').restoreRow(lastSelectedId); $('#list').editRow(id,true,null,onSaveSuccess); lastSelectedId=id; } },//what to call for saving edits editurl:'grid.php?action=save'});//indicate if/when save was successfulfunction onSaveSuccess(xhr){ response = xhr.responseText; if(response == 1) return true; return false;}</script>
Read more
  • 0
  • 0
  • 8837

article-image-ajax-chat-implementation-part-1
Packt
28 Dec 2009
4 min read
Save for later

AJAX Chat Implementation: Part 1

Packt
28 Dec 2009
4 min read
Lets get started. We'll keep the application simple, modular, and extensible. We won't implement a login module, support for chat rooms, the online users list, and so on. By keeping it simple we'll focus on what the goal of this article is: posting and retrieving messages without causing any page reloads. We'll also let the user pick a color for her or his messages, because this involves an AJAX mechanism that is another good exercise. The chat application can be tested online at http://ajaxphp.packtpub.com, and should look like Figure 8-1: Figure 8-1: Online chat application built with AJAX and jQuery Using jQuery as a framework will simplify things: we won't need to worry about constructing XmlHttpRequest by ourselves and implementing design patterns and best practices. Technically, the application is split into two smaller applications that build the final solution: The chat application: Here we use a MySql database and AJAX to store and retrieve the users' messages and pass them between the client and the server. The code for choosing a text color: Here we use AJAX to call the PHP script that can tell us which text color was chosen by the user from the color palette. We use an image containing the entire spectrum of colors and allow the user choose any color for the text he or she writes. When the user clicks on the palette, the mouse coordinates are sent to the server, which obtain the color code, store it in the user's DB entry, and set the user's test to that color. The chat application Here we use a MySql database and AJAX to store and retrieve the users' messages and pass them between the client and the server. The chat window contacts the server periodically to send and retrieve the newest posted messages from the server to each user. Our DB will also hold username and text color information used in the application. Implementing this functionality involves creating the files and structures shown in the following figure: Figure 8-2: The components of the AJAX Chat application The application functions following our usual coding pattern as follows: The user interface is generated by index.html, which displays the chat box and the color picker. This file loads the other client-side files, which in our case are chat.js (our JavaScript chat class), jQuery-1.3.2.js (the jQuery framework), chat.css, and palette.png (the color picker image). On the server side, the main player is chat.php, which is designed to take requests from the client. In our case, client-server communication will happen between chat.js (on the client) and chat.php (on the server). The chat.php script uses three other files—config.php, error_handler.php and chat.class.php; we'll pay special attention to the latter, which is more complex and more interesting than the others. The other server-side file that listens to client requests is color.php, which is called whenever the user clicks the color palette image. When that happens, the client script calls color.php, tells it the location the user clicked on the palette, and color.php replies by telling the color at that location. You'll also need to create a new data table named chat (refer to the following figure), which holds the chat messages exchanged by the chatters. The files to which we're paying a little attention before starting to code are chat.js and chat.class.php. The chat.class.php file contains a server-side class named Chat which includes all the server-side functionality required to manipulate chat messages, as you can see in its diagram in Figure 8-3. This class contains methods for adding, deleting, and retrieving chat messages to and from the chat database table. Figure 8-3: Server-side Chat class Then we have the Chat class in the chat.js file. This is a JavaScript class that contains the client-side functionality required for our chatting application, which include functions for retrieving the list of messages from the server, sending new messages, deleting messages, displaying error messages, and so on. Most of the features are backed up by the server-side components, which are called to perform the necessary work. Figure 8-4: Client-side Chat class
Read more
  • 0
  • 0
  • 2470
article-image-ajax-chat-implementation-part-2
Packt
28 Dec 2009
9 min read
Save for later

AJAX Chat Implementation: Part 2

Packt
28 Dec 2009
9 min read
Create a new file named index.html, and add this code to it: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xml_lang="en" lang="en"> <head> <title>AJAX Chat</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link href="chat.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="jQuery-1.3.2.js" ></script> <script type="text/javascript" src="chat.js" ></script> </head> <body> <noscript> Your browser does not support JavaScript!! </noscript> <table id="content"> <tr> <td> <div id="scroll"> </div> </td> <td id="colorpicker"> <img src="palette.png" id="palette" alt="Color Palette" border="1"/> <br /> <input id="color" type="hidden" readonly="true" value="#000000" /> <span id="sampleText"> (text will look like this) </span> </td> </tr> </table> <div> <input type="text" id="userName" maxlength="10" size="10"/> <input type="text" id="messageBox" maxlength="2000" size="50" /> <input type="button" value="Send" id="send" /> <input type="button" value="Delete All" id="delete" /> </div> </body> </html> Let's deal with appearances now, creating chat.css and adding the following code to it: body { font-family: Tahoma, Helvetica, sans-serif; margin: 1px; font-size: 12px; text-align: left } #content { border: DarkGreen 1px solid; margin-bottom: 10px } input { border: #999 1px solid; font-size: 10px } #scroll { position: relative; width: 340px; height: 270px; overflow: auto } .item { margin-bottom: 6px } #colorpicker { text-align:center } It's time for another test. We still don't have the color picker in place, but other than that, we have the whole client-server chat mechanism in place. Load index.html at http://localhost/ajax/chat/index.html from multiple browsers and/or computers, and ensure everything works as planned. Figure 8-7: Screenshot of index.html Copy palette.png from the code download to your ajax/chat folder. Create a file named color.php and add the following code to it. This is actually the only step left to make the color picker work as expected. <?php // the name of the image file $imgfile='palette.png'; // load the image file $img=imagecreatefrompng($imgfile); // obtain the coordinates of the point clicked by the user $offsetx=$_GET['offsetx']; $offsety=$_GET['offsety']; // get the clicked color $rgb = ImageColorAt($img, $offsetx, $offsety); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; // return the color code echo json_encode(array("color" => sprintf('#%02s%02s%02s', dechex($r), dechex($g), dechex($b)))); ?> Make another test to ensure the color picker works and that your users can finally chat in color. What just happened? First, make sure the application works well. Load http://localhost/ajax/chat/index.html with a web browser, and you should get a page that looks like the one in Figure 8-1. If you analyze the code for a bit, the details will become clear. Everything starts with index.html. The only part that is really interesting in index.html is a scrolling region implemented in DHTML. (A little piece of information regarding scrolling can be found at http://www.dyn-web.com/code/scroll/.) The scrolling area allows our users to scroll up and down the history of the chat and ensures that any new messages that might flow out of the area are still viewed. In our example, the scroll element and its inner layers do the trick. The scroll element is the outermost layer; it has a fixed width and height; and its most useful property, overflow, determines how any content that falls (or overflows) outside of its boundaries is displayed. Generally, the content of a block box is confined to the content edges of the box. In CSS, the overflow property has four possible values that specify what should happen when an element overflows its area: visible, hidden, scroll, and auto. (For more details, please see the specification of overflow, at http://www.w3.org/TR/REC-CSS2/visufx.html.)   As you can see, the HTML file is very clean. It contains only the declarations of the HTML elements that make up the user interface. There are no event handlers and there is no JavaScript code inside the HTML file—we have a clean separation between the user interface and the programming. In our client-side JavaScript code, in the chat.js file, the action starts with the ready event, which is defined in jQuery (reference: http://docs.jQuery.com/Events/ready) as a replacement for window.onload. In other words, your ready() function, which you can see in the following code snippet, is called automatically after the HTML page has been loaded by the browser, and the page elements can be safely used and manipulated by your JavaScript code: $(document).ready(function() { } Inside this function, we do several operations involving events related to the user interface. Let's analyze each step! We want to be sure that a username always appears, that is, it should never be left empty. To do this, we can create a function that checks for this and bind it to the blur event of the textbox. // function that ensures that the username is never empty and //if so a random name is generated $('#userName').blur( function(e) { // ensures our user has a default random name when the form loads if (this.value == "") this.value = "Guest" + Math.floor(Math.random() * 1000); } ); If the username is empty, we simply generate a random username suffixing Guest with a randomly generated number. When the page first loads, no username has been set and we trigger the blur event on userName. // populate the username field with // the default value $('#userName').triggerHandler('blur'); The success() function starts by checking if the JSON response contains an errno field, which would mean that an error has happened on the server side. If an error occurred the displayPHPError() function is called passing in the error in JSON format. // function that displays a PHP error message function displayPHPError(error) { displayError ("Error number :" + error.errno + "rn" + "Text :"+ error.text + "rn" + "Location :" + error.location + "rn" + "Line :" + error.line + + "rn"); } The displayPHPError() will retrieve the information from the error and call in turn the displayError() function. The displayError() function shows the error message or a generic alert depending on whether the debugging flag is set or not. // function that displays an error message function displayError(message) { // display error message, with more technical details if debugMode is true alert("Error accessing the server! " + (debugMode ? message : "")); } Next, in our ready event, we set the default color for the sample text to black: // set the default color to black $('#sampleText').css('color', 'black'); Moving on, we hook on to the click event of the Send button. The following code is very simple, as the entire logic behind sending a message is encapsulated in sendMessage(): $('#send').click( function(e) { sendMessage(); } ); Moreover, here we hook on to the click event of the Delete all button in a similar way as the Send button. $('#delete').click( function(e) { deleteMessages(); } ); For the messageBox textbox, where we input messages, we disable autocomplete and we capture the Enter key and invoke the logic for sending a message: // set autocomplete off $('#messageBox').attr('autocomplete', 'off'); // handle the enter key event $('#messageBox').keydown( function(e) { if (e.keyCode == 13) { sendMessage(); } } ); Finally, when the page loads, we want to have the messages that have already been posted and we call retrieveNewMessages() function. Now that we have seen what happens when the page loads, it's time to analyze the logic behind sending and receiving new messages. Because everything starts when the page loads and the existing messages are retrieved, we will start with retrieveNewMessages() function. The function simply makes an AJAX request to the server indicating the retrieval of the latest messages. function retrieveNewMessages() { $.ajax({ url: chatURL, type: 'POST', data: $.param({ mode: 'RetrieveNew', id: lastMessageID }), dataType: 'json', error: function(xhr, textStatus, errorThrown) { displayError(textStatus); }, success: function(data, textStatus) { if(data.errno != null) displayPHPError(data); else readMessages(data); // restart sequence setTimeout("retrieveNewMessages();", updateInterval); } }); } The request contains as parameters the mode indicating the retrieval of new messages and the ID of the last retrieved message: data: $.param({ mode: 'RetrieveNew', id: lastMessageID }), On success, we simply read the retrieved messages and we schedule a new automatic retrieval after a specific period of time: success: function(data, textStatus) { if(data.errno != null) displayPHPError(data); else readMessages(data); // restart sequence setTimeout("retrieveNewMessages();", updateInterval); } Reading messages is the most complicated function as it involves several steps. It starts by checking whether the database has been cleared of messages and, if so, it empties the list of messages and resets the ID of the last retrieved message. function readMessages(data, textStatus) { // retrieve the flag that says if the chat window has been cleared or not clearChat = data.clear; // if the flag is set to true, we need to clear the chat window if (clearChat == 'true') { // clear chat window and reset the id $('#scroll')[0].innerHTML = ""; lastMessageID = -1; } Before retrieving the new messages, we need to check and see if the received messages have not been already processed. If not, we simply store the ID of the last received message in order to know what messages to ask for during the next requests: if (data.messages.length > 0) { // check to see if the first message // has been already received and if so // ignore the rest of the messages if(lastMessageID > data.messages[0].id) return; // the ID of the last received message is stored locally lastMessageID = data.messages[data.messages.length - 1].id; }
Read more
  • 0
  • 0
  • 2577

article-image-data-tables-and-datatables-plugin-jquery-13-php
Packt
19 Nov 2009
10 min read
Save for later

Data Tables and DataTables Plugin in jQuery 1.3 with PHP

Packt
19 Nov 2009
10 min read
In this article by Kae Verens, we will look at: How to install and use the DataTables plugin How to load data pages on request from the server Searching and ordering the data From time to time, you will want to show data in your website and allow the data to be sorted and searched. It always impresses me that whenever I need to do anything with jQuery, there are usually plugins available, which are exactly or close to what I need. The DataTables plugin allows sorting, filtering, and pagination on your data. Here's an example screen from the project we will build in this article. The data is from a database of cities of the world, filtered to find out if there is any place called nowhere in the world: Get your copy of DataTables from http://www.datatables.net/, and extract it into the directory datatables, which is in the same directory as the jquery.min.js file. What the DataTables plugin does is take a large table, paginate it, and allow the columns to be ordered, and the cells to be filtered. Setting up DataTables Setting up DataTables involves setting up a table so that it has distinct < thead > and < tbody > sections, and then simply running dataTable() on it. As a reminder, tables in HTML have a header and a body. The HTML elements < thead > and < tbody > are optional according to the specifications, but the DataTables plugin requires that you put them in, so that it knows what to work with. These elements may not be familiar to you, as they are usually not necessary when you are writing your web pages and most people leave them out, but DataTables needs to know what area of the table to turn into a navigation bar, and which area will contain the data, so you need to include them. Client-side code The first example in this article is purely a client-side one. We will provide the data in the same page that is demonstrating the table. Copy the following code into a file in a new demo directory and name it tables.html: <html> <head> <script src="../jquery.min.js"></script> <script src="../datatables/media/js/jquery.dataTables.js"> </script> <style type="text/css"> @import "../datatables/media/css/demo_table.css";</style> <script> $(document).ready(function(){ $('#the_table').dataTable(); }); </script> </head> <body> <div style="width:500px"> <table id="the_table"> <thead> <tr> <th>Artist / Band</th><th>Album</th><th>Song</th> </tr> </thead> <tbody> <tr><td>Muse</td> <td>Absolution</td> <td>Sing for Absolution</td> </tr> <tr><td>Primus</td> <td>Sailing The Seas Of Cheese</td> <td>Tommy the Cat</td> </tr> <tr><td>Nine Inch Nails</td> <td>Pretty Hate Machine</td> <td>Something I Can Never Have</td> </tr> <tr><td>Horslips</td> <td>The Táin</td> <td>Dearg Doom</td> </tr> <tr><td>Muse</td> <td>Absolution</td> <td>Hysteria</td> </tr> <tr><td>Alice In Chains</td> <td>Dirt</td> <td>Rain When I Die</td> </tr> <!-- PLACE MORE SONGS HERE --> </tbody> </table> </div> </body> </html> When this is viewed in the browser, we immediately have a working data table: Note that the rows are in alphabetical order according to Artist/Band. DataTables automatically sorts your data initially based on the first column. The HTML provided has a < div > wrapper around the table, set to a fixed width. The reason for this is that the Search box at the top and the pagination buttons at the bottom are floated to the right, outside the HTML table. The < div > wrapper is provided to try to keep them at the same width as the table. There are 14 entries in the HTML, but only 10 of them are shown here. Clicking the arrow on the right side at the bottom-right pagination area loads up the next page: And finally, we also have the ability to sort by column and search all data: In this screenshot, we have the data filtered by the word horslips, and have ordered Song in descending order by clicking the header twice. With just this example, you can probably manage quite a few of your lower-bandwidth information tables. By this, I mean that you could run the DataTables plugin on complete tables of a few hundred rows. Beyond that, the bandwidth and memory usage would start affecting your reader's experience. In that case, it's time to go on to the next section and learn how to serve the data on demand using jQuery and Ajax. As an example of usage, a user list might reasonably be printed entirely to the page and then converted using the DataTable plugin because, for smaller sites, the user list might only be a few tens of rows and thus, serving it over Ajax may be overkill. It is more likely, though, that the kind of information that you would really want this applied to is part of a much larger data set, which is where the rest of the article comes in! Getting data from the server The rest of the article will build up a sample application, which is a search application for cities of the world. This example will need a database, and a large data set. I chose a list of city names and their spelling variants as my data set. You can get a list of this type online by searching. The exact point at which you decide a data set is large enough to require it to be converted to serve over Ajax, instead of being printed fully to the HTML source, depends on a few factors, which are mostly subjective. A quick test is: if you only ever need to read a few pages of the data, yet there are many pages in the source and the HTML is slow to load, then it's time to convert. The database I'm using in the example is MySQL (http://www.mysql.com/). It is trivial to convert the example to use any other database, such as PostgreSQL or SQLite. For your use, here is a short list of large data sets: http://wordlist.sourceforge.net/—Links to collections of words. http://www.gutenberg.org/wiki/Gutenberg:Offline_Catalogs—A list of books placed online by Project Gutenburg. http://www.world-gazetteer.com/wg.php?men=stdl—A list of all the cities in the world, including populations. The reason I chose a city name list is that I wanted to provide a realistic large example of when you would use this. In your own applications, you might also use the DataTables plugin to manage large lists of products, objects such as pages or images, and anything else that can be listed in tabular form and might be very large. The city list I found has over two million variants in it, so it is an extreme example of how to set up a searchable table. It's also a perfect example of why the Ajax capabilities of the DataTables project are important. Just to see the result, I exported all the entries into an HTML table, and the file size was 179 MB. Obviously, too large for a web page. So, let's find out how to break the information into chunks and load it only as needed. Client-side code On the client side, we do not need to provide placeholder data. Simply print out the table, leaving the < tbody > section blank, and let DataTables retrieve the data from the server. We're starting a new project here, so create a new directory in your demos section and save the following into it as tables.html: <html> <head> <script src="../jquery.min.js"></script> <script src="../datatables/media/js/jquery.dataTables.js"> </script> <style type="text/css"> @import "../datatables/media/css/demo_table.css"; table{width:100%} </style> <script> $(document).ready(function(){ $('#the_table').dataTable({ 'sAjaxSource':'get_data.php' }); }); </script> </head> <body> <div style="width:500px"> <table id="the_table"> <thead> <tr> <th>Country</th> <th>City</th> <th>Latitude</th> <th>Longitude</th> </tr> </thead> <tbody> </tbody> </table> </div> </body> </html> In this example, we've added a parameter to the .dataTable call, sAjaxSource, which is the URL of the script that will provide the data (the file will be named get_data.php). Server-side code On the server side, we will start off by providing the first ten rows from the database. DataTables expects the data to be returned as a two-dimensional array named aaData. In my own database, I've created a table like this: CREATE TABLE `cities` ( `ccode` char(2) DEFAULT NULL, `city` varchar(87) DEFAULT NULL, `longitude` float DEFAULT NULL, `latitude` float DEFAULT NULL, KEY `city` (`city`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 Most of the searching will be done on city names, so I've indexed city. Initially, let's just extract the first page of information. Create a file called get_data.php and save it in the same directory as tables.html: <?php // { initialise variables $amt=10; $start=0; // } // { connect to database function dbRow($sql){ $q=mysql_query($sql); $r=mysql_fetch_array($q); return $r; } function dbAll($sql){ $q=mysql_query($sql); while($r=mysql_fetch_array($q))$rs[]=$r; return $rs; } mysql_connect('localhost','username','password'); mysql_select_db('phpandjquery'); // } // { count existing records $r=dbRow('select count(ccode) as c from cities'); $total_records=$r['c']; // } // { start displaying records echo '{"iTotalRecords":'.$total_records.', "iTotalDisplayRecords":'.$total_records.', "aaData":['; $rs=dbAll("select ccode,city,longitude,latitude from cities order by ccode,city limit $start,$amt"); $f=0; foreach($rs as $r){ if($f++) echo ','; echo '["',$r['ccode'],'", "',addslashes($r['city']),'", "',$r['longitude'],'", "',$r['latitude'],'"]'; } echo ']}'; // } In a nutshell, what happens is that the script counts how many cities are there in total, and then returns that count along with the first ten entries to the client browser using JSON as the transport.
Read more
  • 0
  • 0
  • 8909