jeudi 23 août 2012

Basic JavaScript - Browser Events

This post corresponds to notes taken while reading Eloquent JavaScript.

Event handling is a powerfull tool that allows to execute some interesting actions after the occurrence of a given events. As JavaScript is single-threaded, only one event can be handled at time.
If no actions is registered for an event then this one is bubbled through the DOM tree. For example, if a user clik on a link and no event handler is registered for this then the event will be forwarded to the link parent (e.g. paragraph element) until document.body.
For handling events, someone should:
  1. Register an event handler by setting an element's onclick (or onkeypress, etc.) property. If someone need more than one handler then use addEventListener function. This later needs boolean parameter to indicate event 'bubble' through the DOM tree as normal when false.
  2. Get the event object than can be passed to the handler as a local variable 'event' or stored in the top-level variable window.event. This code event || window.event can be used to get the event object.
  3. Extract information from the event object such as the source element that can be find in the srcElement or target event property, also the precise corrdinates of a click are available in clientX and clientY properties. pageX and pageY properties are usefull when the document is scrolled, document.body.scrollLeft and document.body.scrollTop tells how many in pixels the document has been scrolled.
  4. Signal the event handling.
Example:
// register a handler for 'onclick' event
$('button').onclick = function() {console.log("Click !");};

$('button').addEventListener("click", function() {console.log("Click !");}, false);

// unregister a handler for 'onclick' event
$('button').removeEventListener("click", function() {console.log("Click !");}, false);
 Example of common events that can be registered for:
  • load is a window event that fires when the document is fully loaded.
  • onunload fires when leaving a page
  • click/dbclick fires when user click or double click on an element
  • mousedown, mouseup
  • mousemove fires whenever the mouse moves while it is over a given element.
  • mouseover and mouseout fires when the mouse enters or leaves a node/element.
  • focus and blur are fired on elements that can be focused (e.g. input) when the element has focus or the focus leaves the element.
  • change is fired when the node content changed (e.g. input).
  • submit is a form event fired when the form is submitted.
  • resize fired when window is resized.
The target or srcElement property points to which node the event is fired for, while relatedTarget or toElement or fromElement property gives which node the mouse came from.

Key related events:
  • keydown and keyup are used when someone is interested in which key was pressed (e.g. arrow keys).
  • keypress to be used when someone interested in the typed character.
The event property keyCode/charCode tells the code to identify the key (for mouseup) or character (for keypress). String.fromCharCode can be used to convert the charCode to a string. The properties shiftKey, ctrlKey and altKey tells whether the shift, control or alt key were held during the key/mouse event.

To control event bubble use stopPropagation (or 'cancelBubble' in IE) property.

mercredi 22 août 2012

Basic JavaScript - Document-Object Model (DOM)

This post corresponds to notes taken while reading Eloquent JavaScript.

HTML tags are organized in a tree object called DOM in order to be accessible from JavaScript code. The links in the tree are properties of node:
  • parentNode property refers to the object container of the current node
  • childNodes property refers to a pseudo-array that stores the children of the node
  • firstChild and lastChild refers to the first and last child, or null where there are no children.
  • nextSibling and previousSibling refers to the nodes sitting next or before the current node, these nodes have same parent node as the current one.
Example:
console.log(document.body);
console.log(document.body.parentNode);
console.log(document.body.childNodes.length);
console.log(document.documentElement.firstChild);
console.log(document.documentElement.lastChild);
console.log(document.body.previousSibling);
console.log(document.body.nextSibling);
There are two types of nodes: HTML tags and simple text. Node type can be found by checking the nodeType property which may has different values:
- 1 for regular nodes
- 3 for text nodes
- 9 for document object
Example:
function isTextNode(node) {
 return node.nodeType == 3;
}
console.log(isTextNode(document.body));
Regular nodes have the nodeName property (which is always capitalized, e.g. "IMG") to store the HTML tag type, while text nodes have the nodeValue that contains the text content.

