Ajax Updates |
- The JavaScript InfoVis Toolkit
- Shoutbox using PHP and AJAX with jQuery
- TaskSpeed – Library Task Test Suite
- Building a Tag Cloud Using the Google Web Toolkit
The JavaScript InfoVis Toolkit Posted: 30 Sep 2009 11:51 AM PDT The JavaScript InfoVis Toolkit provides tools for creating Interactive Data Visualizations for the Web. Features * Multiple Data Representations Related Listings:
| |||||
Shoutbox using PHP and AJAX with jQuery Posted: 30 Sep 2009 11:24 AM PDT Dynamic ajax based shoutbox with jQuery from scratch. It will be very interesting to know how to use the ajax function of jQuery and how it can be used to insert and recover data from a MySQL database via PHP in a way asynchronous. First of all we will create the layout (as always, you know), it will be similar to the tabbed menu tutorial and it will have 2 main divisions: * Form (fields with the user and message to send) So now we have have seen the main divisions, take a look at the xHTML code: < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>yensdesign.com - Create a shoutbox using PHP and AJAX with jQuery</title> <link rel="stylesheet" href="css/general.css" type="text/css" media="screen" /> </head> <body> <a id="logo" title="Go to yensdesign.com!" href="http://www.yensdesign.com"><img src="css/images/logo.jpg" alt="yensdesign.com" /></a> <form method="post" id="form"> <table> <tr> <td><label>User</label></td> <td><input class="text user" id="nick" type="text" MAXLENGTH="25" /></td> </tr> <tr> <td><label>Message</label></td> <td><input class="text" id="message" type="text" MAXLENGTH="255" /></td> </tr> <tr> <td></td> <td><input id="send" type="submit" value="Shout it!" /></td> </tr> </table> </form> <div id="container"> <ul class="menu"> <li>Shoutbox</li> </ul> <span class="clear"></span> <div class="content"> <h1>Latest Messages</h1> <div id="loading"><img src="css/images/loading.gif" alt="Loading..." /></div> <ul> </ul><ul> </ul></div> </div> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="shoutbox.js"></script> </body> </html> We are limiting the maxlength of both fields: nick(25) & message(255) because our shoutbox table will have these length limitations. Nothing more to explain over here, let's go to the CSS part. There is nothing special in this case for the css part, just remember you that we are reusing the CSS trick for the tab that we have used in the tabbed menu tutorial. Here you have the entire CSS code: @CHARSET "UTF-8"; /******* GENERAL RESET *******/ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { border:0pt none; font-family:inherit; font-size: 100%; font-style:inherit; font-weight:inherit; margin:0pt; padding:0pt; vertical-align:baseline; } body{ background: #fff; line-height:14px; font-size: 12px; font-family: Arial, Verdana, Helvetica, sans-serif; margin:0pt; cursor:default; overflow: hidden; } html,body{ height:100%; text-align: center; } .clear{ clear: both; height: 0; visibility: hidden; display: block; } a{ text-decoration: none; } strong{ font-weight: 700; } /******* GENERAL RESET *******/ /******* LOGO *******/ #logo{ margin-top: 1em; display: block; } /******* /LOGO *******/ /******* FORM *******/ #form{ margin: 5em auto 3em; width: 300px; } #form table td{ text-align: left; font-size: 11px; } #form label{ font-weight: 700; } #form input{ border: 1px solid #d0ccc9; background: #fff; color: #5f95ef; font-size: 11px; font-weight: 700; } #form input.text{ font-weight: normal; color: #565656; border: 1px solid #9c9c9c; width: 250px; padding: 2px; margin-bottom: 5px; text-align: left; } #form input.text.user{ width: 100px; } /******* /FORM *******/ /******* MENU *******/ #container{ margin: 1em auto; width: 400px; } #container ul{ list-style: none; list-style-position: outside; } #container ul.menu li{ float: left; margin-right: 5px; margin-bottom: -1px; } #container ul.menu li{ font-weight: 700; display: block; padding: 5px 10px 5px 10px; background: #fff; border: 1px solid #d0ccc9; border-width: 1px 1px 0 1px; position: relative; color: #5f95ef; cursor: pointer; } /******* /MENU *******/ /******* CONTENT *******/ .content{ margin: 0pt auto; background: #efefef; background: #fff; border: 1px solid #d0ccc9; text-align: left; padding: 10px; padding-bottom: 20px; font-size: 11px; } .content h1{ line-height: 1em; vertical-align: middle; height: 48px; padding: 10px 10px 10px 52px; font-size: 32px; background: transparent url(images/bubble.jpg) no-repeat scroll left top; } .date{ font-weight: normal; font-size: 9px; color: #aeaeae; } /******* /CONTENT *******/ /******* LOADING *******/ #loading{ text-align: center; } /******* /LOADING *******/ As you may noticed, we have an empty ul element with no li elements, that's because we will load his content via AJAX Let's create the MySQL table. As I told you, we will make use of a MySQL database to store our messages and then we will retrieve data via PHP. So we only need to create a simple table called shoutbox with these columns: * id (int primary key and with auto increment) So here you have the MySQL code that you must execute in your database (via phpmyadmin for example): CREATE TABLE `shoutbox`( `id` int(5) NOT NULL auto_increment, `date` timestamp NOT NULL default CURRENT_TIMESTAMP, `user` varchar(25) NOT NULL default 'anonimous', `message` varchar(255) NOT NULL default '', PRIMARY KEY (`id`) ); So now that we have our layout ready and the MySQL table created let's continue with the PHP part. Last two steps (step 4 & step 5) are very important so guys pay attention! With jQuery.ajax() function from jQuery we can load a remote page using an HTTP request. We will make use of the jQuery.ajax() function to make a POST request to a PHP script named shoutbox.php that will manage the insert / retrieve data action with a switch sentence. We will receive a XMLHttpRequest object from $.ajax() function that will have a property called responseText. This property will give us the required information to display the shoutbox's messages (in case of select action) or the confirmation (in case of insert action). So before add the AJAX code we need to create our shoutbox.php that will manage all the requests from our future javascript file shoutbox.js. We will define some constants to the MySQL connection: /************************ CONSTANTS /************************/ define("HOST", "YOUR HOST"); define("USER", "YOUR USER"); define("PASSWORD", "YOUR USER PASSWORD"); define("DB", "YOUR DATABASE"); As you may noticed the second parameter of each define() function it's wrong / empty, you must change them for values that apply in your case. Now we have defined our constants to the connection with MySQL we will create 3 functions: * connect(): It will open a connection to a specific host selecting a specific database too. So here you have the three functions: /************************ FUNCTIONS /************************/ function connect($db, $user, $password){ $link = @mysql_connect($db, $user, $password); if (!$link) die("Could not connect: ".mysql_error()); else{ $db = mysql_select_db(DB); if(!$db) die("Could not select database: ".mysql_error()); else return $link; } } function getContent($link, $num){ $res = @mysql_query("SELECT date, user, message FROM shoutbox ORDER BY date DESC LIMIT ".$num, $link); if(!$res) die("Error: ".mysql_error()); else return $res; } function insertMessage($user, $message){ $query = sprintf("INSERT INTO shoutbox(user, message) VALUES('%s', '%s');", mysql_real_escape_string(strip_tags($user)), mysql_real_escape_string(strip_tags($message))); $res = @mysql_query($query); if(!$res) die("Error: ".mysql_error()); else return $res; } It's almost finished guys. As we said, we will manage via switch sentence the POST requests from AJAX (from the future shoutbox.js file) so we will make use of the three previous functions to retrieve and insert data: /****************************** MANAGE REQUESTS /******************************/ if(!$_POST['action']){ //We are redirecting people to our shoutbox page if they try to enter in our shoutbox.php header ("Location: index.html"); } else{ $link = connect(HOST, USER, PASSWORD); switch($_POST['action']){ case "update": $res = getContent($link, 20); while($row = mysql_fetch_array($res)){ $result .= " <li><strong>".$row['user']."</strong><img src="\" alt="\"-\"" />".$row['message']." <span class="\"date\"">".$row['date']."</span></li> "; } echo $result; break; case "insert": echo insertMessage($_POST['nick'], $_POST['message']); break; } mysql_close($link); } And that's all in the PHP part guys. Just comment that we are avoiding the direct access to shoutbox.php by checking the post variable action that we send in each request to shoutbox.php from javascript code (from shoutbox.js remember). Let's go to the final step… the AJAX part! So now we have done the layout with the CSS, the shoutbox table in a MySQL database and the PHP script to insert / retrieve data. We only need to know how to make POST requests from our shoutbox.js javascript file to our soutbox.php PHP script file. All the following code will be in a javascript file named shoutbox.js and in the $(document).ready of jQuery. First of all we will define some variables to save some references to jQuery selectors: [code lang="phpl"] //global vars //check if all fields are filled function checkForm(){ if(inputUser.attr("value") &amp;&amp; inputMessage.attr("value")) return true; else return false; } As we said in the Step 1, we will load the messages of our shoutbox table via AJAX from the first instance, so let's create a function to retrieve this data: function updateShoutbox(){ //just for the fade effect messageList.hide(); loading.fadeIn(); //send the post to shoutbox.php $.ajax({ type: "POST", url: "shoutbox.php", data: "action=update", complete: function(data){ loading.fadeOut(); messageList.html(data.responseText); messageList.fadeIn(2000); } }); } What's happening here? We are showing the loading animated gif while we are retrieving data from shoutbox table via POST request to our shoutbox.php. With the data parameter of $.ajax() function we can send post variables (action = update), in this case we are sending $_POST['action'] = "update", so shoutbox.php can manage the specific action in the switch sentence that we have made before. Finally when the request is completed, we hide the loading animated gif, load the new data in our xHTML layout and show it. So adding a call to this function, updateShoutbox() in the ready event of jQuery we can load the data in a first instance: //Load for the first time the shoutbox data updateShoutbox(); Finally we need to manage the submit event to insert user's messages in our shoutbox table and then refresh the content in the shoutbox (with the updateShoutbox() function, you know): //on submit event $("#form").submit(function(){ if(checkForm()){ var nick = inputUser.attr("value"); var message = inputMessage.attr("value"); //we deactivate submit button while sending $("#send").attr({ disabled:true, value:"Sending..." }); $("#send").blur(); //send the post to shoutbox.php $.ajax({ type: "POST", url: "shoutbox.php", data: "action=insert&nick=" + nick + "&message=" + message, complete: function(data){ messageList.html(data.responseText); updateShoutbox(); //reactivate the send button $("#send").attr({ disabled:false, value:"Shout it!" }); } }); } else alert("Please fill all fields!"); //we prevent the refresh of the page after submitting the form return false; }); Related Listings:
| |||||
TaskSpeed – Library Task Test Suite Posted: 30 Sep 2009 11:04 AM PDT This is not SlickSpeed, though uses the same framework. Tests are run against a local copy of this document. They add, remove, append, connect and otherwise mangle the DOM as defined by the sample-tests.js file. These results are [optionally] reported back. There are Charts being generated from this data 1. Context Members of the CSS+FP Working Group proposed during the Clamart meeting to modularize the CSS specification. This modularization, and the externalization of the general syntax of CSS will reduce the size of the specification and allow new specifications to use selectors and/or CSS general syntax. For instance, behaviors or tree transformations. This specification contains its own test cases, one test per concept introduced in this document. These tests are not full conformance tests but are intended to provide users with a way to check if a part of this specification is implemented ad minima or is not implemented at all. The main differences between the selectors in CSS2 and those in Selectors are: * the list of basic definitions (selector, group of selectors, simple selector, etc.) has been clarified 2. Selectors A Selector represents a structure. This structure can be used as a condition (e.g. in a CSS rule) that determines which elements a selector matches in the document tree, or as a flat description of the HTML or XML fragment corresponding to that structure. Selectors may range from simple element names to rich contextual representations. The following table summarizes Selector syntax: The meaning of each selector is derived from the table above by prepending “matches” to the contents of each cell of the “Meaning” column. The case-sensitivity of document language element names in selectors depends on the document language. For example, in HTML, element names are case-insensitive, but in XML they are case-sensitive. The case-sensitivity of attribute names and attribute values in attribute selectors also depends on the document language. A selector is a chain of one or more sequences of simple selectors separated by combinators. A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence. A simple selector is either a type selector, universal selector, attribute selector, ID selector, content selector, or pseudo-class. One pseudo-element may be appended to the last sequence of simple selectors. Combinators are: white space, “greater-than sign” (>), “plus sign” (+) and “tilde” (~). White space may appear between a combinator and the simple selectors around it. Only the characters “space” (Unicode code 32), “tab” (9), “line feed” (10), “carriage return” (13), and “form feed” (12) can occur in white space. Other space-like characters, such as “em-space” (8195) and “ideographic space” (12288), are never part of white space. The elements of the document tree represented by a selector are called subjects of the selector. A selector consisting of a single sequence of simple selectors represents any element satisfying its requirements. Prepending another sequence of simple selectors and a combinator to a sequence imposes additional matching constraints, so the subjects of a selector are always a subset of the elements represented by the rightmost sequence of simple selectors. Note: an empty selector, containing no sequence of simple selectors and no combinator, is an invalid selector. When several selectors share the same declarations, they may be grouped into a comma-separated list. h1 { font-family: sans-serif } h2 { font-family: sans-serif } h3 { font-family: sans-serif } is equivalent to: h1, h2, h3 { font-family: sans-serif } Related Listings:
| |||||
Building a Tag Cloud Using the Google Web Toolkit Posted: 30 Sep 2009 10:20 AM PDT A while back, I read a tutorial by Dan Wellman, which described the steps required to produce a neat Tag-Cloud. Dan’s example largely relied on the jQuery framework to request data and construct the user interface elements. I decided to write his tutorial all over again with the two exceptions of using GWT instead of jQuery, and a different method of choosing font size variations. In case you don’t know what Tag-Clouds are and what purpose they serve, briefly, a Tag-Cloud is a form of visualizing the difference in importance or activeness of some predefined categories based on how large they appear in the cloud. We are going to use the latest version of GWT (currently 1.5) and work with MySQL and PHP as our back-end to request the JSON data. Similar to Dan’s tutorial, I too, assume that you already are familiar with inserting into a database. The PHP code in this article will merely cover how to query data from the database and send back the result in JSON format. You should expect to learn: * how GWT can request data from a PHP back-end and handle the response using callbacks I used the Cypal Studio GWT plug-in for Eclipse to create this project. If you are already using this combination, you should be able to download and open this project in Eclipse. Otherwise here is a link to obtain more information. Although GWT debugger doesn’t exactly debug JavaScript, using Eclipse with Cypal Studio plug-in allows for debugging GWT code inside the Eclipse IDE, which is better than many other JavaScript debuggers out there. By default, as part of the script that generates a blank GWT project, you will get an HTML file which, more or less, looks like the code below. You may need to correct the path of the JavaScript file according to your server setup. <html> <head> <title>Main</title> </head> <body> <script language="javascript" src="in.cypal.studio.gwt.samples.TagCloud.nocache.js"></script> <!-- This div is added to allow center align the page even in IE --> <div id="wrapper" style="text-align:center"></div> </body> </html> Our tag cloud is going to appear in the center of the browser. Since center-aligning pages using CSS doesn’t work properly in IE, we add a new DIV element and set its id to “wrapper”. This is all we need to get started. As we move further in this tutorial, we will re-visit this document to add more, but for now let’s move on. We will start by modifying the onModuleLoad() method of the MainEntryPoint class, as it’s the method that GWT uses to begin executing our code. We want to start by requesting data (tag names and their frequencies) from the PHP and MySQL back-end. public void getTagData(){ // you may need to change the URL according to your server setup String url = "/wmGetTags.php"; RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET,url); try{ requestBuilder.sendRequest(null, new RequestCallback() { public void onResponseReceived(Request request, Response response){ if (response.getStatusCode() == 200){ // handler code } } public void onError(Request request, Throwable exception){ throw new UnsupportedOperationException("Not supported yet."); } }); } catch (Exception e){ e.printStackTrace(); } } public void onModuleLoad() { } We have defined a new method called getTagData() in which the RequestBuilder type is instantiated to call the wmGetTags PHP script in the back-end. Note how the sendRequest() method takes in a callback parameter that handles the response once it arrives back. When creating a new RequestCallback, we must implement the onResponseReceived() and onError() methods to handle each case. Notice how in the onResponseReceived() method, we check the response status code. This is because during the life cycle of a request, this method could be invoked multiple times by the browser even though it may not be completely fulfilled. A request is complete only when the status code is equal to 200. We check the status code using the getStatusCode() method. Next we will create a FlowPanel widget and insert it inside the “wrapper” DIV. The GWT widget library provides many different kinds of panels for different use; however, a FlowPanel is the kind of widget that allows for holding more than one child widget in itself. This property makes it a suitable widget for a Tag-Cloud. What we are doing here is creating a holding container for all the tags that we must show. public void onModuleLoad() { getTagData(); flowPanel = new FlowPanel(); RootPanel.get("wrapper").add(flowPanel); } Constructing a Response Using PHP This part is fairly simple. Let’s create a new PHP script and call it wmGetTags.php. First, we must create a connection to the database using the mysql_connect() function, then perform a SELECT query on the table that holds both tag names and their occurrences. Finally when the query is done, we use a “For Loop” to generate a JSON formatted response. < ?php //connection information $host = "localhost"; $user = "root"; $password = "your_password_here"; $database = "tagcloud"; //make connection $server = mysql_connect($host, $user, $password); $connection = mysql_select_db($database, $server); //query the database $query = mysql_query("SELECT * FROM tags"); //start json object $json = "(["; //loop through and return results for ($x = 0; $x < mysql_num_rows($query); $x++) { $row = mysql_fetch_assoc($query); //continue json object $json .= "{tag:'" . $row["tag"] . "',frequency:" . $row["frequency"] . "}"; //add comma if not last row, closing brackets if is if ($x < mysql_num_rows($query) -1) $json .= ","; else $json .= "])"; } //return JSON with GET for JSONP callback $response = $_GET["callback"] . $json; echo $response; //close connection mysql_close($server); ?> When executed, the script above will generate a response similar to that shown below: ([{tag:'Gmail',frequency:21},{tag:'Web',frequency:19},{tag:'Salesforce',frequency:66},{tag:'Amazon',frequency:17}]) Above is an example of a JSON response. To be precise, this will be parsed into an array with each of its four indexes holding an object with two fields. The first field “tag” holds the name of the tag, while the second field “frequency” holds the occurrences count. Running what we’ve coded so far will produce a blank page, however inspecting browser communications using the “Net” tab in Firebug should show us the output of the PHP script above like shown in the image below. At this point we must define the routine that will parse the response received from the back-end and construct the UI further to show the tags in the cloud. Since the HTTP and JSON types are contained within separate GWT modules, we must add the following
You can find more about GWT modules here. public void getTagData(){ // ... try{ requestBuilder.sendRequest(null, new RequestCallback() { public void onResponseReceived(Request request, Response response){ if (response.getStatusCode() == 200){ handleGetTags(response.getText()); } } public void onError(Request request, Throwable exception){ throw new UnsupportedOperationException("Not supported yet."); } }); } catch (Exception e){ e.printStackTrace(); } } We now must call the handleGetTags() when the status code of the Response instance is equal to 200 like shown in the above code. The handleGetTags() method will actually process the JSON data. public void handleGetTags(String jsonText){ JSONObject jsonObject; JSONString tagName; JSONNumber tagFreq; int frequency; String realTagName; JSONValue jsonValue = JSONParser.parse(jsonText); JSONArray jsonArray = jsonValue.isArray(); if (jsonArray != null){ for (int i = 0; i < jsonArray.size(); i++){ jsonObject = (JSONObject)jsonArray.get(i); tagName = jsonObject.get("tag" ).isString(); tagFreq = jsonObject.get("frequency").isNumber(); frequency = (int)tagFreq.doubleValue(); Hyperlink tagLink = new Hyperlink(tagName.stringValue(),tagName.stringValue()); flowPanel.add(tagLink); } } } We now must call the handleGetTags() when the status code of the Response instance is equal to 200 like shown in the above code. The handleGetTags() method will actually process the JSON data. public void handleGetTags(String jsonText){ JSONObject jsonObject; JSONString tagName; JSONNumber tagFreq; int frequency; String realTagName; JSONValue jsonValue = JSONParser.parse(jsonText); JSONArray jsonArray = jsonValue.isArray(); if (jsonArray != null){ for (int i = 0; i < jsonArray.size(); i++){ jsonObject = (JSONObject)jsonArray.get(i); tagName = jsonObject.get("tag" ).isString(); tagFreq = jsonObject.get("frequency").isNumber(); frequency = (int)tagFreq.doubleValue(); Hyperlink tagLink = new Hyperlink(tagName.stringValue(),tagName.stringValue()); flowPanel.add(tagLink); } } } All XMLHTTPRequest communication between the client and the back-end happens through plain text. So even though the back-end response is JSON formatted, it’s yet to be converted/parsed into real JavaScript objects that we can then interact with, as shown below. # JSONValue jsonValue = JSONParser.parse(jsonText); # JSONArray jsonArray = jsonValue.isArray(); The JSONParser class provides a static method called parse() that takes in a String parameter and returns a JSONValue object that we can then interact with. As we previously established, our PHP script will return an array structure holding a number of objects encapsulating data related to the tags. To get a handle to that array we must use the isArray() method. for (int i = 0; i < jsonArray.size(); i++){ jsonObject = (JSONObject)jsonArray.get(i); tagName = jsonObject.get("tag" ).isString(); tagFreq = jsonObject.get("frequency").isNumber(); frequency = (int)tagFreq.doubleValue(); realTagName = tagName.stringValue(); //... } The above code will access the embedded object within every index of the array to get to the actual tag data. So in every iteration of the loop, content of the current index is returned as a JSONObject. Every extracted JSONObject should have two fields: tag, and frequency. We use the get() method of JSONObject class to retrieve these fields. Hyperlink tagLink = new Hyperlink(tagName.stringValue(),null); flowPanel.add(tagLink); Related Listings:
|
You are subscribed to email updates from Ajax Updates To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Google Inc., 20 West Kinzie, Chicago IL USA 60610 |
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.