Date post: | 19-Jan-2015 |
Category: |
Education |
Upload: | giacomo-antonino-fazio |
View: | 3,699 times |
Download: | 2 times |
1
Web DevelopmentWeb Developmentwithwith
PHP, jQuery, AJAX, Comet, HTML5PHP, jQuery, AJAX, Comet, HTML5
Giacomo Fazio Giacomo Fazio 20112011
2
Web development, or Web programming, refers to the design of software applications for a Web
site
Web developmentWeb development
Giacomo Fazio - 2011Giacomo Fazio - 2011
3
■ Client / Server Architecture■ Server-side technologies■ Client-side technologies■ JavaScript■ jQuery■ AJAX■ Comet■ HTML5: WebSockets & Server-Sent Events■ CodeIgniter
OutlineOutline
Giacomo Fazio - 2011Giacomo Fazio - 2011
4
A web application uses the traditional Client / Server architecture:■ The Client gathers information from the user
and asks the server a service■ The Server receives a request for information
from the client and servs the requested information to it
Client / Server ArchitectureClient / Server Architecture
Giacomo Fazio - 2011Giacomo Fazio - 2011
5
■ At first, all the Web pages were static: the user asked for a page and the server returned it
■ Internet was used especially for research and in the universities, so static pages were enough
■ So there was a 2-tier architecture, where the client was composed by a web browser (which asks the server a page) and by the HTML document received from the server
■ Soon Internet spread in other fields, such as commerce
■ More dynamic pages were needed, to store data permanently and to make the user interact with the website
■ The 2-tier architecture was not sufficient anymore
Client / Server ArchitectureClient / Server Architecture
Giacomo Fazio - 2011Giacomo Fazio - 2011
6
Sometimes there is still a 2-tier architecture, but now we have often a 3-tier (or multi-tier) client/server system, which consists of three distinct pieces:■ Client tier (or user interface tier or presentation tier),
composed by a web browser (which asks the server a page) and by the HTML document received from the server.
■ Processing tier (or middle tier), that receives a request from the client tier, handles it, communicates with the data storage tier and answers the client tier. It's composed by a web server (ex. Apache, IIS).
■ Data storage tier, which stores data in a database and receives the requests from the processing tier, answering to it (ex. MySQL).
Client / Server ArchitectureClient / Server Architecture
Giacomo Fazio - 2011Giacomo Fazio - 2011
7
Client / Server ArchitectureClient / Server Architecture
Giacomo Fazio - 2011Giacomo Fazio - 2011
8
The 3 tiers could stay all in the same machine, but they are usually divided in different machines that could be very far from each other:■The client tier is on the user's pc or
smartphone.■The processing tier and the data
storage tier are in the same computer or in different computers.
Client / Server ArchitectureClient / Server Architecture
Giacomo Fazio - 2011Giacomo Fazio - 2011
9
One of the most powerful development models for the Web is the ”LAMP”:■ Linux■ Apache■ MySQL■ PHP and/or Perl and/or Python
LAMPPLAMPP
Giacomo Fazio - 2011Giacomo Fazio - 2011
Apache is the industry-leading web server that runs a majority of web servers
on the Internet.
MySQL is a very popular
database that runs on most
operating systems.
PHP / Perl is a general purpose
scripting environment
widely used for building dynamic
web sites.
Linux is the free and open-source operating system
that runs on most servers
If you want to install a LAMP stack on your machine, you can try XAMPP, an easy to install Apache distribution that contains PHP, Perl and MySQL and is available for the most used operating systems.
10
■ We said webpages are now dynamic■ Classic HTML is not enough, we have to
use other technologies■ The technologies used to make a
webpage dynamic can be classified in server-side and client-side technologies
■ Server-side technologies work on the processing tier
■ Client-side technologies work on the client-tier
Server / Client side technologiesServer / Client side technologies
Giacomo Fazio - 2011Giacomo Fazio - 2011
11
Server / Client side technologiesServer / Client side technologies
Giacomo Fazio - 2011Giacomo Fazio - 2011
Web technologies
Server-side scripting Client-side scripting
Compiled programs
Server-side scripts
Programs compiled on the client
Client-side scripts
Hybrid technologies
CGI
Java Servlets
ASP.NET
PHP
ASP
Cold Fusion
Java Server Pages
ASP.NET
Java Applets Javascript
VBScript
12
■ Executed on the server side■ It allows the creation of pages that are not actually on
the server when asked from the browser, they are created and composed dynamically from the server, eventually using the data storage tier
■ It offers more complex and advanced capabilities, as well as the data storage
■ The code remains hidden from the clients■ Browser- and client-independent■ It allows secure access to databases■ Interactivity is not as immediate as the client-side scripting,
since it's the server who executes the program.■ Many technologies: CGI, SSI, Servlets, JSP, PHP, ASP,
ASP .NET, Perl, Ruby on Rails, etc.■ From now on, we will deal with PHP, but many aspects
work the same way in other languages, and translating the code is usually quite easy.
Server-side technologiesServer-side technologies
Giacomo Fazio - 2011Giacomo Fazio - 2011
13
■ A typical example of use of server-side programming are the Web forms: data are inserted in a HTML page, they are then submitted to a server-side page which can use data for example saving them into a database
Server-side technologies: web formsServer-side technologies: web forms
Giacomo Fazio - 2011Giacomo Fazio - 2011
14
■ form.htmlform.html<html><html>
<body><body>
<form action="form_handler.php" method="get"><form action="form_handler.php" method="get">
User Name: <input name="user" type="text" />User Name: <input name="user" type="text" />
<input type="submit" /><input type="submit" />
</form></form>
</body></body>
</html></html>
■ form_handler.phpform_handler.php<html><html>
<body><body>
<?php <?php
$name = $_GET['user'];$name = $_GET['user'];
echo "Hello $name!";echo "Hello $name!";
?>?>
</body></body>
</html></html>
Server-side technologies: web formsServer-side technologies: web forms
Giacomo Fazio - 2011Giacomo Fazio - 2011
15
■Runs on the local browser■Creates visual effects such as
animations (ex. rollover on the buttons)■Changes the contents of a Web page
after a browser has rendered it■Controls the Web browser window itself■Provides immediate feedback to the
user■Turns static Web pages into
applications
Client-side technologiesClient-side technologies
Giacomo Fazio - 2011Giacomo Fazio - 2011
16
■ Reduces the load on a server: maintaining state, filling out forms, error checking, or performing numeric calculation, can be handled by the client's own computer.
■ Reduces network traffic■ A script can behave differently on different
browsers■ Code is viewable by user■ Sometimes requires additional knowledge of
DHTML and DOM (Document Object Model)■ Many technologies: JavaScript, VBScript,
Applets, etc.
Client-side technologiesClient-side technologies
Giacomo Fazio - 2011Giacomo Fazio - 2011
17
■ DHTML is a term that indicates a combination of HTML and client-side technologies that produces dynamic documents
■ DHTML uses HTML/XHTML, style sheets (CSS), and client-side scripting to create simple animations, images, and text that change as a mouse moves over them
■ DHTML allows more interactivity with visitors to a Web site
■ DHTML also allows Web pages to behave more like desktop applications
DHTML (Dynamic HTML)DHTML (Dynamic HTML)
Giacomo Fazio - 2011Giacomo Fazio - 2011
18
■ A W3C standard■ Describes how the document object can
be traversed and modified ■ Represented as tree structure■ Can add new elements to the page■ Can change attributes of existing
elements■ Client-side languages can work on it
The DOM (Document Object Model)The DOM (Document Object Model)
Giacomo Fazio - 2011Giacomo Fazio - 2011
19
The DOM (Document Object Model)The DOM (Document Object Model)
Giacomo Fazio - 2011Giacomo Fazio - 2011
20
■ Interpreted, object-oriented programming language■ Weakly typed, types are not declared.■ Introduced by Netscape with Netscape 2.0 in 1995■ Standardized as ECMAScript by ECMA (European
Computer Manufacturers Association)■ Not related to Java other than the name■ Tightly integrated with browser■ Can handle many types of events generated by the
normal interaction between user and browser■ Can modify the internal objects based on which the
browser renders the web page
Client-side technologies: JavaScriptClient-side technologies: JavaScript
Giacomo Fazio - 2011Giacomo Fazio - 2011
21
■ JavaScript example about events:
<html><html><head><head> <script language="JavaScript"><script language="JavaScript"> function pushbutton() {function pushbutton() { alert("Hello!");alert("Hello!"); }} </script></script></head></head><body><body> <form><form> <input type="button" name=“okay" value=“Click me" onclick="pushbutton()"><input type="button" name=“okay" value=“Click me" onclick="pushbutton()"> </form></form></body></body></html></html>
Client-side technologies: JavaScriptClient-side technologies: JavaScript
Giacomo Fazio - 2011Giacomo Fazio - 2011
22
■ Some events JavaScript can handle:
Client-side technologies: JavaScriptClient-side technologies: JavaScript
Giacomo Fazio - 2011Giacomo Fazio - 2011
Handler Triggered when Comments
onclick Mouse click on element Return false to cancel default action
onchange The control’s state changes
onfocus The control gets focus
onsubmit The form is submitted Specific to forms
onmouseover Mouse moves over el.
onmouseout Mouse moves off el.
onmousedown Mouse button pressed
onmouseup Mouse button released
onkeydown Key pressed down Used for form elements and <body>Return false to cancelonkeypress Key pressed and released
onkeyup Key released Used for form elements and <body>
onload Document load complete Used for <body> and <img>
23
■ JavaScript examples:
<input type="text" name="phone_number" id="phone_number"/><input type="text" name="phone_number" id="phone_number"/><script type="text/javascript"><script type="text/javascript"> var phone = document.getElementById('phone_number');var phone = document.getElementById('phone_number'); phone.value='095738';phone.value='095738'; phone.disabled=true;phone.disabled=true; document.images[0].src="http://.../some_other_image.jpg";document.images[0].src="http://.../some_other_image.jpg";</script></script>
var counter;var counter;for(counter=1; counter<=10; counter++) {for(counter=1; counter<=10; counter++) { document.writeln("<p>cnt:"+counter+"</p>")document.writeln("<p>cnt:"+counter+"</p>")}}……var name = prompt("What is your name?");var name = prompt("What is your name?");if(name=="John") document.writeln("Hello.");if(name=="John") document.writeln("Hello.");else if(name=="Jean") document.writeln("Bonjour.");else if(name=="Jean") document.writeln("Bonjour.");else document.writeln("Who are you?");else document.writeln("Who are you?");
Client-side technologies: JavaScriptClient-side technologies: JavaScript
Giacomo Fazio - 2011Giacomo Fazio - 2011
Can walk the DOMCan walk the DOM
Control flowControl flow
24
If you need to track user information across several Web pages to create a "Web application“, you must use server-side programming.
If you need to interact with server-side databases, you must use server-side programming.
If you need to use server variables or check the capabilities of the user's browser, you must use server-side programming
In general, server-side programming creates dynamic web pages
Server-Side or Client-Side?Server-Side or Client-Side?
Giacomo Fazio - 2011Giacomo Fazio - 2011
25
If you want to have dynamic client forms with client-side validation, you must use client-side programming.
If you want your site to have highly interactive pages, you should use client-side programming.
If you need to provide your client with advanced functionality that can be created only using ActiveX controls (or Flash, or …), you must use client-side programming.
If you want to control the user's browser (i.e., to turn off the menus), you must use client-side programming.
So if you want to bring life to the HTML pages, you must use client-side programming
Server-Side or Client-Side?Server-Side or Client-Side?
Giacomo Fazio - 2011Giacomo Fazio - 2011
26
Both server-side and client-side Both server-side and client-side programming, either working together programming, either working together
hand-to-hand or not, enhance web hand-to-hand or not, enhance web development by extending server development by extending server functionality and at the same time, functionality and at the same time,
enrich our web experience with enrich our web experience with interactivityinteractivity
Server-Side or Client-Side?Server-Side or Client-Side?
Giacomo Fazio - 2011Giacomo Fazio - 2011
27
■ In the last years the trend is not to use pure JavaScript, but to use one of the many frameworks created for it
■ Each framework allows a more rapid development, allowing the web programmer to write a code that is often more elegant, secure and cross browser compatible.
■ There are many frameworks: jQuery, mooTools, Dojo, Prototype, etc.
■ The most used is jQuery (39% of all sites that use JavaScript use jQuery)
Introduction to jQueryIntroduction to jQuery
Giacomo Fazio - 2011Giacomo Fazio - 2011
28
■ Use of jQuery and of the other frameworks:
Introduction to jQueryIntroduction to jQuery
Giacomo Fazio - 2011Giacomo Fazio - 2011
29
■ Developed by John Resig at Rochester Institute of Technology
■ jQuery is a lightweight JavaScript library that emphasizes interaction between JavaScript and HTML. It was released in January 2006 at BarCamp NYC by John Resig.
■ jQuery is free, open source software, dual-licensed under the MIT License and the GNU General Public License.
■ It’s all about simplicity. Why should web developers be forced to write long, complex, book-length pieces of code when they want to create simple pieces of interaction?
■ Easy to learn■ It's tiny, few KB■ Well documented■ Cross browser compatibility
Introduction to jQueryIntroduction to jQuery
Giacomo Fazio - 2011Giacomo Fazio - 2011
30
■ What jQuery can do: Cross browser support and detection AJAX functions CSS functions DOM manipulation DOM transversal Attribute manipulation Event detection and handling JavaScript animation Hundreds of plugins for pre-built user interfaces, advanced
animations, form validation, etc Expandable functionality using custom plugins Small foot print
■ Starting is easy: download the last ”js” file from jQuery website and include it in your html file using <script src="jquery-1.4.2.js" type="text/javascript" charset="utf-8"></script>
then use it instead of (or together with) your Javascript code.
Introduction to jQueryIntroduction to jQuery
Giacomo Fazio - 2011Giacomo Fazio - 2011
31
■ So we don't have anymore to learn pure JavaScript? It's not that easy: jQuery is extraordinarily useful, but you'd better know how JavaScript works and how to use it correctly.
■ The best way is probably to look for a pair of good tutorials on JavaScript, study and practise a bit with it, then use jQuery when possible: your code will surely benefit from it
Introduction to jQueryIntroduction to jQuery
Giacomo Fazio - 2011Giacomo Fazio - 2011
32
■ It's the principal component of the framework
■ It provides the function $(). ■ Example:
$('<p>Hello World</p>').appendTo('body');$('<p>Hello World</p>').appendTo('body');
jQuery CorejQuery Core
Giacomo Fazio - 2011Giacomo Fazio - 2011
33
■ They are one of the most important innovations of jQuery, whose aim is to select HTML elements of the page using tag name, attributes or their content (similar to CSS selectors)
■ 9 types of selectors: Basic selectors: used to select elements by their id, tag name and
class; Hierarchy selectors: used to select elements by the hierarchical
organization of the page; Basic filters: used to filter elements according to their position and
order in the page; Content filters: used to filter elements according to their content; Visibility filters: used to filter elements according to their visibility Attribute filters: used to filter elements according to their
attributes;; Child filters: used to filter child elements of an element; Form selectors: used to select elements according to their usage
in the form; Form filters: used to select elements of a form according to their
current state.
jQuery selectorsjQuery selectors
Giacomo Fazio - 2011Giacomo Fazio - 2011
35
■ As in JavaScript, jQuery allows the user to add, modify and delete the attributes of the HTML elements.
■ Example:
$('a.google').attr('href','http://www.google.com');$('a.google').attr('href','http://www.google.com');
$('a#home').addClass('selected');$('a#home').addClass('selected');
alert($('input#name').val());alert($('input#name').val());
$('div').text('New content...')$('div').text('New content...')
jQuery attributes managementjQuery attributes management
Giacomo Fazio - 2011Giacomo Fazio - 2011
36
■ Dual purpose methods■ Example:
<p> Hello World! </p><p> Hello World! </p>
myvar= $('p').text(); myvar= $('p').text();
$('p').text(”Hello to everybody!”);$('p').text(”Hello to everybody!”);
jQuery getters and settersjQuery getters and setters
Giacomo Fazio - 2011Giacomo Fazio - 2011
<p> Hello to everybody! </p><p> Hello to everybody! </p>
myvar = 'Hello World!'myvar = 'Hello World!'
37
■ jQuery provides some functions whose aim is to manipulate the DOM: modify the content of the elements, add, remove and substitute elements in specific points, etc.
■ Example:
$('body').append(”<div id='container'></div>”);$('body').append(”<div id='container'></div>”);$('#container').text('Here goes the container text').prepend(”<div id='box'></div>”)$('#container').text('Here goes the container text').prepend(”<div id='box'></div>”)$('#box').text('Here goes the box text').append(”<img src='img.jpg' />”)$('#box').text('Here goes the box text').append(”<img src='img.jpg' />”)
<div id='container'><div id='container'><div id='box'<div id='box'Here goes the box textHere goes the box text<img src='img.jpg' /> <img src='img.jpg' /> </div> </div> Here goes the container textHere goes the container text</div></div>
jQuery DOM manipulationjQuery DOM manipulation
Giacomo Fazio - 2011Giacomo Fazio - 2011
38
■ jQuery allows the user to change the graphical features of each HTML element of the page.
■ Two ways: The function css() helpers that recall particular properties (for
example width() and height()).■ Example:
$('#img').css('width','50px');$('#img').css('width','50px');$('#img').width('50px');$('#img').width('50px');
jQuery and CSSjQuery and CSS
Giacomo Fazio - 2011Giacomo Fazio - 2011
39
■ jQuery allows the user to associate a callback function to each event. This function will be executed when the event occurs.
■ Example:
clkCallback = function() { clkCallback = function() { alert ('you clicked me'); alert ('you clicked me');
};};$('div#link').click(clkCallback);$('div#link').click(clkCallback);
=
$('div#link').click(function() {$('div#link').click(function() {alert ('you clicked me');alert ('you clicked me');
});});
jQuery and eventsjQuery and events
Giacomo Fazio - 2011Giacomo Fazio - 2011
40
■ jQuery provides some functions to make your web application more and more similar to a desktop application.
■ Beyond the css functions that we have already seen, we have other functions, such as fade() and slide().
■ Another good function is animate(), which allows to create your animation from the element that has to be animated (height, width, position) and from the starting value and the target one.
jQuery graphical effectsjQuery graphical effects
Giacomo Fazio - 2011Giacomo Fazio - 2011
41
What's AJAX? Wait some more slides ;-)
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
42
■ jQuery UI (User Interface) has been started as a project parallel to jQuery, but it has been then incorporated into the jQuery development, becoming the ”jQuery official user interface library”, even though it has an autonomous development group
■ Three subcomponents: Graphical effects (that can be added to the ones
present in jQuery) Complex interactions (ordering of the elements,
drag and drop, etc) Widgets (complex controls such as calendars,
modal windows and tabs navigation)
jQuery UIjQuery UI
Giacomo Fazio - 2011Giacomo Fazio - 2011
43
■ Start by looking on Google ”jquery tutorial”, you will find a lot of stuff
■ Look on jquery.com, you will find the explanation of all the functions and many examples
■ Look on www.html.it, you will find some good guides (in italian)
■ If you have time and you like, buy a book on jQuery (there are many out there)
■ When you have learned well jQuery, start with jQuery UI if you like
■ Google is your friend ;-)
Where can I study jQuery?Where can I study jQuery?
Giacomo Fazio - 2011Giacomo Fazio - 2011
44
In general, keep in mind that the process is the following: The client asks a server a page The server retrieves the page The server executes the server-side code in the
page and obtains so a page that contains HTML and client-side code
The server returns that page to the client The browser loads the page returned by the
server It is possible for the user to exploit the client-
side code to obtain visual effects and in general to make the web page looks like an application
Limitations of the current modelLimitations of the current model
Giacomo Fazio - 2011Giacomo Fazio - 2011
45
Anyway, there are lots of limitations: when a page has been obtained and loaded by the client, you
can't access the server anymore (to do this you have to ask again the server the page, so you have to repeat the whole process)
If I have a page with lots of things and I want to update only a little part (for example stocks trends), I have to reload the whole page from the server and wait: this causes loss of band and time and can make the interaction with the user slow and bad
The alternative would be to put the stocks trends on another page or on a popup window and reload it often, but the result would be very ugly!
You could also use Iframes, but they don't solve all the problems, it's not clear if they are deprecated or not and some programmers tend to consider them a dirty solution
You could use other technologies like Java applets or Flash, but they usually suffer from some problems, such as heaviness, proprietary solutions, not cross-browsers or cross-platforms, need to install other plugins or software, security issues, etc.
Limitations of the current modelLimitations of the current model
Giacomo Fazio - 2011Giacomo Fazio - 2011
46
This is the model used by ”normal” webpages (totally sinchronous):
As you can see the client transmits data to the server when the user requests it. While the server is processing and trying to return a new web page to the user, the user is left with a blank screen and a ”still loading” icon in the status bar
Solution: AJAX!!!
Limitations of the current modelLimitations of the current model
Giacomo Fazio - 2011Giacomo Fazio - 2011
47
■ It stands for Asynchronous Javascript And XML■ It's a technique for creating “better, faster, more
responsive web applications”■ It’s not a new technology, but today it's more and more
used, especially by Google, Microsoft, etc.■ How does it work?
JavaScript applications perform requests to the server The server responds with the requested information All this takes place without reloading the page and
without blocking the page (asynchronous of the client)
Javascript then processes the result and manipulates the page
XML is used for data exchange, even if you can also use JSON or preformatted HTML, or simple text
AJAXAJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
48
■ Nobody forces you to use JavaScript, since you can also use concurrent technologies like VBScript, but JavaScript is widely adopted, cross-browser and cross-platform, so we will deal only with it
■ So AJAX is simply the idea of enabling your browser to communicate asynchronously with the server to provide a richer user “Web 2.0” experience.
■ It's faster because less data is transmitted and because the browser has less work to do
■ It allows a better user experience and interaction with the web page
■ Better solution than Java applets or Flash, because it is cross-browser, cross-platform, lighter, no need to install other plugins, no proprietary, etc.
AJAXAJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
49
■ This is the model of an AJAX Web Application:
■ An intermediary layer (Ajax engine) is introduced between the user and the server, written in JavaScript and usually in a hidden frame
■ This engine is responsible for both rendering the interface and communicating with the server on the user’s behalf.
AJAXAJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
50
■ In particular every user action that normally would generate an HTTP request takes the form of a JavaScript call to the Ajax engine instead:
any response to a user action that doesn’t require a trip back to the server (such as simple data validation, editing data in memory, and even some navigation) is handled directly by the engine
if the engine needs something from the server in order to respond (if it’s submitting data for processing, loading additional interface code, or retrieving new data) the engine makes those requests asynchronously, usually using XML, without interrupting the user’s interaction with the application.
■ Using AJAX in our example of the stocks trends, we can have in our page, among the other things, a field in which we can view the stocks trends, with a button that, if pressed, will do an AJAX call, get the new trends from the server and show them in the field, without reloading the whole page and without making us wait. We can also avoid the button and do an automatic refresh every n seconds.
AJAXAJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
51
■ Your browser has to support the XMLHttpRequest (XHR) API, used to send HTTP or HTTPS requests directly to a web server: new browsers surely support it
■ All starts from JavaScript: if your browser doesn't support it, it won't support AJAX
■ JavaScript has to create an XMLHttpRequest object, and send it (via HTTP) to the server
■ Nothing special is required of the server (every server can handle HTTP requests)
var request = null;var request = null;
function getXMLHttpRequest( ) {function getXMLHttpRequest( ) { try { try {
request = new XMLHttpRequest();request = new XMLHttpRequest(); }} catch(err1) {catch(err1) { request = null;request = null; }} if (request == null) alert("Error creating request object!");if (request == null) alert("Error creating request object!");}}
JavaScript and AJAXJavaScript and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
52
function sendRequest() {function sendRequest() { getXMLHttpRequest();getXMLHttpRequest(); var url = some URLvar url = some URL request.open("GET", url, true); //or POSTrequest.open("GET", url, true); //or POST request.onreadystatechange = handleTheResponse;request.onreadystatechange = handleTheResponse; request.send(null); //or send(content), if POSTrequest.send(null); //or send(content), if POST}}function handleTheResponse() {function handleTheResponse() { if (request.readyState == 4) {if (request.readyState == 4) { if (request.status == 200) {if (request.status == 200) { var response = request.responseText;var response = request.responseText; // do something with the response string// do something with the response string } else {} else { alert("Error! Request status is " + request.status);alert("Error! Request status is " + request.status); }} }}}}
■ In the page:
<input value="Click Me" type="button" onclick="sendRequest"><input value="Click Me" type="button" onclick="sendRequest">
JavaScript and AJAXJavaScript and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
53
■ It's not that simple to handle AJAX from JavaScript■ The problem is solved by jQuery, that has many ways to work with
AJAX and allows the user to do it in a simple and efficient way■ You don't have anymore to work directly with the XMLHttpRequest
object and with all the JavaScript functions■ Consider a function that has to write a string on a file:
function write_data() {function write_data() {var data2send= {var data2send= {
'data' : $('#textarea').val()'data' : $('#textarea').val()};};$.post("http://localhost/write_file.php", data2send, $.post("http://localhost/write_file.php", data2send, function(data){function(data){
if(data) alert("Data saved successfully!");if(data) alert("Data saved successfully!");else alert("Error! Please retry!");else alert("Error! Please retry!");
});});}}
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
JavaScript functionInput data:
format data as in
the example
Output dataPOST method to pass parameters:
you can also use GET
54
■ File write_file.php on the server:
<?php<?php$data = $_REQUEST['data'];$data = $_REQUEST['data'];file_put_contents('testfile' , $data);file_put_contents('testfile' , $data);print true;print true;?>?>
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
All the input data can be found
as fields of the $_REQUEST array:
the data2send structurehas become an associative array
You have to print the result of the function, in order to return it to
the JavaScript function
55
■ It works, but this way you will create a different PHP file for each AJAX call.
■ Let's make things in a more efficient and tidy way, by creating a file on the server that contains many functions and by passing in data2send the function to call.
■ The JavaScript function becomes:
function write_data() {function write_data() {var data2send= {var data2send= {
'func': 'write_on_file','func': 'write_on_file','data' : $('#textarea').val()'data' : $('#textarea').val()
};};$.post("http://localhost/$.post("http://localhost/procedures_retrieve.phpprocedures_retrieve.php", data2send, ", data2send, function(data){function(data){
if(data) alert("Data saved successfully!");if(data) alert("Data saved successfully!");else alert("Error! Please retry!");else alert("Error! Please retry!");
});});}}
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
function to execute on server
56
■ File procedures_retrieve.php on the server:
<?php<?php$func = $_REQUEST['func'];$func = $_REQUEST['func'];$res = $func($_REQUEST);$res = $func($_REQUEST);print $res;print $res;
function write_on_file($req) {function write_on_file($req) {$data=$req['data'];$data=$req['data'];file_put_contents('testfile' , $data);file_put_contents('testfile' , $data);return true;return true;
}}?>?>
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
57
■ Now it's ok, but we can make things even better■ The JavaScript function becomes:
function write_data() {function write_data() {var data2send= {var data2send= {
'func': 'write_on_file','func': 'write_on_file','data' : $('#textarea').val()'data' : $('#textarea').val()
};};$.post("http://localhost/$.post("http://localhost/rpc.phprpc.php", data2send, ", data2send, function(data){function(data){
if(data) alert("Data saved successfully!");if(data) alert("Data saved successfully!");else alert("Error! Please retry!");else alert("Error! Please retry!");
});});}}
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
58
■ File rpc.php on the server:
<?php<?phprequire_once 'procedures_retrieve.php';require_once 'procedures_retrieve.php';$func = $_REQUEST['func'];$func = $_REQUEST['func'];$res = $func($_REQUEST);$res = $func($_REQUEST);print $res;print $res;?>?>
■ File procedures_retrieve.php on the server:
<?php<?phpfunction write_on_file($req) {function write_on_file($req) {
$data=$req['data'];$data=$req['data'];file_put_contents('testfile' , $data);file_put_contents('testfile' , $data);return true;return true;
}}?>?>
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
59
■ Our PHP function returns only 'true'. But if we have to return objects?
■ Let's introduce the JSON encoding■ The JavaScript function becomes:
function write_data() {function write_data() {var data2send= {var data2send= {
'func': 'write_on_file','func': 'write_on_file','data' : $('#textarea').val()'data' : $('#textarea').val()
};};$.post("http://localhost/rpc.php", data2send, $.post("http://localhost/rpc.php", data2send, function(data){function(data){
if(data) alert(if(data) alert(datadata););else alert("Error! Please retry!");else alert("Error! Please retry!");
},},'json''json'););}}
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
JSON encoding: JavaScript expects an object encoded
in JSON
60
■ File rpc.php on the server:
<?php<?phprequire_once 'procedures_retrieve.php';require_once 'procedures_retrieve.php';$func = $_REQUEST['func'];$func = $_REQUEST['func'];if (function_exists($func)) {if (function_exists($func)) {
header('Content-Type: text/plain; charset=utf-8');header('Content-Type: text/plain; charset=utf-8');print print json_encodejson_encode($func($_REQUEST));($func($_REQUEST));
} } else {else {
print print json_encodejson_encode(array ((array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}?>?>
■ File procedures_retrieve.php on the server:
<?php<?phpfunction write_on_file($req) {function write_on_file($req) {
$data=$req['data'];$data=$req['data'];file_put_contents('testfile' , $data);file_put_contents('testfile' , $data);return return $req$req;;
}}?>?>
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
I'm returning an object
JSON encoding:the jQuery function expects
something encoded in JSON, so it knows
how to handle it
61
■ JSON stands for JavaScript Object Notation and is a subset of JavaScript, in fact it can be parsed by a JavaScript parser
■ It's simultaneously human- and machine-readable format■ It has support for Unicode, allowing almost any information
in any human language to be communicated■ It can represent either complex or simple data: Strings,
Number, Boolean, Objects, Arrays, Records, Lists, Trees■ E.g. of Object:
{ "name": "Jack Nimble", "format": { "type": "rect", "width": 120, "interlace": false}}
■ E.g. of Array: ["Sunday", "Monday", "Tuesday", "Wednesday“]
■ Also compatible with other languages like C, C++, C#, ColdFusion, Python and many more.
What's JSON?What's JSON?
Giacomo Fazio - 2011Giacomo Fazio - 2011
62
■ One more thing: in a PHP function called by AJAX, everything written to STDOUT/STDERR won't be shown, instead will be written in a buffer and all its content is the return value of the function when it finishes
■ So don't use functions like echo(), print_r or var_dump(), they are useless and they would ruin your output by adding things you don't want.
■ Instead write to a file your temporary output, by using
$res=print_r($object,true); //saves the output on $res$res=print_r($object,true); //saves the output on $resfile_put_contents(”file_put_contents(”filenamefilename”,$res);”,$res);
■ For the same reason, disable errors showing through ini_set('display_errors', 0); at the beginning of the file rpc.php, instead enable option ”log_errors” in php.ini and select a writeable file, then always look at that file, you will find there your errors
■ So add this at the beginning of your rpc.php:
error_reporting(E_ALL);error_reporting(E_ALL);ini_set('display_errors', 0);ini_set('display_errors', 0);ini_set('log_errors',TRUE);ini_set('log_errors',TRUE);ini_set('error_log','errorlog');ini_set('error_log','errorlog');
jQuery and AJAXjQuery and AJAX
Giacomo Fazio - 2011Giacomo Fazio - 2011
63
■ The easy way: print_r and var_dump() for PHP (include it in the HTML tag <pre></pre>
to avoid seeing the results only in one line); alert() or console.log() for JavaScript / jQuery When you want to see the structure of an object in Javascript / jQuery (for
example the object returned from a AJAX call) you can use this function:
function print_r(theObj){function print_r(theObj){if(theObj.constructor == Array || theObj.constructor == Object){if(theObj.constructor == Array || theObj.constructor == Object){
document.write("<ul>");document.write("<ul>");for(var p in theObj){for(var p in theObj){
if(theObj[p].constructor == Array || theObj[p].constructor == if(theObj[p].constructor == Array || theObj[p].constructor == Object){Object){
document.write("<li>["+p+"] => "+typeof(theObj)+"</li>");document.write("<li>["+p+"] => "+typeof(theObj)+"</li>");document.write("<ul>");document.write("<ul>");print_r(theObj[p]);print_r(theObj[p]);document.write("</ul>");document.write("</ul>");
} } else document.write("<li>["+p+"] => "+theObj[p]+"</li>");else document.write("<li>["+p+"] => "+theObj[p]+"</li>");
}}document.write("</ul>");document.write("</ul>");
}}}}
How to debug?How to debug?
Giacomo Fazio - 2011Giacomo Fazio - 2011
64
As said before, during an AJAX call, on the server side you can't use print_r() or var_dump(), so write to a file
The best way: Use Firebug/Chrome Developer Tools, really useful for
JavaScript/jQuery and to control request and response of AJAX calls (you will find many tutorials in Internet)
As said before, enable option ”log_errors” in php.ini and select a writeable file, then always look at that file, especially for AJAX calls
Use a PHP debugger that includes also tracing and profiling features, such as XDebug (you have at first to install and enable it in your php.ini)
Use an IDE (ex. NetBeans or Aptana Studio), that can control XDebug in a graphical and easy way
Use Unit Testing: I suggest to use PHPUnit to test PHP code (look here and then here) and QUnit to test JavaScript/jQuery code (look here and here)
A look to the TestSwarm website could be interesting as well. Probably the best solution is to combine all the techniques!
How to debug?How to debug?
Giacomo Fazio - 2011Giacomo Fazio - 2011
65
■ For further information about jQuery and AJAX you can find a lot of stuff on the Internet, for example here
■ AJAX is a great technology, but it has some limitations:
Back functionality doesn't work because the dynamic pages don’t register themselves to the browsers history engine (this can be solved using Iframes and/or anchor tags, as showed here and here)
The page cannot be bookmarked if implemented using AJAX
AJAX limitationsAJAX limitations
Giacomo Fazio - 2011Giacomo Fazio - 2011
66
Returning to our example of the stocks trends, we solved a lot of problems using AJAX but, in order to view updated stocks trends in the field, we have to use polling, that is we have to do a call to the server every n seconds, with the drawback to waste server resources and bandwidth. If the millions of users of a large site do this every few seconds, the effect on the server would be similar to a DOS attack! The solution could be not to use polling and make the server gives data to the browser as soon as data on the server have changed. This is not possible, since in AJAX all the server processing is done at the request of the client, the server can only answer and can't start a communication towards the client...
AJAX limitationsAJAX limitations
Giacomo Fazio - 2011Giacomo Fazio - 2011
67
For example, with the polling approach, this could be the function called by jQuery to retrieve the number of users currently registered:
function retrieve_numusers() {function retrieve_numusers() {var data2send= {var data2send= {
'func': 'retrieve_numusers','func': 'retrieve_numusers',};};$.post("http://localhost/example2/rpc.php", data2send, function(data){$.post("http://localhost/example2/rpc.php", data2send, function(data){
if(!data) alert("Error! Please retry!");if(!data) alert("Error! Please retry!");else {else {
$('#numusers').text(data); //writes the number in the document$('#numusers').text(data); //writes the number in the documentsetTimeout('retrieve_numusers()',10000);setTimeout('retrieve_numusers()',10000);
}}},'json');},'json');
}}
$(document).ready(function(){$(document).ready(function(){retrieve_numusers();retrieve_numusers();
});});
So we are calling the function every 10 sec.
AJAX: polling example (client side)AJAX: polling example (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
68
And this, assuming that updated data are on a database, could be the function on the server:
function retrieve_numusers($req) {function retrieve_numusers($req) {$conn=mysql_connect("localhost","root","") or die ("<br />Error $conn=mysql_connect("localhost","root","") or die ("<br />Error in the database connection " . mysql_error($conn));in the database connection " . mysql_error($conn));mysql_select_db("example", $conn); mysql_select_db("example", $conn); $query="SELECT surname FROM user";$query="SELECT surname FROM user";$res=mysql_query($query);$res=mysql_query($query);$num=mysql_num_rows($res);$num=mysql_num_rows($res);return $num;return $num;
}}
So this is the situation: Waste of resources Waste of bandwidth The solution is... Comet!
AJAX: polling example (server side)AJAX: polling example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
69
Comet is a web application model which allows a web server to push data to a browser, without the browser explicitly requesting it
Called also Ajax Push, Ajax Reverse, HTTP Push, etc.
Two types of Comet techniques: long polling and streaming (Hidden IFrame and Multipart XMLHttpRequest)
Comet: overviewComet: overview
Giacomo Fazio - 2011Giacomo Fazio - 2011
70
It is very similar to polling, except the request sleeps on the server and if at any time data becomes available, the server immediately returns the requested data to the client.
So this represents the situation:
Comet: long pollingComet: long polling
Giacomo Fazio - 2011Giacomo Fazio - 2011
71
For example, with the long polling approach, this could be the function called by jQuery to retrieve the number of users currently registered:
function retrieve_numusers() {function retrieve_numusers() {var data2send= {var data2send= {
'func': 'retrieve_numusers''func': 'retrieve_numusers'};};if($('#numusers').text()!="") data2send.currentnum=$('#numusers').text();if($('#numusers').text()!="") data2send.currentnum=$('#numusers').text();$.post("http://localhost/example3/rpc.php", data2send, function(data){$.post("http://localhost/example3/rpc.php", data2send, function(data){
if(!data) alert("Error! Please retry!");if(!data) alert("Error! Please retry!");else {else {
$('#numusers').text(data); $('#numusers').text(data); //writes the number in the document //writes the number in the documentretrieve_numusers();retrieve_numusers();
}}},'json');},'json');
}}
$(document).ready(function() {$(document).ready(function() {retrieve_numusers();retrieve_numusers();
});});
We are doing the AJAX call passing to the server function the previous value, in order to see if it has changed or not.
If the server function returns (because the value changed or because of timeout), the client will do the call again without waiting
Comet: long polling example (client side)Comet: long polling example (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
72
And this could be the function on the server:
set_time_limit(0); //to avoid timeoutsset_time_limit(0); //to avoid timeoutsfunction retrieve_numusers($req) {function retrieve_numusers($req) {
while(true) {while(true) {$conn=mysql_connect("localhost","root","") or die ("<br />Error in the $conn=mysql_connect("localhost","root","") or die ("<br />Error in the database connection " . mysql_error($conn));database connection " . mysql_error($conn));mysql_select_db("example", $conn); mysql_select_db("example", $conn); $query="SELECT surname FROM user";$query="SELECT surname FROM user";$res=mysql_query($query);$res=mysql_query($query);$num=mysql_num_rows($res);$num=mysql_num_rows($res);if(!isset($req["currentnum"]) || $num!=$req["currentnum"]) return $num;if(!isset($req["currentnum"]) || $num!=$req["currentnum"]) return $num;
}}}}
We passed to the function $req["currentnum"], so the server can understand if the value taken from the database has changed
The function returns only if $req["currentnum"] is not set (that is it is the first time we call the function) or if the value has changed
Comet: long polling example (server side)Comet: long polling example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
73
One factor you must keep in mind is that, if you can't avoid timeouts like we did with set_time_limit(0), your AJAX request can time out if you sleep too long. To overcome timing out, you should only sleep for less than the timeout, then return, and the client must repeat the long poll request until data becomes available.
Long polling drawback: the two-connection per host name limit for some browsers, that is you cannot open two connections to the same host name with long-lived connections and open a third connection to same server; this is due to security restrictions of some web browsers.
Comet: long pollingComet: long polling
Giacomo Fazio - 2011Giacomo Fazio - 2011
74
It is also referred as the ”Forever Frame” technique
IFrame stands for Inline Frame. It is part of HTML and it allows a Web page to embed one HTML document inside another HTML element.
It doesn't use AJAX
Comet: Hidden IFrameComet: Hidden IFrame
Giacomo Fazio - 2011Giacomo Fazio - 2011
75
With the Hidden IFrame approach, you have at first to create an iframe element in your document, setting the height and the frameborder to 0 (in order to make it hidden):
<iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" <iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" height="0" width="0" src="server.php"></iframe>height="0" width="0" src="server.php"></iframe>
As you can see, the iframe content is the file server.php whose example code below shows it never returns completely from the call, but every time, after a certain elaboration, it injects a JavaScript code into the iframe, passing it the updated result of the elaboration:
while(true) {while(true) { $num=rand(); //it generates a random number$num=rand(); //it generates a random number
echo "<br /><br />"; //it may be necessary to send some noise to make it workecho "<br /><br />"; //it may be necessary to send some noise to make it work echo "<script type='text/javascript'>alert($num);</script>";echo "<script type='text/javascript'>alert($num);</script>"; sleep(1); //a little break for the serversleep(1); //a little break for the server}}
With AJAX, the server function had to end after having sent a value and then it could be called again
With the Hidden Iframe approach it's not necessary: the function can send a value to the client and continue executing
Comet: Hidden IFrameComet: Hidden IFrame
Giacomo Fazio - 2011Giacomo Fazio - 2011
76
We can improve this model by using the usual approach (rpc.php and procedures_retrieve.php), especially if we are already using it with AJAX on our website and we want a tidy solution without many files. So we could use GET in the iframe content to choose the function :
<iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" height="0" <iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" height="0" width="0" src="width="0" src="rpc.php?func=function1rpc.php?func=function1"></iframe>"></iframe>
rpc.php is the usual
<?php<?phprequire_once 'procedures_retrieve.php';require_once 'procedures_retrieve.php';$func = $_REQUEST['func'];$func = $_REQUEST['func'];if (function_exists($func)) {if (function_exists($func)) {
header('Content-Type: text/plain; charset=utf-8');header('Content-Type: text/plain; charset=utf-8');print json_encode($func($_REQUEST));print json_encode($func($_REQUEST));
} } else {else {
print json_encode(array (print json_encode(array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}?>?>
Comet: Hidden IFrameComet: Hidden IFrame
Giacomo Fazio - 2011Giacomo Fazio - 2011
We can also specify other parameters
using GETor use JSON
to send objects
Values in GET are in $_REQUEST and are passed to the function
77
■ In procedures_retrieve.php, among the other functions, we have:
function function1($req) {function function1($req) {set_time_limit(0); //no timeoutsset_time_limit(0); //no timeoutsob_implicit_flush(); //explicit calls to flush() will no longer be neededob_implicit_flush(); //explicit calls to flush() will no longer be needed$num=rand(); //it generates a random number$num=rand(); //it generates a random numberecho "<br /><br />"; //it may be necessary to send some noiseecho "<br /><br />"; //it may be necessary to send some noise
echo "<script type='text/javascript'>alert($num);</script>";echo "<script type='text/javascript'>alert($num);</script>"; sleep(1); //a little break for the serversleep(1); //a little break for the server}}
■ The line print json_encode($func($_REQUEST)) print json_encode($func($_REQUEST)) in rpc.php won't print anything, but we leave it in that it could be needed for other server functions (for example for AJAX)
Comet: Hidden IFrameComet: Hidden IFrame
Giacomo Fazio - 2011Giacomo Fazio - 2011
78
So we will use this approach in our example of the registered users. We use this iframe on the client:
<iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" height="0" <iframe name="hidden_iframe" id="hidden_iframe" frameborder="0" height="0" width="0" src="width="0" src="rpc.php?func=retrieve_numusersrpc.php?func=retrieve_numusers"></iframe>"></iframe>
rpc.php is the usual. This is our function in procedures_retrieve.php:
function retrieve_numusers($req) {function retrieve_numusers($req) {set_time_limit(0); //no timeoutsset_time_limit(0); //no timeoutsob_implicit_flush(); //explicit calls to flush() will no longer be neededob_implicit_flush(); //explicit calls to flush() will no longer be needed$old_num=-1;$old_num=-1;while(true) {while(true) {
$conn=mysql_connect("localhost","root","");$conn=mysql_connect("localhost","root","");mysql_select_db("example", $conn); mysql_select_db("example", $conn); $query="SELECT surname FROM user";$query="SELECT surname FROM user";$res=mysql_query($query);$res=mysql_query($query);$num=mysql_num_rows($res);$num=mysql_num_rows($res);if($num!=$old_num) {if($num!=$old_num) {echo "<br /><br />"; //it may be necessary to send some noiseecho "<br /><br />"; //it may be necessary to send some noiseecho "<script type='text/javascript'>parent.update_numusers($num);</script>";echo "<script type='text/javascript'>parent.update_numusers($num);</script>";$old_num=$num;$old_num=$num;
}}sleep(1); //a little break for the serversleep(1); //a little break for the server}}
}}
Comet: Hidden IFrame exampleComet: Hidden IFrame example
Giacomo Fazio - 2011Giacomo Fazio - 2011
79
■ It never returns completely from the call, but every time it injects a JavaScript code into the iframe, passing it the updated number of registered users
■ What does that line do? It will call the client function update_numusers(), whose purpose is to write in the document the updated number
function update_numusers(num) {function update_numusers(num) {$('#numusers').text(num);$('#numusers').text(num);
}}
■ Since the server function doesn't terminate after having sent a value to the client, it can handle the old value and there is no need to get it from the client anymore
Comet: Hidden IFrame exampleComet: Hidden IFrame example
Giacomo Fazio - 2011Giacomo Fazio - 2011
80
■ Drawbacks of the Hidden IFrame approach: IFrames were never meant to serve as a
control for handling streaming. As such, this approach has been criticized by some as being a bit of a "hack".
IFrames are slow-loading elements, if compared to the alternatives
It causes browsers to leave the loading bar visible indefinitely, and in some browsers continually shows a wait cursor
Lack of a reliable error handling method Impossibility of tracking the state of the
request calling process
Comet: Hidden IFrame drawbacksComet: Hidden IFrame drawbacks
Giacomo Fazio - 2011Giacomo Fazio - 2011
81
Multipart XMLHttpRequest (MXHR) is a feature invented in 1995 by Netscape Navigator, which allowed servers to send new versions of an image or HTML page to the browser, as part of a multipart HTTP response, using the content type multipart/x-mixed-replace.
Since 2004, Gecko-based browsers such as Firefox accept multipart responses to XHR, which can therefore be used as a streaming Comet transport
On the server side, each message is encoded as a separate portion of the multipart response
On the client side, the callback function provided to the XHR onreadystatechange() function will be called as each message arrives.
This functionality is only included in Gecko-based browsers; there was a discussion about adding it to WebKit (Chrome, Safari, etc.) but with the coming of HTML5 it was set aside
Comet: Multipart XMLHttpRequestComet: Multipart XMLHttpRequest
Giacomo Fazio - 2011Giacomo Fazio - 2011
82
HTTP request and response headers, which contain lots of additional, unnecessary header data and introduce latency.
Effort to simulate full-duplex communication over half-duplex HTTP
Significant overhead in terms of resource consumption
Lots of complexity Error-prone Reduction of CPU performance HTTP wasn't designed for real-time, full-duplex
communication! Future solution: HTML5 WebSockets!
Comet drawbacksComet drawbacks
Giacomo Fazio - 2011Giacomo Fazio - 2011
83
HTML5 is a markup language for the projectation of webpages. Still draft: W3C says it will be ready for July 2014. The initial specifics have been created by an external group from W3C,
called WHATWG. Now both WHATWG and W3C HTML are following it. Main objectives:
The main aim was to propose new commands and features that were so far obtained in a non-standard way, that is through plugins or proprietary extensions, which sometimes worked only for some browsers.
Guarantee compatibility with browsers, including the mobile ones. Separate content from presentation (use CSS) Support for geolocation New tags <audio> and <video> to handle media Support for the Canvas element that allows to create animations and
vectorial graphics through JavaScript Support for offline web applications Drag and drop WebSockets And many others...
The future: HTML5The future: HTML5
Giacomo Fazio - 2011Giacomo Fazio - 2011
84
We are particularly interested in WebSockets HTTP:
half-duplex (traffic flows in only one direction at a time) Hard to achieve real-time, bi-directional communication, even with
Comet Tons of unnecessary HTTP header information sent with each HTTP
request and response and added latency, with overhead as much as 2 Kbytes
WebSocket: New protocol that uses the same TCP connection Bi-directional, full-duplex, text based socket The web application client can maintain an always open connection
with the server and data can be sent and received at the same time: no need to use anymore polling or Comet techniques
Enables webpages to communicate with a remote host Traverses firewalls, proxies and routers seamlessly Dramatic overhead reduction (2 bytes overhead per frame) Reduced complexity It is still a draft, but it will be the future, and now it has reached
enough stability to be discussed
HTML5: WebSocketsHTML5: WebSockets
Giacomo Fazio - 2011Giacomo Fazio - 2011
85
Suppose you have a web application which uses the polling approach and whose overhead for request and response headers is 871 bytes (not so bad, considering that it can reach 2 Kbytes)
With WebSockets overhead is only 2 bytes What happens when many users use this application? Use case A: 1000 clients
With polling network throughput is 871*1000 = 871000 bytes = 6968000 bits per second (6.6 Mbps)
With WebSockets network throughput is 2*1000 = 2000 bytes = 16000 bits per second (0.015 Mbps)
Use case B: 10000 clients With polling network throughput is 871*10000 = 8710000 bytes =
69680000 bits per second (66 Mbps) With WebSockets network throughput is 2*10000 = 20000 bytes =
160000 bits per second (0.153 Mbps) Use case C: 100000 clients:
With polling network throughput is 871*100000 = 87100000 bytes = 696800000 bits per second (665 Mbps)
With WebSockets network throughput is 2*100000 = 200000 bytes = 1600000 bits per second (1.526 Mbps)
HTML5: WebSockets performanceHTML5: WebSockets performance
Giacomo Fazio - 2011Giacomo Fazio - 2011
86
So this is the situation:
HTML5: WebSockets performanceHTML5: WebSockets performance
Giacomo Fazio - 2011Giacomo Fazio - 2011
87
In order to use AJAX we had to use the XmlHttpRequest API, for WebSockets new APIs have been defined.
Now all the browsers support XmlHttpRequest (so they can use AJAX), but for WebSockets we have to use a browser which supports them:
currently they are supported and enabled in new versions of Chrome and Safari.
supported, but you have to enable them, on new versions of Firefox and Opera
The client side code can be written in JavaScript / jQuery. The main thing is the object WebSocket, we have to give it
a URL on the server when we build it We’ll be using three events:
onopen: When a socket has opened onmessage: When a message has been received onclose: When a socket has been closed
HTML5: WebSockets (client side)HTML5: WebSockets (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
88
Example:var ws;var ws;$(document).ready(function() {$(document).ready(function() {
try {try {ws = new WebSocket("ws://localhost:12345");ws = new WebSocket("ws://localhost:12345");ws.onopen = function () {ws.onopen = function () {
alert(”Connected...”);alert(”Connected...”);};};ws.onmessage = function(msg) {ws.onmessage = function(msg) {
alert(”Message arrived: ”+msg.data);alert(”Message arrived: ”+msg.data);};};ws.onclose = function () {ws.onclose = function () {
alert(”Disconnected...”);alert(”Disconnected...”);};};
}}catch(ex){ catch(ex){
alert(ex);alert(ex);}}
});});
HTML5: WebSockets (client side)HTML5: WebSockets (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
89
On server side, for AJAX we had to do nothing, because nothing changed for servers
The situation for WebSockets is more complicated, since we are not using HTTP, but a new protocol.
We must have a server listening to eventual connection requests from the client
Soon webservers and/or server-side languages will support completely WebSockets, but right now there are only unstable or beta solutions to implement them: new webservers only for them, Apache extensions, etc.
Examples: phpwebsocket, jWebSocket, web-socket-ruby, mod-pywebsocket, which allow the user to create a WebSocket on the server accepting connections from the client and to define what is the behavior to adopt when a message from the client arrives (you have to code respectively in PHP, Java, Ruby on Rails, Python).
HTML5: WebSockets (server side)HTML5: WebSockets (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
90
I decided to use phpwebsocket, since I want to code in PHP and, moreover, I have already the functions to execute server-side in PHP and I want to reuse them
You can find phpwebsocket here Use the class version, contained in websocket.class.php, you
have to create a new class that extends it and overrides the method process() in order to do what you like
Then you have to create a php file that creates a new object from this class, specifying server and port, and launch it with php q filename.php
Now you have a WebSocket on your server, listening on the port that you chose
There's a bug in the current version with the first message sent to the browser. Solution:
change line 102 in websocket.class.php tosocket_write($user->socket,$upgrade.chr(0).chr(255),strlen($upgrade)+2);socket_write($user->socket,$upgrade.chr(0).chr(255),strlen($upgrade)+2);
send something like ”\r\r” as first message if it doesn't work properly, simply relaunch the server
HTML5: WebSockets (server side)HTML5: WebSockets (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
91
With AJAX we passed data as a particular structure with the form { 'name': 'value', 'name2': 'value2' } which in the server function became an associative array ($_REQUEST)
Then we returned an object encoded in JSON through the function json_encode and the jQuery function which received it automatically did the conversion, since we had indicated it to expect JSON as result
Here the WebSockets exchange messages as strings So we can always send objects, but we have to handle JSON
encoding manually: We can encode an object from JavaScript / jQuery with
JSON.stringify(objectname) We can decode it in PHP with json_decode($msg,true),
that obtains an associative array Encode the object to return from PHP as usual, with
json_encode Decode it in JavaScript/jQuery with JSON.parse(msg.data)
HTML5: WebSockets (object passing)HTML5: WebSockets (object passing)
Giacomo Fazio - 2011Giacomo Fazio - 2011
92
WebSockets can be used for many things, but in this document we are interested in using them to substitute AJAX and in particular Comet
For example, the following could be the client side part to call a server function
var ws;var ws;function call_server_function() {function call_server_function() {
var data2send= {var data2send= {'func': 'server_function''func': 'server_function'
};};ws.send(JSON.stringify(data2send));ws.send(JSON.stringify(data2send));
}}$(document).ready(function(){$(document).ready(function(){
ws = new WebSocket("ws://localhost:12345");ws = new WebSocket("ws://localhost:12345");ws.onopen = function () {ws.onopen = function () {
ws.send("\r\r"); //to avoid the first message bugws.send("\r\r"); //to avoid the first message bugcall_server_function();call_server_function();
};};ws.onmessage = function(msg) {ws.onmessage = function(msg) {
alert(JSON.parse(msg.data));alert(JSON.parse(msg.data));};};ws.onclose = function () {ws.onclose = function () {};};
});});
WebSockets instead of AJAX (client side)WebSockets instead of AJAX (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
We are using JSONbecause we will
receive a JSON string from the server
93
On the server side, we have to extend the WebSocket class and override the method ”process()”.
In particular we will make it have the same behavior of our old rpc.php, which calls the functions in procedures_retrieve.php (that in fact is included)
include "websocket.class.php";include "websocket.class.php";require_once ”procedures_retrieve.php”;require_once ”procedures_retrieve.php”;class MyWebSocketServer extends WebSocket{class MyWebSocketServer extends WebSocket{
function process($user,$msg) {function process($user,$msg) {$this->say("< ".$msg); //enable only to see what arrives to the server$this->say("< ".$msg); //enable only to see what arrives to the server$msg_dec=json_decode($msg,true);$msg_dec=json_decode($msg,true);if(is_array($msg_dec)) {if(is_array($msg_dec)) {
$func = $msg_dec['func'];$func = $msg_dec['func'];if (function_exists($func)) {if (function_exists($func)) {
$res=json_encode($func($msg_dec));$res=json_encode($func($msg_dec));}}else {else {
$res=json_encode(array ($res=json_encode(array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}$this->send($user->socket,$res);$this->send($user->socket,$res);
}}}}
}}$master = new MyWebSocketServer("localhost",12345);$master = new MyWebSocketServer("localhost",12345);
WebSockets instead of AJAX (server side)WebSockets instead of AJAX (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
Creation of the WebSocket on the server
This is the code of mywebsocketserver.php.
We can launch it with php q mywebsocketserver.php
Creation of the WebSocket on the server
94
Then on procedures_retrieve.php there must be the function server_function() that the client wants to call and which will return something:
function server_function($req) {function server_function($req) {……return $msg;return $msg;
}}
WebSockets instead of AJAX (server side)WebSockets instead of AJAX (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
95
With the WebSockets approach we can handle our example of retrieving the number of users currently registered, without the drawbacks of the long polling approach. This is the client side code:
var ws;var ws;function retrieve_numusers() {function retrieve_numusers() {
var data2send= {var data2send= {'func': 'retrieve_numusers''func': 'retrieve_numusers'
};};ws.send(JSON.stringify(data2send));ws.send(JSON.stringify(data2send));
}}$(document).ready(function(){$(document).ready(function(){
ws = new WebSocket("ws://localhost:12345");ws = new WebSocket("ws://localhost:12345");ws.onopen = function () {ws.onopen = function () {
ws.send("\r\r"); //to avoid the first message bugws.send("\r\r"); //to avoid the first message bugretrieve_numusers();retrieve_numusers();
};};ws.onmessage = function(msg) {ws.onmessage = function(msg) {
if(!isFinite(msg.data)) alert("Error! Please retry!");if(!isFinite(msg.data)) alert("Error! Please retry!");else $('#numusers').text(JSON.parse(msg.data));else $('#numusers').text(JSON.parse(msg.data));
};};ws.onclose = function () {ws.onclose = function () {};};
});});
WebSockets example (client side)WebSockets example (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
96
Maybe you expected some behaviors similar to the long polling case, but they are not necessary anymore:
We call retrieve_numusers() only in the onopen() function, since the function executed server side doesn't need anymore to finish after having returned a value (unlike in AJAX and Comet), so it will execute forever and there is no need to care about a recall
We don't pass the previous value anymore when we call the server: since the server side function doesn't end after having sent a value, it can keep the last number got from the database and see if changes occur, without the need to get that value from the client
WebSockets example (client side)WebSockets example (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
97
On the server side, when calling the function present in procedures_retrieve.php, we have to pass it also the current object and the variable $user, because transmission has to be done within the function, we will see why later
include "websocket.class.php";include "websocket.class.php";require_once ”procedures_retrieve.php”;require_once ”procedures_retrieve.php”;class MyWebSocketServer extends WebSocket{class MyWebSocketServer extends WebSocket{
function process($user,$msg) {function process($user,$msg) {$this->say("< ".$msg); //enable only to see what arrives to the server$this->say("< ".$msg); //enable only to see what arrives to the server$msg_dec=json_decode($msg,true);$msg_dec=json_decode($msg,true);if(is_array($msg_dec)) {if(is_array($msg_dec)) {
$func = $msg_dec['func'];$func = $msg_dec['func'];if (function_exists($func)) {if (function_exists($func)) {
$res=json_encode($func($msg_dec,$res=json_encode($func($msg_dec,$this,$user$this,$user));));}}else {else {
$res=json_encode(array ($res=json_encode(array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}$this->send($user->socket,$res);$this->send($user->socket,$res);
}}}}
}}$master = new MyWebSocketServer("localhost",12345);$master = new MyWebSocketServer("localhost",12345);
WebSockets example (server side)WebSockets example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
Creation of the WebSocket on the server
We are passing also the current object and the
variable $user
98
In AJAX and in Comet the server function had to end after having sent a value, now it's not necessary anymore: the function can send a message with the new value and continue executing
So it will handle the old value and there is no need to get it from the client anymore
Anyway, we have to send the message from within the function, that's why we have as input parameters also the websocket server and the variable $user
So in this case the line $this->send($user->socket,$this->send($user->socket,$res) $res) in mywebsocketserver.php is not necessary, but we leave it in that it could be needed for other server functions
This is the function retrieve_numusers():
WebSockets example (server side)WebSockets example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
99
function retrieve_numusers($req,$wsserver,$user) {function retrieve_numusers($req,$wsserver,$user) {set_time_limit(0); //no timeoutsset_time_limit(0); //no timeouts$old_num=-1;$old_num=-1;while(true) { //the function never endswhile(true) { //the function never ends
$conn=mysql_connect("localhost","root","") or die $conn=mysql_connect("localhost","root","") or die ("<br />Error in the database connection " . ("<br />Error in the database connection " . mysql_error($conn));mysql_error($conn));mysql_select_db("example", $conn); mysql_select_db("example", $conn); $query="SELECT surname FROM user";$query="SELECT surname FROM user";$res=mysql_query($query);$res=mysql_query($query);$num=mysql_num_rows($res);$num=mysql_num_rows($res);if($num!=$old_num) {if($num!=$old_num) {
$res=json_encode($num);$res=json_encode($num);$wsserver->send($user->socket,$res);$wsserver->send($user->socket,$res);$old_num=$num;$old_num=$num;
}}}}
}}
WebSockets example (server side)WebSockets example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
100
WebSockets provide a richer protocol to perform bi-directional, full-duplex communication, useful for things like games, messaging apps and for cases where you need near real-time updates in both directions.
However, in some scenarios data doesn't need to be sent from the client, you simply need updates from some server action (for example friends' status updates, stock tickers, news feeds)
Server-Sent Events (SSE) is another possible alternative which comes from HTML5
The original API was created by Opera in 2006 and is used for pushing events from the server to the client.
HTML5: Server-Sent Events (SSE)HTML5: Server-Sent Events (SSE)
Giacomo Fazio - 2011Giacomo Fazio - 2011
101
The client cannot send messages to the server, it can only listen for messages.
Like for WebSockets, the SSE approach opens a persistent connection to the server, which sends data to the client when new information is available, eliminating the need for polling or Comet techniques and their overhead
SSEs are sent over traditional HTTP. So no need for a special protocol or server implementation
Moreover they have been designed to be efficient SSE have a variety of features that WebSockets lack
by design such as automatic reconnection, event IDs, and the ability to send arbitrary events.
So they could be a good tradeoff between AJAX/Comet and the WebSockets
HTML5: Server-Sent Events (SSE)HTML5: Server-Sent Events (SSE)
Giacomo Fazio - 2011Giacomo Fazio - 2011
102
As for WebSockets, new APIs have been defined for SSE
We have to use a browser which supports them: currently they are supported and enabled in new
versions of Chrome, Opera and Safari. they will be surely supported in the future by Firefox
The client side code can be written in JavaScript / jQuery.
The main thing is the object EventSource, we have to give it a URL on the server when we build it
As for WebSockets, we’ll be using three events: onopen: When the connection has been created onmessage: When a message has been received onclose: When the connection has been closed
HTML5: SSE (client side)HTML5: SSE (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
103
Example:
$(document).ready(function() {$(document).ready(function() {var source = new EventSource('http://localhost/server.php');var source = new EventSource('http://localhost/server.php');
source.onmessage = function (event) {source.onmessage = function (event) {alert(event.data);alert(event.data);
};};
source.onopen = function (event) {source.onopen = function (event) {alert("Connected...");alert("Connected...");
};};
source.onerror = function (event) {source.onerror = function (event) {alert("Error!");alert("Error!");
};};});});
HTML5: SSE (client side)HTML5: SSE (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
104
On server side (file server.php) nothing changes, since we use the normal HTTP protocol
If the server has to give the client a response, this must contain a "data:" line, followed by the message, followed by two "\n" characters:
header("Content-Type: text/event-stream");header("Content-Type: text/event-stream");header('Cache-Control: no-cache');header('Cache-Control: no-cache');set_time_limit(0); //no timeoutsset_time_limit(0); //no timeoutsob_implicit_flush(); //to avoid explicit calls to flush()ob_implicit_flush(); //to avoid explicit calls to flush()echo "data: Hello!\n\n"; //message from the serverecho "data: Hello!\n\n"; //message from the server
HTML5: SSE (server side)HTML5: SSE (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
105
SSE can be used for many things, but in this document we are interested in using them to substitute AJAX and in particular Comet
We would like to use the usual approach (rpc.php and procedures_retrieve.php), because for example we are using it with AJAX and Comet on our website and we want a tidy solution without many files.
But how can we do, since with SSE client can't send messages to the server and so it can't specify the function to execute? Actually it can, when the object EventSource is created, by using GET
We can also specify other parameters when using GET and we can use JSON to send objects
$(document).ready(function() {$(document).ready(function() {var url='http://localhost/example_eventsource/rpc.phpvar url='http://localhost/example_eventsource/rpc.php?func=function1?func=function1';';var source = new EventSource(url);var source = new EventSource(url);
source.onmessage = function (event) {source.onmessage = function (event) {alert(JSON.parse(event.data));alert(JSON.parse(event.data));
};};});});
SSE instead of AJAX (client side)SSE instead of AJAX (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
106
The file rpc.php is a bit modified, since it must take the message from the server and send it after having formatted it in the correct way
require_once 'procedures_retrieve.php';require_once 'procedures_retrieve.php';$func = $_REQUEST['func'];$func = $_REQUEST['func'];if (function_exists($func)) {if (function_exists($func)) {
header('Content-Type: text/plain; charset=utf-8');header('Content-Type: text/plain; charset=utf-8');$ret=json_encode($func($_REQUEST));$ret=json_encode($func($_REQUEST));
} } else {else {
$ret=json_encode(array ($ret=json_encode(array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}print "data: $ret\n\n";print "data: $ret\n\n";
On procedures_retrieve.php there must be function1(), for example:
function function1($req) {function function1($req) {header("Content-Type: text/event-stream");header("Content-Type: text/event-stream");header('Cache-Control: no-cache');header('Cache-Control: no-cache');set_time_limit(0); //no timeoutsset_time_limit(0); //no timeoutsob_implicit_flush(); //to avoid explicit calls to flush()ob_implicit_flush(); //to avoid explicit calls to flush()return "Hello!"; //message from the serverreturn "Hello!"; //message from the server
}}
SSE instead of AJAX (server side)SSE instead of AJAX (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
Values in GET are in $_REQUEST and are passed to the function
107
With the SSE approach we can handle our example of retrieving the number of users currently registered, without the drawbacks of the long polling approach. This is the client side code:
$(document).ready(function() {$(document).ready(function() {var url='http://localhost/example_eventsource/rpc.phpvar url='http://localhost/example_eventsource/rpc.php?func=retrieve_numusers?func=retrieve_numusers';';var source = new EventSource(url);var source = new EventSource(url);
source.onmessage = function (event) {source.onmessage = function (event) {$('#numusers').text(JSON.parse(event.data));$('#numusers').text(JSON.parse(event.data));
};};});});
As for WebSockets, we call the server function retrieve_numusers() only once, since it doesn't need anymore to finish after having returned a value, so it will execute forever and there is no need to care about a recall
We don't pass the previous value anymore when we call the server: since the server side function doesn't end after having sent a value, it can keep the last number got from the database and see if changes occur, without the need to get that value from the client
HTML5: SSE example (client side)HTML5: SSE example (client side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
108
We are in a particular case: since the server function will execute forever, it will never use the JSON encoding and return part of rpc.php, so it makes no sense to use a different rpc.php, we can use the usual rpc.php that we already use for AJAX functions:
require_once 'procedures_retrieve.php';require_once 'procedures_retrieve.php';$func = $_REQUEST['func'];$func = $_REQUEST['func'];if (function_exists($func)) {if (function_exists($func)) {
header('Content-Type: text/plain; charset=utf-8');header('Content-Type: text/plain; charset=utf-8');print json_encode($func($_REQUEST));print json_encode($func($_REQUEST));
} } else {else {
print json_encode(array (print json_encode(array ('status' => '404','status' => '404','func' => $func'func' => $func
));));}}
HTML5: SSE example (server side)HTML5: SSE example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
not used
109
This is our function in procedures_retrieve.php:
function retrieve_numusers($req) {function retrieve_numusers($req) {header("Content-Type: text/event-stream");header("Content-Type: text/event-stream");header('Cache-Control: no-cache');header('Cache-Control: no-cache');set_time_limit(0); //no timeoutsset_time_limit(0); //no timeoutsob_implicit_flush(); //explicit calls to flush() will no longer be neededob_implicit_flush(); //explicit calls to flush() will no longer be needed$old_num=-1;$old_num=-1;while(true) {while(true) {
$conn=mysql_connect("localhost","root","");$conn=mysql_connect("localhost","root","");mysql_select_db("example", $conn); mysql_select_db("example", $conn); $query="SELECT surname FROM user";$query="SELECT surname FROM user";$res=mysql_query($query);$res=mysql_query($query);$num=mysql_num_rows($res);$num=mysql_num_rows($res);if($num!=$old_num) {if($num!=$old_num) {
$msg=json_encode($num);$msg=json_encode($num);echo "data: $msg\n\n";echo "data: $msg\n\n";$old_num=$num;$old_num=$num;
}}}}
}}
■ As for WebSockets, the function will run forever, it can send a message with the new value and continue executing
■ So it will handle the old value and there is no need to get it from the client
HTML5: SSE example (server side)HTML5: SSE example (server side)
Giacomo Fazio - 2011Giacomo Fazio - 2011
110
■ Aptana is an IDE (Integrated Development Environment). It can be used to create websites and Web applications.
■ It's released under the GNU open source license: it can be downloaded and used free of charge.
■ Aptana can be used to create simple websites or complex web applications. It has got a quality and a quantity of features that allow it to be a valid alternative to commercial softwares like Dreamweaver.
■ It's based on Eclipse and PDT (PHP Development Tools).■ It can be downloaded as a standalone tool or as a plugin for Eclipse■ It's cross-platform■ You can find a good guide (in Italian) on
http://editor.html.it/guide/leggi/193/guida-aptana/■ Other tutorials are present on the Aptana website,
http://docs.aptana.com/docs/index.php/Aptana_Tutorials
Aptana StudioAptana Studio
Giacomo Fazio - 2011Giacomo Fazio - 2011