The innerHTML property gives the HTML text inside the node without the node tag, while the outerHTML property (supported by some browsers) include the node itself.
Example:
document.body.firstChild.innerHTML = "bla bla";
An alternative to access a node via tree traversal is to use the document object property getElementById and indicating the node identifier (value of the 'id' attribute), or call it directly with $. In addition, all DOM nodes have the getElementsByTagName property that returns an array of all nodes with a given tag name.
Example:
var picture1 = document.getElementById("picture1");
var picture2 = $("picture2");
console.log(document.body.getElementsByTagName("H1")[0]);
Nodes can be created dynamically thanks to the document methods createElement to create regular node and createTextNode to create text node. All nodes have an appendChild method to add an element to a node. To insert a node before another one use the parent insertBefore mehod. To replace a node with another one or remove it from its parent use replaceChild and removeChild methods.
Example:
var secondHeader = document.createElement("H1");
var secondTitle = document.createTextNode("Chapter 2: Deep magic");
secondHeader.appendChild(secondTitle);
document.body.appendChild(secondHeader);
New attributes can be added to a node by using its method setAttribute or directly as a node property. Node's attribute can be accessedd as a property of the DOM node or via getAttribute.
Example:
var newImage = document.createElement("IMG");
newImange.setAttribute("src", "img/Alto.png");
document.body.appendChild(newImage);
console.log(newImage.getAttribute("src"));
The style property refers to the CSS style object of a node. Example:
$("picture").style.borderColor = "green";
$("picture").style.display = "none";
$("picture").style.position = "absolute";
$("picture").style.width = "400px";
$("picture").style.height = "200px";

Basic JavaScript - Web programming

This post corresponds to notes taken while reading Eloquent JavaScript.

The open method of the window object takes an URL argument that will open on a new window. An opened window can be closed with its close method. To escape unwanted characters in the URL (e.g. space), the encodeURIComponent method can be used. To remove them again use decodeURIComponent method.
Every window object has a document property that contains the document shown in that window. To force the browser to load another document, someone can set the document.location.href property.
Example:
var perry = window.open("http://www.pbfcomics.com");
// show some information about the URL of the document
console.log(document.location.href);
perry.close();
// encoding URL
var encoded = encodeURIComponent("aztec empire");
console.log(encoded);
The document object has a property named forms which contains links to all the forms in the document. Example, if a form has a property name="userinfo" then it can be accessed as a propery named userinfo.
The object for the form tag has a property elements that refers to an object containing the fields of the form by their name.
Example:
var userForm = document.forms.userinfo;
console.log(userForm.method);
console.log(userForm.action);
// set the content (via the value property) of a text input element called 'name'
var nameField = userForm.elements.name;
nameField.value = "Eugène";


mardi 21 août 2012

HTML5 WebSocket API

One of the new features coming with HTML5 is the WebSocket API that provides a full-duplex communication channel through a single socket over the web. This piece of technology eables ease of integration of asynchronous/real-time features to web applications.
Before being able to use (send and receive) this API, the WebSocket client should initiate a handshake with the WebSocket server by creating a new WebSocket object and providing the server URL with ws:// or wss:// prefix to indicate WebSocket or a secure WebScoket connection.

At the client side, the WebSocket interface consists of the following methods:
  • onopen(event) called when the connection is successfully opened
  • onmessage(event) called when a message is received from the remote endpoint 
  • onclose(event) called when the connection is closed by the remote endpoint 
  • send(message) used to send data 
  • close() used to close an opened connection
Example:
//Checking for browser support
if(window.WebSocket) {
 Alert("WebSocket is supported by your web browser.");
 // create a new WebSocket object to connect to the server
 var url = "ws://localhost:8080/echo";
 var ws = new WebSocket(url);
 // Adding liseners for connection opened, message received and connection closing events
 ws.onopen = function() {
  log("connection opened");
  // sending a message
  ws.send("thank you for accepting this websocket request");
 };
 ws.onmessage = function(e) {
  log("received message: "+e.data);
 };
 ws.onclose = function(e) {
  log("connection closed");
 };
}else {
 Alert("WebSocket is not supported by your web browser.");
}

