Friday, December 08, 2006

AJAX pour SVG

En complément à un-zeste-de-svg-ajax-et-rex.html, on peut se poser la question du support de XmlHttpRequest par les différents navigateurs.

Plusieurs projets proposent des librairies Javascript pour améliorer le support XML/XSLT dans les navigateurs.

Je ne ferais que mentionner ici deux projets significatifs:
- Sarissa: http://sarissa.sourceforge.net/
- Google: http://goog-ajaxslt.sourceforge.net/

Friday, October 06, 2006

Quel avenir pour SVG?

Adobe a annoncé ne plus assurer de support pour son Viewer SVG (ASV) à partir de janvier 2007 et ne plus le distribuer à partir de janvier 2008. Hors ASV était jusqu'à présent le plus utilisable et le plus utilisé des viewers SVG.

Je ne reviendrais pas en détail ici de la place importante que prend SVG dans les téléphones mobiles, où une très grosse partie des modèles qui sortent comportent un player SVG (notons par exemple que Nokia recommande aux développeurs d'applications pour téléphone de concevoir leurs interfaces en graphique vectoriel SVG).

De nombreux concepteurs d'applications Web se demandent s'ils peuvent encore s'appuyer sur SVG. Sans ASV, il apparait difficile d'afficher du SVG dans Internet Explorer. Si on peut se passer d'Internet Explorer et promouvoir Firefox, la situation parait favorable, mais encore très problématique: en effet, le support SVG de firefox ne permet pas actuellement d'imprimer correctement les documents et le plan de travail ne prévoit pas de résoudre ce problème à court terme (http://developer.mozilla.org/en/docs/SVG_in_Firefox_1.5#Printing). Peut-on encore compter sur SVG?

D'abord, on peut espérer que Firefox résolve ses problèmes. Ensuite, d'autres solutions émergent qui pourraient prendre une place laissée par Adobe. Par exemple, le player multimédia Osmo4 -qu'on trouve dans le projet GPAC sur sourceforge, http://gpac.sourceforge.net/- a été récemment décliné sous forme d'un plug-in pour Firefox (Osmozilla) et d'un plug-in pour Internet Explorer.

SVG se développe fortement sur mobiles, ASV est encore là pour quelques temps et la relève est sur les starting blocks, alors ce n'est pas le moment d'abandonner une bonne technologie sans équivalent: le graphique vectoriel dans un environnement ouvert.

Thursday, July 20, 2006

Un zeste de SVG, Ajax et REX

(c) Jean-Claude Moissinac - ENST Juin 2006

Résumé

Dans cette note, je présente une implémentation de REX pour modifier dynamiquement des documents SVG à l'aide de XmlHttpRequest popularisé par AJAX. REX est une grammaire XML simple, proposée par le W3C (http://www.w3.org/TR/rex/) en février 2006, qui permet de décrire des modifications qu'on veut apporter à un document XML: insertion, remplacement ou suppression de sous-arbre, et changement d'attributs. Grâce à cette implémentation, avec très peu de code Javascript, on peut faire toutes sortes de manipulation d'une page graphique SVG par des commandes issues d'un serveur.

ATTENTION: le paragraphe 'les problèmes avec REX' vers la fin de cette note contient un avertissement potentiellement important pour les développeurs qui utilisent AJAX

Abstract
In this article, I present a REX implementation to modify dynamically SVG documents by means of the XmlHttpRequest function popularized by AJAX. REX is a simple XML grammar, proposed by the W3C (http://www.w3.org/TR/rex/) in February, 2006, which allows to describe modifications which we want to bring to an XML document: insertion, replacement or deletion of a sub-tree, and change of attributes. Thanks to this implementation, with a short piece of Javascript, we can make many transformation of a graphic SVG page by commands obtained from a server.

An english version of this article is available:
http://svgmpeg4.blogspot.com/2006/06/taste-of-rex-ajax-and-svg.html

ATTENTION: the end of this note contains a warning potentially important for the developers which use AJAX

SVG


SVG signifie Scalable Vector Graphics. Il s'agit d'une grammaire XML, définie par le W3C, qui permet de décrire des documents graphiques, éventuellement animés et interactifs, souvent perçu comme un concurrent de Flash. Nous verrons d'ailleurs dans une prochaine note comment les techniques proposées ici permettent d'exploiter une pratique assez courante des développeurs Flash: envoyer une scène graphique initiale presque vide et la compléter ensuite progressivement en fonction des préférences et des interactions de l'utilisateur, du navigateur utilisé, de la taille de la fenêtre...

De nombreux développeurs ont développé au cas par cas leur propre code javascript pour modifier des scènes SVG; nous allons voir ci-après qu'avec très peu de code, on peut avoir une solution générique.


AJAX


Ajax a popularisé, en lui donnant un nom, la méthode de développement de sites Web dynamiques basée notamment sur l'utilisation par script de la fonction XMLHttpRequest pour récupérer les données permettant de modifier une page sans la recharger (voir par exemple http://www.adaptivepath.com/publications/essays/archives/000385.php). Une pratique courante consiste à demander au serveur un morceau de page HTML à l'aide de XMLHttpRequest et à l'injecter dans la page courante par simple copie. Cela procure une méthode extrêmement souple et légère pour la réalisation de pages dynamiques.

Cette façon de travailler s'applique aussi à des documents SVG. Dans le cas des navigateurs qui supportent l'utilisation d'éléments HTML et SVG dans une même page, on peut même manipuler à la fois le HTML et le SVG par cette méthode; c'est le cas, par exemple, avec les versions courantes du navigateur Firefox.


REX, brève introduction

La proposition faite pat le W3C est courte et claire. On peut la trouver à l'adresse http://www.w3.org/TR/rex/. REX signifie Remote Events for XML.

REX utilise une sous-partie de la syntaxe Xpath pour désigner la portion de l'arbre XML que l'on souhaite modifier. Cette sous-partie est simple à comprendre, proche de la description d'un chemin dans une arborescence de dossiers. Par exemple:
/ désigne la racine du document
/svg/g[3] désigne le troisième élément g directement trouvé comme fils de la racine du document svg (rem.: en svg, g permet de grouper des éléments).
id('bouton1') désigne le noeud de l'arbre ayant l'identificateur (id) bouton1
id('boutons1')/@fill désigne l'attribut fill de l'élément d'identificateur bouton1

On le devine à travers ces exemples, la syntaxe est vite assimilable, au moins pour les utilisations les plus courantes.

Une fois que nous savons désigner la partie du document à modifier, voilà quelques exemples simples de modifications possibles:

<rex xmlns="http://www.w3.org/2006/rex" >
<event target="id('S1')/svg:path[13]" name="DOMNodeRemove">
</rex xmlns="http://www.w3.org/2006/rex" >

name contient le nom de la commande exécutée, ici DOMNodeRemove sert à supprimer un noeud; dans cet exemple, on supprime donc le treizième noeud path (et son sous-arbre éventuel) trouvé sous l'élément d'identificateur S1.
_________________________________________________

<event target="id('S1')/svg:text[1]/@fill" name="DOMAttrModified" newvalue="blue">

Ici, je ne montre que la ligne centrale changée par rapport au message précédent. DOMAttrModified indique qu'on modifie une valeur d'attribut. L'attribut est l'indication de couleur de remplissage (fill) attribuée au premier noeud text trouvé sous un élément d'identificateur S1; la nouvelle valeur donnée à cet attribut est blue
_________________________________________________

<event target="id('S1')/svg:text/text()" name="DOMCharacterDataModified" newvalue="Texte changé">

DOMCharacterDataModified indique qu'on modifie le contenu textuel du premier élément text trouvé sous l'élément d'identificateur S1; la nouvelle valeur est Texte changé
_________________________________________________

Il est possible de groupe plusieurs modifications:
<rex xmlns="http://www.w3.org/2006/rex" >
<event target="id('S1')/svg:path[13]" name="DOMNodeRemove">
<event target="id('S1')/svg:text[1]/@fill" name="DOMAttrModified" newvalue="blue">
<event target="id('S1')/svg:text/text()" name="DOMCharacterDataModified" </rex xmlns="http://www.w3.org/2006/rex" >

Les trois modifications précédentes sont groupées dans un seul message REX.

Pour plus de précisions, le mieux est surement de regarder les 15 pages de la proposition du W3C.

_________________________________________________
_________________________________________________

Implémentation en Javascript

La première chose à faire pour implémenter REX est de disposer de méthodes pour trouver un noeud dans un document à partir d'une expression XPATH supportée par REX. Comme j'avais
connaissance de l'implémentation Open Source de XPATH en Javascript effectuée par Google (voir http://goog-ajaxslt.sourceforge.net/), et que je voulais l'évaluer, j'ai commencé par cette solution. J'y reviendrais surement dans une autre note.

Ensuite, j'ai considéré que Firefox assurant à la fois un support de SVG et de XPATH , il était intéressant d'étudier cette solution. C'est elle que nous allons d'abord commenter du fait de l'élégance et de la compacité qu'elle autorise: la totalité du support de REX pour des documents utilisés avec Firefox prend environ 200 lignes de code Javascript.

La démonstration peut être vue à l'adresse suivante:
http://shadok.enst.fr:8080/modifxml/purMozilla/index.htm

Le code REX utilisé dans l'exemple:
http://shadok.enst.fr:8080/modifxml/purMozilla/commandeRex.html

Le code Javascript pour exécuter les commandes REX:
http://shadok.enst.fr:8080/modifxml/purMozilla/rexfox.js

Le document SVG utilisé dans l'exemple:
http://shadok.enst.fr:8080/modifxml/frame1.svgm
_________________________________________________

Note: les attributs position et timeStamp des commandes REX ne sont pas traités pour l'instant; position va être rapidement rajouté; timeStamp me parait encore insuffisament défini dans le cas général de modifications de documents XML, mais je crois pouvoir en faire une implémentation pour SVG.
_________________________________________________

Obtention de l'objet XMLHttpRequest


function getHTTPObject() {
var xmlhttp;
if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
{
try { xmlhttp = new XMLHttpRequest(); }
catch (e) { xmlhttp = false; }
}
return xmlhttp;
}

Je ne commenterai pas ces 9 lignes de code et renverai aux nombreux tutoriels sur Ajax qu'on peut trouver par exemple à partir de http://en.wikipedia.org/wiki/AJAX.

Nous supposerons que la fonction précédente a permis de récupérer un objet nommé xmlupdater.

XMLHttpRequest n'est pas standardisée. On trouve cependant sur le Web diverses techniques pour utiliser des objets équivalents avec Firefox et Internet Explorer. Le W3C travaille à la normalisation de ce type de technique dans le groupe de travail WEB API (voir http://www.w3.org/2006/webapi/).
_________________________________________________

Obtention de la liste de commande à exécuter

Nous supposons que les commandes sont fournies par un serveur et que d'autres éléments de la page en cours de modification permettent de déterminer l'URL du message REX à exécuter.

L'envoi de la demande de mise à jour depuis le document nécessite les 6 lignes de code suivantes:
function sendRequest(urlcommand)
{
xmlupdater.open("GET", urlcommand);
xmlupdater.onload = handleRexResponse;
xmlupdater.send(null);
}

La gestion spécifique d'une réponse composée d'un message REX est gérée par la fonction handleRexResponse.
_________________________________________________

Exécution du message REX


Cette exécution représente environ 50 lignes de code pour interpréter le message REX et appeler les fonctions qui exécutent les modifications proprement dites. le code complet est accessible sur le site de démonstration.

Par exemple, DOMNodeRemove conduit déterminer le noeud visé à l'aide de la fonction nodesetFromPath, puis à l'appel de la fonction removeNode; c'est à dire la séquence de code suivante:

if(commandType == "DOMNodeRemove")

{

pointedSet = nodesetFromPath(ru.doc, ru.nsResolver, target);

for (var k = 0; k < pointedSet.snapshotLength; k++) {

removeNode(pointedSet.snapshotItem(k));

}

}



Obtenir un ensemble de noeuds à partir d'un xpath

J'ai mentionné dans le paragraphe précédent la fonction nodesetFromPath.
Elle est définie de la façon suivante:
function nodesetFromPath(doc, resolver, target)
{
return ret = doc.evaluate( target, doc, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
}


target est la chaîne de caractère représentant le xpath de l'objet ciblé
doc est la référence du document XML dans lequel on cherche
resolver est une fonction de résolution de namespace (voir ci-dessous)

La méthode evaluate de l'objet doc est une méthode définie dans l'implémentation Javascript de Firefox.

resolver est la référence à une fonction qui permet d'associer un préfixe d'espace de nommage à une chaîne de caractère, pour assurer la réslution des espaces de nommage. Dans le cas de notre exemple, où du SVG est contenu dans du HTML, la fonction est définie comme suit:
function nsResolver(prefix) {
var ns = {
'xhtml' : 'http://www.w3.org/1999/xhtml',
'svg': 'http://www.w3.org/2000/svg'
};
return ns[prefix] || null;
}
_________________________________________________
_________________________________________________

Les problème avec REX

Le premier problème posé par REX est qu'il s'agit de XML. Donc:
- c'est ralativement verbeux,
- c'est un codage textuel peu compact de l'information,
- c'est une technologie inadaptée pour le streaming.

Ces deux problèmes n'ont rien de spécifique à REX et se posent pour l'ensemble des technologies qui s'appuient sur XML. Il faudra attendre les résultats des travaux sur le XML binarisé pour changer cette situation.

Cela n'enlève rien au fait que les propositions ci-dessus proposent une solution générique simple d'emploi pour faire évoluer une scène multimédia SVG A L'INITIATIVE D'ACTIONS SUR LE CLIENT. Il faut en effet que quelquechose -une interaction, un timer...- déclenche l'appel approprié à XMLHttpRequest. Nous verrons dans le prochain paragraphe qu'il existe au moins une solution qui donne l'initiative au serveur.

Le deuxième problème est d'ordre juridique. France Telecom revendique la possession de brevets qui empêcheraient la libre exploitation de REX. N'étant pas expert en brevet, je me limiterai à quelques commentaires sur les brevets en question et les technologies auxquelles ils semblent s'appliquer.

Les brevets que j'ai vu portent sur l'application de commandes de modification à une scène graphique représentée sur un écran. Les commandes prises en considération sont:
- insertion d'un nouvel élément dans la scène,
- modification d'un élément de la scène,
- suppression d'un élément de la scène.
Ces brevets ont été déposés lors de la définition de la technologie BIFS qui est une partie de MPEG-4 (voir http://gpac.sourceforge.net/tutorial/bifs_intro.htm).

Il apparait clairement que tous les documents multimédia peuvent être qualifiés de scènes graphiques. Peuvent être couverts par ce brevet les modifications de documents XHTML et Flash.

Nous voyons également que les commandes REX appliquées à du SVG semblent couvertes par ce brevet.

Les commandes ci-dessus sont les commandes de base de tout éditeur de document: insérer, modifier, supprimer. Si le brevet est valide, il semble que toute édition/modification de document multimédia soit couverte par ce brevet.

Je regretterais beaucoup de ne pas pouvoir utiliser REX et la méthode que j'ai proposée ci-dessus sans négocier des licences avec France Telecom, mais c'est le principe des brevets logiciels.

Je dois surtout mettre en garde tous les développeurs Ajax qui utilisent XMLHttprequest pour insérer ou modifier un morceau d'une page HTML: leur travail est probablement couvert par les brevets de France Telecom.

LASER, une vision complémentaire des scènes multimédia dynamiques

Nous avons vu ci-dessus un assemblage de technologies qui se prête bien à une utilisation simple sur le WEB, mais relativement peu performante. Nous allons introduire ici ce qui pourrait être un développement important de SVG.

SVG et REX sont des grammaires XML et donc des formats textuels.

Dans le cadre de MPEG-4, une application originale de SVG a été proposée sous le nom de LASER. Elle pourrait contribuer de façon significative au développement de l'utilisation de SVG en environnement mobile; son adoption par le 3GPP est envisagée.

En effet, en s'appuyant sur SVG, LASER introduit les possibilités suivantes:
- offrir une représentation compacte binaire de la scène SVG,
- permettre des commandes de modifications du types de celles présentées ci-dessus dans cet article,
- permettre de streamer l'envoi progressif, défini temporellement, de ces modifications.

Nous reviendrons dans une prochaine note sur cette technologie prometteuse.

Friday, June 23, 2006

A taste of REX, AJAX and SVG

(C) Jean-Claude Moissinac - ENST - June, 2006

Abstract

The purpose of this note is to present my implementation of REX to dynamically modify SVG documents via the XMLHttpRequest instruction, popularized by AJAX. REX is a simple XML grammar - proposed by the W3C in February 2006 - which allows us to describe modifications we want to bring to an XML document: insertion, replacement or deletion of a sub-document, and attributes change. Thanks to this implementation, with a little bit of JavaScript code, we can make any manipulation of a graphic SVG page through commands stemming from a server.

THANKS: to Berthele Rodriguez and Thierry Arbelot for useful reviews

Résumé
Dans cette note, je présente une implémentation de REX pour modifier dynamiquement des documents SVG à l'aide de XMLHttpRequest popularisé par AJAX. REX est une grammaire XML simple, proposée par le W3C en février 2006, qui permet de décrire des modifications qu'on veut apporter à un document XML: insertion, remplacement ou suppression de sous-arbre, et changement d'attributs. Grâce à cette implémentation, avec très peu de code Javascript, on peut faire toutes sortes de manipulation d'une page graphique SVG par des commandes issues d'un serveur.

Une version française de cet article se trouve à
http://svgmpeg4.blogspot.com/2006/07/un-zeste-de-rex-ajax-et-svg.html.

SVG

SVG means Scalable Vector Graphics. It is a XML grammar, defined by the W3C, which allows us to describe graphic documents, even animated and interactive. SVG is often perceived as a competitor of Flash. We shall see in a future note how techniques proposed here allow to use a common practice of Flash developers: send an almost empty initial graphic scene then gradually complete it according to the preferences and the interactions of the user, the navigator, the size of the window...

Numerous developers developed their own JavaScript code case by case in order to modify SVG; we shall see below that with a short JavaScript code, we can have a useful generic solution.

AJAX

By naming it, Ajax popularized the method of dynamic publishing Web sites based on the use of the XMLHttpRequest function to get back data via script, allowing to modify one page without reloading it. A common practice is to ask the server for a piece of HTML page through an XMLHttpRequest and bring it in the current page by simple copy. This function gives us an extremely flexible and light method for dynamic pages construction.

This way of working also applies to SVG documents. When navigators support the use of HTML and SVG elements in the same page, we can even manipulate the HTML and the SVG parts by this method. This is the case, for example, of the current versions of Firefox (1.5 when writing this article).

REX, short introduction

The REX proposition is short and clear. We can find it at http://www.w3.org/TR/rex/. REX means Remote Events for XML.

REX uses a subsection of the XPATH syntax to point to the XML tree portion we wish to modify. This subsection is simple to understand, close to the description of a path in a file tree. For example:

/ points to the root of the document

/svg/g[3] points to the third element g directly found as child of the root of the svg document (rem.: g allows to group svg elements).

id('bouton1') points to the node of the tree having the identifier (id) bouton1

id('boutons1')/@fill points to the fill attribute of the element with identifier bouton1

As seen in these examples, the syntax is quickly discovered, at least for the most common uses.

Now that we know how to point to the part of the document to be modified, here are some simple modifications examples:

<rex xmlns="http://www.w3.org/2006/rex" >
<event target="id('S1')/svg:path[13]" name="DOMNodeRemove">
</rex xmlns="http://www.w3.org/2006/rex" >

name contains the name of the executed command and DOMNodeRemove let us to delete a node; in this example, DOMNodeRemove is used for deleting a node. We thus delete the thirteenth path node (and its possible sub-nodes) found under the element with the S1 identifier.

_______________________________________ __________

<event target="id('S1')/svg:text[1]/@fill" name="DOMAttrModified" newvalue="blue">

Here, I show only the central line changed from the previous message. DOMAttrModified indicates that we modify the value of an attribute. The attribute is the color filling attribute of the first text node found under the element with the S1 identifier; the new value given to this attribute is blue.

_______________________________________ __________

<event target="id('S1')/svg:text/text()" name="DOMCharacterDataModified" newvalue="Texte changé">

DOMCharacterDataModified indicates that we modify the textual content of the first text element found under the element with the S1 identifier; the new value is ‘changed text’.

_______________________________________ __________

We can group several modifications:

<rex xmlns="http://www.w3.org/2006/rex" >
<event target="id('S1')/svg:path[13]" name="DOMNodeRemove">
<event target="id('S1')/svg:text[1]/@fill" name="DOMAttrModified" newvalue="blue">
<event target="id('S1')/svg:text/text()" name="DOMCharacterDataModified" </rex xmlns="http://www.w3.org/2006/rex" >

In this way, the previous three modifications are grouped in a single REX message.

For more details, your best bet is to look at the W3C proposition (15 pages).

_______________________________________ __________

_______________________________________ __________

Implementation of REX in Javascript

The first step to implement REX is to have methods to find a node in a document from an XPATH expression, REX compliant. My first implementation used an implementation of XPATH from Google (see http://goog-ajaxslt.sourceforge.net/). I would comment this implementation in a future note.

Then, I took into account the fact that Firefox has a support for SVG and XPATH. It was interesting to study this solution. This solution is compact and elegant: the whole REX support for documents used with Firefox takes approximately 200 lines of code Javascript.

The demonstration can be seen at the following address:

http://shadok.enst.fr:8080/modifxml/purMozilla/index.htm

The REX code used in this example:

http://shadok.enst.fr:8080/modifxml/commandeRex.xml

The Javascript code to execute the REX commands:

http://shadok.enst.fr:8080/modifxml/purMozilla/rexfox.js

The SVG document used in this example:

http://shadok.enst.fr:8080/modifxml/frame1.svgm

_______________________________________ __________

Note: the attributes position and timeStamp of REX commands are not implemented at the time being; position is going to be quickly added; timeStamp still seems to be under-defined in the general case of modifications of XML documents, but I believe I can make an implementation for SVG.

_______________________________________ __________

Obtaining the XMLHttpRequest object

function getHTTPObject() {
var xmlhttp;
if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
{
try { xmlhttp = new XMLHttpRequest(); }
catch (e) { xmlhttp = false; }
}
return xmlhttp;
}

I shall not comment on these 9 lines of code and point to the many tutorials about Ajax, for example from http://en.wikipedia.org/wiki/AJAX.

We shall suppose that the previous function allowed to get back an object named xmlupdater.

_______________________________________ __________

Obtaining the list of command to be executed

We suppose that a server supplies the commands and that the other elements of the modified page allow determining the URL of the REX message.

The request of the REX message requires the following 6 lines of code:

function sendRequest(urlcommand)
{
xmlupdater.open("GET", urlcommand);
xmlupdater.onload = handleRexResponse;
xmlupdater.send(null);
}

The management of the answered REX message is managed by the handleRexResponse function.

_______________________________________ __________

Execution of the REX message

The execution represents approximately 50 lines of code to interpret the REX message and call the functions, which execute the document modifications. The complete code is accessible on the demonstration site (see below).

For example, DOMNodeRemove begin by determining the targeted node by means of the nodesetFromPath function, then by calling the removeNode function; this is the following code sequence:


if(commandType == "DOMNodeRemove")

{

pointedSet = nodesetFromPath(ru.doc, ru.nsResolver, target);

for (var k = 0; k <>

removeNode(pointedSet.snapshotItem(k));

}

}


_______________________________________ __________

Obtain a set of nodes from an xpath

I mentioned in the previous paragraph the nodesetFromPath function.

It is defined in the following way:

function nodesetFromPath(doc, resolver, target)
{
return ret = doc.evaluate( target, doc, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
}

Where target is the string representing the xpath of the targeted object

doc is the reference of the XML document XML in which we look and

resolver is a function for the resolution of namespaces (see below)

The method evaluate of the doc object is a method defined in the Javascript implementation of Firefox.

resolver is the function reference that allows to associate a namespace prefix to a string, in order to resolve namespaces. In our example, where an SVG document is contained in a HTML document, the function is defined as follows:

function nsResolver(prefix) {
var ns = {
'xhtml' : 'http://www.w3.org/1999/xhtml',
'svg': 'http://www.w3.org/2000/svg'
};
return ns[prefix] || null;
}

_______________________________________ __________
_______________________________________ __________

Attention: it is possible that patents apply to the methods exposed in this article