# Créer un widget Avancé

Portaneo utilise le standard de développement de Widgets Google pour créer des widgets intégrable dans un portail Internet personnalisable tel que POSH.

## Résumé

Créer un widget avancé consiste pour l'essentiel à créer un fichier XML respectant le format imposé par l'API.
Votre widget doit donc contenir au minimum les tags suivant:

- <ModulePrefs>
- <Content>

Il est possible de créer des widget plus complexes avec les tags suivants intégrés dans le tag ModulePrefs:

- <usersPrefs>
- <Locale>
- <Require>

Pour les widgets RSS, il suffit d'importer l'url du flux RSS dans votre portail POSH, à travers l'interface tutorial ou dans le menu d'options de votre portail personnel.
Vous pouvez ajouter des widgets en provenance de la plate-forme Igoogle ou de la plate-forme Netvibes, ou encore des widgets créés spécialement par Portaneo.

# Sommaire

- Les propriétés du widget : titre, description et hauteur du widget
- Les options du widget : options de personnalisation du widget proposées aux utilisateurs
- Le contenu du widget :
  - Le type du widget
  - Le contenu HTML
  - Le contenu Javascript
  - Traduction / internationalisation
- Modèles de widgets
- Exemples de widgets
- Testez votre widget

Votre widget se présente sous la forme d'un fichier XML :

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="nom de mon widget" description="description de mon widget" height="200" /> <UserPref name="variable1" datatype="enum" default_value="valeur1" display_name="variable n.1 :" > <EnumValue value="valeur1" display_value="valeur n.1" /> <EnumValue value="valeur2" display_value="valeur n.2" /> <EnumValue value="valeur3" display_value="valeur n.3" /> <EnumValue value="valeur4" display_value="valeur n.4" /> <EnumValue value="valeur5" display_value="valeur n.5" /> </UserPref> <Content type="html"><![CDATA[ contenu HTML du widget <script type="text/javascript"> contenu javascript du widget </script> ]]> </Content> </Module>
Il se découpe en 3 parties principales que nous allons détailler dans la suite du document:

- les propriétés du widget (balise ModulePrefs)
- les options du widget (balise UserPref)
- le contenu du widget (balise Content)

## Les propriétés du widget

la balise ModulePrefs sert à définir les propriétés du widget:

<ModulePrefs title="mon widget" description="c'est mon widget" height="200" />

- title : nom du widget (obligatoire). Chaîne limitée à 30 caractères.
- description : description du widget (optionnel). Chaîne limitée à 250 caractères.
- height : hauteur du widget en pixels (obligatoire). Entier compris entre 20 et 400. Cette hauteur est celle d'affichage du widget.
  Si la hauteur du widget évolue, vous pourrez utiliser dans le code du widget la fonction _IG_AdjustIFrameHeight.

## Les pré-requis du widget

Certains tags permettent de signaler à l'API que votre widget comprend certains options obligatoires.

Avec POSH, vous pouver ajouter un pré-requis spécifique qui va signaler à l'API que les fichiers d'internationalisation de votre widget sont sur votre portail. Vous pourrez donc mettre des url relatives.

<Require feature="internal-posh"/>

De la même façon, si vous téléchargez un widget propre à Portaneo, le widget contiendra le pré-requis suivant.

<Require feature="external-portaneo" />

Certains widgets Portaneo peuvent être pré-intégrés au portail par l'administrateur. Dans ce cas, les urls seront relatifs à votre portail. Le widget contiendra le pré-requis suivant.

<Require feature="internal-portaneo"/>

## Les options du widget

Les balises UserPref servent à définir les options du widget, qui vous permettent d'offrir une personnalisation du widget aux utilisateurs.
Ce sont les options qui s'affichent quand on clique sur "configurer" sur le bandeau du haut du widget.

<UserPref name="variable1" datatype="enum" default_value="valeur1" display_name="variable n.1 :" >...</UserPref>

- name : identifiant de l'option. Chaîne de caractère sans espaces.
- datatype : type de l'option
  Les options peuvent être de plusieurs type :
  - string : Chaîne de caractère
    <UserPref name="name" datatype="string" default_value="Laurent Dubois" display_name="Votre nom :" />
  - password : Chaîne de caractère. Les caractères sont remplacés par des *
    <UserPref name="password" datatype="password" default_value="" display_name="Mot de passe :" />
  - bool : Case à cocher. La valeur par défaut peut être "true"(coché) ou "false"(non coché)
    <UserPref name="thumb" datatype="bool" default_value="true" display_name="Afficher les vignettes ?" />
  - enum : Liste déroulante. Chaque élément de la liste sera définie par une balise EnumValue.
    <UserPref name="color" datatype="enum" default_value="blue" display_name="Couleur de fond :"> <EnumValue value="red" display_value="rouge" /> <EnumValue value="blue" display_value="bleu" /> <EnumValue value="green" display_value="vert" /> <EnumValue value="yellow" display_value="jaune" /> </UserPref>