There are many server-side implementations for WebSocket, here is few ones:
  • Netty a Java network framework that includes WebSocket support
  • Jetty Application Server provides a support for WebSocket
  • Node.js multiple WebSocket server implementations for this server-side JavaScript framework.

Next are the steps that should be followed to embed jetty and use it as a WebSocket Server: first, use tomcat as an application server. Second, add jetty jars to a Dynamic Web Application project. Third, implement a ServletContextListener and declare it into the web.xml file to listen to the web applicaion start-up event to launch the WebSocket server and to shut it down at application destruction. Fourth, Create a handler that implements the server-side of the WebSocket API (which is similar to the client-side) to deal with exchanged messages of the websocket protocol.

Jetty provides multiple interfaces for the WebSocket API that may be used for different purposes, org.eclipse.jetty.websocket.WebSocket is an example of an implementation of WebSocket for exchaging strings.

Here is a code snaphot for starting a jetty-based WebSocket server:
// 1) Create a Jetty server with the 8091 port.
Server server = new Server(8081);
// 2) Register SingalingWebSocketHandler in the Jetty server instance.
MyWebSocketHandler wsHandler = new MyWebSocketHandler();
wsHandler.setHandler(new DefaultHandler());
server.setHandler(wsHandler);
// 2) Start the Jetty server.
server.start();

To shutdown the WebSocket server:
server.stop();
A complete example of how using WebSocket API can be found here.

jeudi 12 juillet 2012

WebRTC: an introduction

WebRTC brings webcam access, p2p, and rich audio/video communication capabilities to the browser. In this talk, we'll give an overview of the WebRTC technologies available today, show how to build WebRTC apps, and discuss the potential this technology adds to the Web Platform.
With more than 10 years experience in audio/video communication, Justin Uberti is a tech lead on Chrome WebRTC team, he was behind Google+ Hangouts, Google Video Chat, and Gmail Call Phone. During Google I/O 2012, Justin gave a great talk explaining the features of WebRTC.

vendredi 6 juillet 2012

Jinja4j a template engine for Java

ANTLR is a powerfull tool for constructing recognizers, interpreters, compilers, and translators from grammatical descriptions containing actions in a variety of target languages. An important feature of ANTLR is that it has a sophisticated grammar development environment called ANTLRWorks that helps a lot when debugging grammars.

I tried to get started with ANTLR by building a Jinja-like template engine for Java which I called Jinja4j. Jinja is one of the most used template engines for Python. It extends Django's templating system with an expressive language that gives template authors a more powerful set of tools. On top of that it adds sandboxed execution and optional automatic escaping for applications where security is important.
The Jinja4j grammar can be found here. The project is open source, any pull requests for imporving the template engine are welcome. Code source can be found at github.

Debugging with ANTLRWorks

When working with the grammar under ANTLRWorks I was getting in the console erros like NoViableAltException and "no start rule (no rule can obviously be followed by EOF)". When I googled the error message, I found an intersting post explain that the problem. In fact Antlr was trying to identify the "start" rules (ones that can end with EOF) by looking for rules that are not used anywhere else in the grammar. So if you have recursion on the "start" rule ANTLR will promot NoViableAltException and the debug will fail. An thus, I added this rule page : html EOF; to fix the problem.

Another kind of problems I was getting is mismatch errors. This happens when for a given input word there are more than one possible token that can be created. Antlr prompt the identifiers of mismatched tokens that can be found in output/gramar_name.tokens file.

mardi 3 juillet 2012

Using Speech Input API

The Android SDK provides support for an easy integration of speech input into native applications. We need just to send out an intent RecognizerIntent (no permission is required) to call any available voice recognition service in the phone (e.g. Google Voice, Nuance Dragon API for mobile). Then, a list of recognized word is send back to the application which can capture them in the onActivityResult method.