- default_value : valeur par défaut de l'option (utilisée au premier affichage du widget pour un utilisateur).
- display_name : label affiché.

## Le contenu du widget

La balise Content indique le type du widget et contient le code HTML et javascript du widget.
Avec la nouvelle version de Posh, vous pouvez définir plusieurs content, qui correspondront à des vues différentes du widget, la vue classique et la vue plein écran.
Attribut view, différentes possibilités :

- view="home"
- view="home,canvas"
- view="canvas"

<Content type="html"><![CDATA[ <div id="examplediv"></div> <script type="text/javascript"> function init(){ var div=_gel("examplediv"); div.innerHTML="Hello World !"; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content>

### Vue par défaut: home

<Content type="html" view="home"><![CDATA[ <div id="examplediv"></div> <script type="text/javascript"> function init(){ var div=_gel("examplediv"); div.innerHTML="Hello World !"; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content>

### Deux vues et un contenu identique

<Content type="html" view="home,canvas"><![CDATA[ <div id="examplediv"></div> <script type="text/javascript"> function init(){ var div=_gel("examplediv"); div.innerHTML="Hello World !"; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content>

### Deux vues et deux contenus

<Content type="html" view="home"><![CDATA[ <div id="examplediv"></div> <script type="text/javascript"> function init(){ var div=_gel("examplediv"); div.innerHTML="Hello World !"; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content> <Content type="html" view="canvas"><![CDATA[ <div id="examplediv"> le contenu de mon widget en vue plein écran </div> ]]> </Content>

- le type du widget via l'attribue "type".
  - type="html" : widget intégré dans une IFRAME hébergé sur nos serveurs. Si vous avez le choix, utilisez toujours ce type.
    <Content type="html"><![CDATA[ <div id="examplediv"></div> <script type="text/javascript"> function init(){ var div=_gel("examplediv"); div.innerHTML="Hello World !"; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content>
  - type="URL" : widget intégré dans une IFRAME hébergé sur vos serveurs. A utiliser si le contenu de votre widget est dynamique (rafraîchi à chaque affichage par les informations de votre base de donnés) et que vous ne pouvez utiliser les fonctions _IG_FetchContent et _IG_FetchXmlContent.
    <Content type="url" href="http://www.monsite.com/monwidget.php" />
    Pour ce type de widget, la balise est vide car le code de votre widget est dans le fichier présent à l'URL mentionnée dans la balise.
    Attention : Si vous voulez utiliser les fonctions javascript mentionnées plus bas et la feuille de style standard, insérez les lignes suivantes dans le du code de votre widget:
    <link rel="stylesheet" type="text/css" media="screen" title="default" href="http://www.portaneo.com/styles/module.css" /> <script type="text/javascript" src="http://www.portaneo.com/includes/modules.js"></script>
- le HTML du widget (sauf pour un type URL)
  taper le HTML du widget. Il sera formatté par notre CSS
- le code javascript du widget (sauf pour un type URL)
  Dans une unique balise <script type="text/javascript"></script>, ecrire le code javascript du widget.
  Vous pouvez utiliser les fonctions suivantes :

  Fonctions principales
  _IG_RegisterOnloadHandler(FONCTION) | Appeler une fonction au chargement du widget. FONCTION : fonction à appeler. exemple : function init(){ alert('hello world'); } _IG_RegisterOnloadHandler(init);
  _IG_AdjustIFrameHeight() | Ajuster la frame contenant le widget à son contenu. A utiliser si le contenu du widget change de taille.
  _IG_FetchContent(URL, FONCTION) | Récupérer le contenu d'un fichier dont l'URL est spécifiée et envoi les résultats à la fonction FONCTION. Utilisation asynchrone d'Ajax. Exemple : function treatFile(responsetxt){ var obj=_gel("mondiv"); obj.innerHTML=responsetxt; } _IG_FetchContent('http://www.monsite.com/mondoc.csv',treatFile);
  _IG_FetchXmlContent(URL, FONCTION) | Récupérer le contenu d'un fichier XML dont l'URL est spécifiée et envoi les résultats à la fonction FONCTION. Utilisation asynchrone d'Ajax. Exemple : function treatXml(responsexml){ var str="nom : "+responsexml.getElementsByTagName("name")[0].firstChild.nodeValue+" age : "+responsexml.getElementsByTagName("age")[0].firstChild.nodeValue; var obj=_gel("mondiv"); obj.innerHTML=str; } _IG_FetchXmlContent('http://www.monsite.com/myxmlfile.xml',treatXml);
  Fonctions permettant d'accéder aux options
  _IG_Prefs(__MODULE_ID__) | récupérer les options du widget dans un objet. Exemple : var pref = new _IG_Prefs(__MODULE_ID__);
  .getString("variable") | récupérer la valeur d'une option de type "string". Exemple : var name = pref.getString("yourname");
  .getInt("variable") | récupérer la valeur d'une option de type "string" au format entier
  .getBool("variable") | récupérer la valeur d'une option de type "bool"
  .set("variable","valeur") | modifier la valeur de l'option "variable" pour l'utilisateur. Assigner la valeur "valeur". Exemple : pref.set("yourname","John Wayne");
  .open() | ouvre la fenetre de configuration des options. Exemple : <A href=# onclick="return pref.open()">Modifier les options</A>
  Gestion d'onglets
  _IG_Tabs(__MODULE_ID__,"default selection") | Initialise la barre d'onglets. Retourne l'objets tabs, utilisé pour exécuter les fonctions ci-dessous. "default selection" est le nom de l'onflet selectionné par défaut (optionnel). Exemple : var tabs = new _IG_Tabs(__MODULE_ID__);
  .tabsContainer | Optionnel. Définit l'objet qui accueillera les onglets. Exemple : tabs.tabsContainer=_gel("tabsdiv"); (si vous avez créé un objet <div id="tabsdiv"></div>)
  .addTab("tabname","divid",function) | Ajoute un nouvel onglet, ayant pour nom "tabname", dans le div "divid", appelant la fonction "function". Exemple : tabs.addTabs("tab 1","tabdiv",displayTab1Content);
  .setSelectedTab("tabIndex") | Défini l'onglet sélectionné."tabIndex" est le numéro de l'onglet (commence par 0).
  Autres fonctions
  _bringToFront(__MODULE_ID__) | Met le widget au premier plan.
  _gel("object") | Récupérer l'objet dont l'id est "object". Exemple : var obj=_get("mondiv");obj.innerHTML='Hello world !';
  _gelstn("object") | Synonyme de la méthode javascript .getElementsByTagName()
  _esc("string") | Synonyme de la méthode javascript .escape()
  _unesc("string") | Synonyme de la méthode javascript .unescape()
  _uc("string") | Retourne le texte "string" en majuscules.
  _lc("string") | Retourne le texte "string" en minuscules.
  _min(valeur1,valeur2) | Retourne le minimum des deux valeurs.
  _max(valeur1,valeur2) | Retourne le maximum des deux valeurs.
  _args("string") | Transforme une chaîne "name=john&age=12&sex=m" en un tableau {"name":"john","age":"12","sex":"m"}
  _trim("string") | Supprime les espaces inutiles en début et fin de chaîne.
  Fonctions pour le mode canvas
  gadgets.views.getCurrentView | retourne la vue courante
  gadgets.views.getName | retourne le nom de la vue courante
  gadgets.views.getSupportedViews() | Renvoie un hash des différentes vues supportées par le widget
  gadgets.views.requestNavigateTo(function) | Renvoie vers un type de vue ('home' ou 'canvas') Exemple pour ouvrir la vue CANVAS : gadgets.views.requestNavigateTo(gadgets.views.getSupportedViews()['canvas']);
  gadgets.views.changeUrl(url) | Modifie l'url d'un widget, ce qui permet d'ouvrir en plein écran une page web signalée dans le widget

- Traduction / internationalisation
  Récupérer la langue de l'utilisateur :
  Utilisez la variable __lang dans le javascript de votre widget. La langue est codée sur 2 caractères (ex: en pour l'anglais, fr pour le français, ...). Ceci n'est valable que si la langue est configurée dans posh (répertoire langue existant dans /l10n et paramêtre AVLANGS mis à jour dans la table adm_config).
  Traduire votre widget en fonction de la langue de l'utilisateur :
  Vous pouvez utiliser la fonction __ pour traduire les éléments de votre widget. Le dictionnaire utilisé est le fichier /l10n/fr/lang.js. Si certains mots n'y sont pas présents, ajoutez les dans ce fichier, ou demandez nous de les ajouter dans la prochaine version de posh.
  Exemple :
  la fonction __("lblClose") permet d'afficher "fermer" ou "close" suivant la langue de l'utilisateur.
  Les noms des options des widgets sont automatiquement traduits à partir du dictionnaire /l10n/fr/lang.js

## Modèles

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="nom de mon widget" description="description de mon widget" height="200" /> <UserPref name="variable1" datatype="enum" default_value="valeur1" display_name="variable n.1 :" > <EnumValue value="valeur1" display_value="valeur n.1" /> <EnumValue value="valeur2" display_value="valeur n.2" /> </UserPref> <UserPref name="variable2" datatype="string" default_value="valeur1" display_name="variable n.2 :" > <UserPref name="variable3" datatype="bool" default_value="true" display_name="variable n.3" /> <Content type="html"><![CDATA[ <!-- contenu HTML du widget --> <script type="text/javascript"> //contenu javascript du widget //fonction d'initialisation du widget (optionnel) function init(){ } _IG_RegisterOnloadHandler(init); </script> ]]> </Content> </Module>

## Exemples de widgets

Pour un aperçu des exemples, copiez le code dans l'outil de test de widgets

### Hello World !

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="Hello world !" description="my first portaneo widget" height="100" /> <Content type="html"><![CDATA[ <h2>Hello world !</h2> ]]> </Content> </Module>

### Boite multicolore

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="Colored box" description="test widget" height="170" /> <UserPref name="color" datatype="enum" default_value="blue" display_name="color :" > <EnumValue value="blue" display_value="blue" /> <EnumValue value="red" display_value="red" /> <EnumValue value="yellow" display_value="yellow" /> </UserPref> <Content type="html"><![CDATA[ <div style='padding:6px'> <table width='100%'> <tr> <td>Choose a color :</td> <td></td> <td bgcolor='blue' onclick='changeColor("blue")' style='text-align:center;width:50px;cursor:hand;cursor:pointer;'>Blue</td> <td></td> <td bgcolor='red' onclick='changeColor("red")' style='text-align:center;width:50px;cursor:hand;cursor:pointer;'>Red</td> <td></td> <td bgcolor='yellow' onclick='changeColor("yellow")' style='text-align:center;width:50px;cursor:hand;cursor:pointer;'>Yellow</td> <td></td> </tr> <tr> <td colspan=8> </td> </tr> <tr> <td colspan=8 id='box' style='height:80px'> </td> </tr> </table> </div> <p> <a href="#" onclick="return addBlackColor()">add black color</a> <a href="#" onclick="return removeBlueColor()">remove blue color</a> </p> <script type="text/javascript"> var pref; function init() { pref = new _IG_Prefs(__MODULE_ID__); var color = pref.getString("color"); var obj = _gel('box'); obj.style.backgroundColor = color; } function changeColor(v_color) { var obj = _gel('box'); obj.style.backgroundColor = v_color; // save the new color value pref.set("color",v_color); } function addBlackColor() { pref.addOption('color','black','black'); return false; } function removeBlueColor() { pref.removeOption('color','blue'); return false; } _IG_RegisterOnloadHandler(init); </script> ]]> </Content> </Module>

### Interaction du widget avec des fichiers : lecture et traitement d'un fichier HTML

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="lecture HTML" description="widget de test" height="50" /> <Content type="html"><![CDATA[ <a href="#" onclick="return loadFile()">afficher le HTML</a><br /> <div id="mondiv"></div> <script type="text/javascript"> function treatFile(responsetxt) { var obj=_gel("mondiv"); obj.innerHTML=responsetxt; _IG_AdjustIFrameHeight(); } function loadFile() { _IG_FetchContent('http://www.portaneo.com/examples/html_include.html',treatFile); } </script> ]]> </Content> </Module>

### Interaction du widget avec des fichiers : lecture et traitement d'un fichier XML

<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="lecture XML" description="widget de test" height="50" /> <Content type="html"><![CDATA[ <div id="mondiv"></div> <script type="text/javascript"> function treatXml(responsexml) { var str=""; var i=0; while (responsexml.getElementsByTagName("eleve")[i]) { var eleve=responsexml.getElementsByTagName("eleve")[i]; str+=eleve.getElementsByTagName("prenom")[0].firstChild.nodeValue+" "+eleve.getElementsByTagName("nom")[0].firstChild.nodeValue+" a eu la note de "+eleve.getElementsByTagName("note")[0].firstChild.nodeValue+"/20 à son devoir.<br />"; i++; } var obj=_gel("mondiv"); obj.innerHTML=str; } function init() { _IG_FetchXmlContent('http://www.portaneo.com/examples/eleves.xml',treatXml); } _IG_RegisterOnloadHandler(init); </script> ]]> </Content> </Module>

## Testez votre widget

Aprés chaque modification, testez votre widget avant de le publier grâce à l'outil de test (disponible sur la page de création d'un widget Avancé).