jan 23 2010

Réaliser un panel à onglet simple avec Mootools

Catégorie(s): InformatiqueSébastien @ 10:34

Objectifs

Je souhaitais réaliser un système de panel à onglet (ou tab panel in english) pour un site sur lequel je travaille. Le but est d’avoir peu de code, que ce soit facilement utilisable et implémentable mais également compatible avec la majorité des navigateurs. Sachant que je bosse avec le framework javascript Mootools, je vais l’utiliser pour me faciliter tout ça. Je souhaite également pouvoir mettre sur la même page plusieurs panels à onglets. Par contre, je tiens à ce que ça reste très simple, donc pas d’animation inutiles ou de fonctionnalités de-la-mort-qui-tue-mais-qui-servent-pas-à-grand-chose.

Le plus rapide aurait été de reprendre un code existant sur le net, mais c’est pas drôle. Alors amusé à le faire tout seul comme un grand.

Résultat

On commence par la démo disponible à cette adresse : http://delistage.net/tutos/tab-panel-simple-mootools/.

Et on passe maintenant au détail des différents fichiers et scripts nécessaires :

index.html

<div class="panel">
  <ul class="panel-header">
    <li class="panel-active"><a href="#" rel="panel-content-1">Content 1</a></li>
    <li><a href="#" rel="panel-content-2">Content 2</a></li>
    <li><a href="#" rel="panel-content-3">Content 3</a></li>
  </ul>

  <div id="panel-content-1" class="panel-content panel-display">
    panel-content-1
  </div><!-- #panel-content-1 -->

  <div id="panel-content-2" class="panel-content">
    panel-content-2
  </div><!-- #panel-content-2 -->

  <div id="panel-content-3" class="panel-content">
    panel-content-3
  </div><!-- #panel-content-3 -->
</div><!-- Panel 1 -->

Conteneur : un div ayant la classe panel, à ne pas changer.

La liste des onglets (ul) sans contrainte au niveau du nom de la classe. Chaque onglet est contenu dans une ligne (li) dont celui à sélectionner par défaut doit avoir la classe panel-active. On a ensuite l’onglet en lui-même sous forme de lien. L’attribut rel de cette balise doit contenir l’id de la div de contenu correspondant.

Différentes DIV de contenu doivent posséder un id (identique à celui rentré dans la balise rel de l’onglet) et la classe panel-content. Si vous souhaitez afficher un des panels par défaut, il suffit de lui ajouter la classe panel-display.

panels.js

Ce fichier contient la fonction en charge de la gestion des différents panels. Pas besoin de plus de commentaires que ceux qui sont dans le code je pense.

panelManager = function(panelClass) {
  // On parcourt chaque panel
  $$('.panel').each(function(panelElt) {
    // On récupère les onglets ...
    var tabs = panelElt.getFirst('ul').getElements('a');

    // Et on les parcourt à leur tour
    tabs.each(function(tab) {
      /*
       * Ajout de l'évèment click
       */
      tab.addEvent('click', function() {
        // On regarde si le panel-content lié à cet onglet existe
        var contentDiv = $(this.rel);
        if(contentDiv != null) {
          // Si c'est le cas, on masque les panel-content
          panelElt.getElements('div').removeClass('panel-display');
          // On déselectionne tous les onglets
          panelElt.getFirst('ul').getElements('li').removeClass('panel-active');
          // On affiche le panel-content sélectionné
          contentDiv.addClass('panel-display');
          // On sélectionne l'onglet
          this.getParent().addClass('panel-active');
        }

        // Etant donné que notre onglet est un lien (a),
        // on retourne faux pour annuler son action
        return false;
      });
    });
  });
}

Sur les pages contenant un ou plusieurs panels, il vous suffit d’appeler cette fonction très simplement :

<script type="text/javascript" src="panels.js"></script>
<script type="text/javascript">
  window.addEvent('domready', function() {
    panelManager();
  });
</script>

panels.css

.panel { margin-bottom: 15px; } 

.panel-header { border-bottom: 1px solid #333333; height: 30px; }

.panel-header li {
  float: left;
  height: 24px;
  margin-right: 10px;
  padding: 0 10px;
  padding-top: 5px;
  border: 1px solid #666666;
  border-bottom: 1px solid #333333;
  background-color: #fafafa;
}

.panel-header li a { color: #555555; text-decoration: none; }

.panel-header li:first-child { margin-left: 5px; }

.panel-header li.panel-active {
  background-color: #eeeeee;
  border: 1px solid #333333;
  border-bottom: 1px dashed #333333;
  color: #333333;
}

.panel-header li.panel-active a {
  color: #333333;
  text-decoration: none;
  font-weight: bold;
}

.panel-content {
  clear: both;
  background-color: #eeeeee;
  border: 1px solid #333333;
  border-top: 0;
  padding: 5px;
  display: none;
}

.panel-display { display: block; }

Conclusion

Et voilà, vous avez là une petite fonction qui s’occupe d’afficher de la gestion des panels très simplement. Ça fonctionne avec Firefox 3.5, IE8 et Chrome 3.0 pour ceux que j’ai testé, mais étant donné que ça utilise Mootools, c’est censé être compatible avec la majorité des navigateurs. En cas de bugs ou de choses pas claires, les commentaires sont ouverts.


déc 14 2009

Ajouter des VirtualHosts sous WampServer

Catégorie(s): InformatiqueSébastien @ 20:43

En commençant à bidouiller avec des frameworks PHP tels que Symfony et CodeIgniter, j’ai rapidement eu besoin de mettre en place des VirtualHosts sous WampServer afin de pouvoir mieux séparer mes différents projets. Ayant rencontré quelques petites difficultés vu que je ne savais pas du tout comment faire, voici un petit tuto pour aider ceux qui sont dans le même cas que moi.

1. Notes préliminaires

La technique que je vous explique ici a été testé sous Windows XP Pro 32bits, Vista Familial 32bits et Seven Pro 32bits sans le moindre soucis.
La version d’Apache utilisée a été la version 2.2.11 (et une ou deux autres inférieures mais j’ai oublié de noter leur numéro).

2. Choix du nom

La première chose à faire est de choisir le nom que l’on voudra donner à notre hôte virtuel. Si vous bossez en local, je vous conseille de ne pas utiliser un nom de domaine existant mais plutôt de passer par un TLD comme « .loc ». Vu qu’on va modifier le fichier hosts par la suite, ça vous évitera de ne plus avoir accès au vrai site.

Tout au long de ce billet, c’est le nom de domaine http://myhost.loc/ que je vais mettre en place. Si vous tentez d’accéder maintenant à cette adresse, vous devriez en toute logique avoir une jolie erreur Serveur introuvable, ce qui est tout à fait normal étant donné que votre système ne sait pas quelle IP liée à ce nom de domaine. Pour ceux qui ne savent pas comment fonctionne les DNS, voilà un peu de lecture : DNS (Domain Name System) sur Wikipedia.

3. Fichier hosts

En vous connectant à cette URL, votre ordinateur va essayer de récupérer l’adresse IP de ce nom de domaine via le fichier hosts puis chez votre fournisseur de DNS. Etant donné que « myhost.loc » n’existe dans aucun des deux, cette erreur est levée (d’où le message Serveur introuvable).

Pour l’ajouter, rien de plus simple : éditer le fichier hosts qui se trouve dans le dossier C:/Windows/system32/drivers/etc/. Pour pouvoir l’éditer, penser à enlever la lecture seule et à avoir les droits d’administration. Il suffit ensuite de rajouter cette ligne dans celui-ci :

127.0.0.1 localhost
127.0.0.1 myhost.loc

Vous demandez donc que « myhost.loc » pointe vers l’adresse IP « 127.0.0.1″, soit l’adresse IP locale de votre PC. Si vous tentez d’y accéder de nouveau, vous devriez maintenant tomber sur la page d’accueil de WampServer. Il nous reste plus qu’à configurer Apache afin qu’il fasse pointer ce domaine au bon endroit.

Si vous n’avez pas la ligne « 127.0.0.1 localhost », ajoutez la maintenant au début de la liste, ça vous évitera sûrement des soucis par la suite.

4. Configurer les VirtualHosts

4.1. a2ensite et a2dissite

Pour bien faire, il faudrait utiliser les commandes a2ensite et a2dissite pour activer et désactiver des VirtualHosts définis dans des fichiers. N’ayant pas accès à ces commandes sous WampServer (ou alors j’ai vraiment mal cherché), il fallait trouver une autre solution : tout configurer dans httpd.conf, ce qui est beaucoup plus contraignant au niveau de la maintenance. On va cependant tâcher de rendre ça le plus simple possible. Si cependant plus d’information sur ce point vous intéresse, je vous conseille le lien suivant : Héberger plusieurs sites sur son serveur : Virtual Hosts.

4.2. Création des VirtualHosts

Pour créer les VirtualHosts, on peut le faire à l’arrache à savoir en les mettant directement dans le fichier httpd.conf. Niveau propreté et maintenabilité, c’est pas ce qu’il y a de mieux. Je vous conseille de créer un dossier nommé hosts à la racine de votre répertoire contenant WampServer (« C:/Wamp » par défaut).

Toujours par soucis de propreté, je conseille également de créer un seul fichier par VirtualHosts. De plus cette méthode permet également de se rapprocher de celle que l’on devrait utiliser normalement (cf. point ci-dessus). Je crée donc un fichier « myhost.conf » pour mon domaine « myhost.loc » contenant :

NameVirtualHost myhost.loc
<VirtualHost myhost.loc>
  DocumentRoot "C:/Wamp/www/myhost/"
  DirectoryIndex index.php
  <Directory "C:/Wamp/www/myhost/">
    AllowOverride All
    Allow from All
  </Directory>
</VirtualHost>

La configuration est ici basique et je vous laisse le soin de la personnaliser selon vos besoins. Une petite information quand même concernant le chemin d’accès : utiliser des « / » et pas de « \ » comme séparateur, et ne pas oublier le « / » final.

Voilà votre hôte virtuel est crée. Passons maintenant à la configuration d’Apache pour l’utiliser.

4.3. Inclusion des VirtualHosts dans httpd.conf

Pour être sûr d’éditer le bon fichier httpd.conf si vous disposez de plusieurs versions d’Apache, je vous conseille de passer par le menu de WampServer : Clic gauche sur l’icône > Apache > httpd.conf.

Placez vous en bas de celui-ci et ajoutez :

Include "C:/Wamp/hosts/myhost.conf"

Il vous suffit dès lors de relancer les services pour que le changement soit pris en compte. Vous devriez maintenant être en mesure d’accéder à votre site via l’adresse : http://myhost.loc. Cependant si vous tentez d’accéder à l’adresse http://localhost/, vous êtes maintenant redirigé également vers votre hôte « myhost.loc ».

Pour corriger ça, il faut créer un virtual host pour « localhost ». On reprend donc la même logique :

1. Créer un fichier localhost.conf dans notre dossier hosts contenant :

NameVirtualHost localhost
<VirtualHost localhost>
  DocumentRoot "C:/Wamp/www/"
  DirectoryIndex index.php
  <Directory "C:/Wamp/www/">
    AllowOverride All
    Allow from All
  </Directory>

  Include "C:/Wamp/alias/*"
</VirtualHost>

A la différence de celui que l’on a fait pour « myhost.loc », vous pouvez remarquer que j’ai inclus les alias dans cet hôte.

2. Configurer Apache

Commencez par supprimer la ligne suivante qui est devenue inutile :

Include "C:/Wamp/alias/*"

Puis incluez votre VirtualHosts « localhost.conf » en première position :

Include "C:/Wamp/hosts/localhost.conf"
Include "C:/Wamp/hosts/myhost.conf"

Il ne vous reste donc plus qu’à relancer les services pour pouvoir accéder à vos deux domaines.

5. Maintenance

Pour gérer vos hôtes, c’est très simple : il suffit d’éditer le fichier httpd.conf et de commenter/décommenter les lignes d’inclusion pour désactiver/activer un hôte.


sept 28 2009

[Symfony] Doctrine : « onDelete: SET NULL »

Catégorie(s): InformatiqueSébastien @ 20:28

Avec Symfony vous pouvez, en utilisant Doctrine, vous servir de l’option « onDelete » sur les clés étrangères (CASCADE, SET NULL, and RESTRICT). SET NULL m’a cependant posé quelques soucis en me déclenchant l’erreur suivante :

SQLSTATE[HY000]: General error: 1005 Can't create table 'sf.#sql-abc_a7' (errno: 150). Failing Query: ALTER TABLE gallery ADD FOREIGN KEY (category_id) REFERENCES gallery_category(id) ON DELETE SET NULL

Si vous aussi vous rencontrez cette erreur, nous allons voir quelques éléments à vérifier. Pour cela, on va utiliser deux tables basiques :

Category:
  - id : entier
  - nom : chaine

Gallery:
  - id : entier
  - category_id : entier
  - nom : chaine


1. Champs identiques

La première chose à vérifier est que vos deux champs soient identiques au niveau du type, de la longueur, des options, etc. Lorsque vous laissez Symfony et Doctrine s’occuper tout seuls des champs ‘ID’ (qui s’appellera toujours id), il faut que votre champs category_id soit tout simplement du type integer et pas integer(X). Le champs id sera en effet généré en tant que BIGINT(20) dans la base de données. Si vous mettez une autre longueur, ça fera planter la création de la clé étrangère.

Incorrect

Category:
  columns:
    nom: { type: string(255), notnull: true }

Gallery:
  columns:
    category_id: { type: integer(10) }
    nom: { type: string(255), notnull: true }
  relations:
    Category: { onDelete: SET NULL, local: category_id, foreign: id }


Correct

Category:
  columns:
    nom: { type: string(255), notnull: true }

Gallery:
  columns:
    category_id: { type: integer }
    nom: { type: string(255), notnull: true }
  relations:
    Category: { onDelete: SET NULL, local: category_id, foreign: id }


2. PAS de notnull true

L’autre élément à faire attention c’est à ce que votre champs local puisse être null. Cette remarque s’appliquent surtout à ceux qui passent d’un onDelete: CASCADE à un onDelete: SET NULL en ne modifiant que cette valeur. Il faut aussi penser à supprimer l’option notnull: true de votre champs local.

Incorrect

Category:
  columns:
    nom: { type: string(255), notnull: true }

Gallery:
  columns:
    category_id: { type: integer, notnull: true }
    nom: { type: string(255), notnull: true }
  relations:
    Category: { onDelete: SET NULL, local: category_id, foreign: id }


Correct

Category:
  columns:
    nom: { type: string(255), notnull: true }

Gallery:
  columns:
    category_id: { type: integer }
    nom: { type: string(255), notnull: true }
  relations:
    Category: { onDelete: SET NULL, local: category_id, foreign: id }


3. Index manquant

Si vous souhaitez faire une clé étrangère sur un champs autre que la clé primaire, comme par exemple le nom, il faut que ce champs possède un index. En théorie, il est crée automatiquement. Si ce n’est pas le cas, il suffit de le créer soit même :

Category:
  indexes:
    MonIndex:
      fields:
        nom: []
  columns:
    nom: { type: string(255), notnull: true }

Gallery:
  columns:
    category_id: { type: integer }
    category_name: { type: integer }
    nom: { type: string(255), notnull: true }
  relations:
    Category: { onDelete: SET NULL, local: category_name, foreign: name }


Conclusion

Rien qu’avec ces trois vérifications, vous devriez ne plus rencontrer d’erreur. Dans le cas contraire, allez faire un tour du coté du forum de Symfony. ;) Notez également que les vérifications 1 et 3 sont aussi utiles quand vous utilisez un onDelete: CASCADE ou RESTRICT.


sept 23 2009

[PDI] Récupérer la valeur du noeud XML que l’on parcourt

Catégorie(s): InformatiqueSébastien @ 21:42

Dans le genre Je bloque sur des trucs trop cons, voilà l’exemple du jour. Comment extraire les données du fichier XML suivant avec Pentaho Data Integration et le composant Extraction de données XML ?

<?xml version="1.0" encoding="UTF-8"?>
<response>
	<resData>
		<list>
			<name>name1</name>
			<name>name2</name>
			<name>name3</name>
			<name>name4</name>
			<name>name5</name>
			<name>name6</name>
			<name>name7</name>
			<name>name8</name>
			<name>name9</name>
			<name>name10</name>
		</list>
	</resData>
</response>

La première chose que j’ai tenté fût de parcourir le noeud /response/resData/list. Après récupération automatique des champs, je vois bien :
- Nom : name
- XPath à parcourir : name
- Elément : Node

C’est parfait ! Testons ça en prévisualisant. Le résultat est simple : une seule ligne est affichée (valeur name1). C’est pas bon.

Il faut donc parcourir /response/resData/list/name. Oui mais quand on récupère les champs, il ne nous ajoute rien. Par contre lorsque l’on prévisualise, on a bien les 10 lignes qui apparaissent mais vide. Il faut donc créer manuellement le champs nécessaire. Autant le nom c’est plutôt simple, autant le reste c’est un peu plus subtil. Dans XPath à parcourir, il suffit de mettre un « . » (point seulement) et dans Elément il faut choisir Node. Et là magie (ou pas), on a bien nos dix noms qui apparaissent.


août 07 2009

[Pentaho BI Server] Personnaliser le menu

Catégorie(s): InformatiqueSébastien @ 21:37

En visitant les stats du blog sur Google Analytics, j’ai remarqué qu’une recherche m’amenait pas mal de visiteurs : « pentaho bi server personnaliser menu ». Le soucis c’est que je n’ai rien écrit sur le sujet et ces visiteurs devaient rentrer bredouille. Je vais essayer de corriger ça et de vous apporter un début de réponse en modifiant une partie de celui-ci. Vous allez voir, c’est très simple en fait une fois qu’on le sait.

La seule partie du menu que j’ai réussi à modifier pour l’instant est celle avec les grosses icônes en dessous du menu « Fichier ». Pour cela c’est facile, il n’y a qu’un seul fichier à modifier : BI_SERVER_HOME/tomcat/webapps/pentaho/mantle/xul/main_toolbar.xul (pensez à faire une sauvegarde de ce fichier avant on sait jamais). Normalement il ressemble à ça :

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window width="400" height="275" title="Placeholder"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"  xmlns:pen="http://www.pentaho.org/2008/xul" onload="mainToolbarHandler.init()">

  <toolbar id="mainToolbar">
    <toolbarspacer width="10"/>
    <toolbarbutton id="openButton" image="mantle/images/open_32.png" onclick="mainToolbarHandler.openClicked()" tooltiptext="${openEllipsis}"/>
    <toolbarspacer width="20"/>
    <toolbarbutton id="newAdhocButton" image="mantle/images/new_report_32.png" onclick="mainToolbarHandler.newAdhocClicked()" tooltiptext="${newAdhocReportEllipsis}"/>
    <toolbarbutton id="newAnalysisButton" image="mantle/images/new_analysis_32.png" disabledimage="mantle/images/new_analysis_32_disabled.png" onclick="mainToolbarHandler.newAnalysisClicked()" tooltiptext="${newAnalysisViewEllipsis}"/>
    <toolbarspacer width="20"/>
    <toolbarbutton id="editContentButton" image="mantle/images/editContent_32.png" disabledimage="mantle/images/editContent_32_disabled.png"  onclick="mainToolbarHandler.editContentClicked()" tooltiptext="${editContent}" disabled="true" type="toggle" pen:visible="false"/>
    <toolbarspacer id="editButtonSpacer" width="20" pen:visible="false"/>
    <toolbarbutton id="saveButton" image="mantle/images/save_32.png" disabledimage="mantle/images/save_32_disabled.png" onclick="mainToolbarHandler.saveClicked()" tooltiptext="${save}" disabled="true"/>
    <toolbarbutton id="saveAsButton" image="mantle/images/saveAs_32.png" disabledimage="mantle/images/saveAs_32_disabled.png"  onclick="mainToolbarHandler.saveAsClicked()" tooltiptext="${saveAs}" disabled="true"/>
    <toolbarspacer width="20"/>
    <toolbarbutton id="printButton" image="mantle/images/print_32.png" disabledimage="mantle/images/print_32_disabled.png" onclick="mainToolbarHandler.printClicked()" tooltiptext="${print}" disabled="true"/>
    <toolbarspacer width="20"/>
    <toolbarbutton id="workspaceButton" image="mantle/images/workspace_32.png" type="toggle" onclick="mainToolbarHandler.workspaceClicked()" tooltiptext="${workspace}"/>
    <toolbarbutton id="showBrowserButton" image="mantle/images/browser_show_32.png" downimage="mantle/images/browser_hide_32.png" type="toggle" onclick="mainToolbarHandler.showBrowserClicked()" tooltiptext="${toggleSolutionBrowser}"/>
  </toolbar>

</window>

Il y a deux choses à modifier, la première étant de modifier la toolbar en elle-même et de supprimer/ajouter/déplacer les éléments que vous souhaitez. La seconde chose à modifier, ou plutôt virer, est l’attribut onload de la balise window.

Si on prend le menu que j’utilise dans ma solution, je n’avais besoin que du bouton Ouvrir et Afficher l’explorateur de solution, ce qui me donne pour le fichier main_toolbar.xul :

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window width="400" height="275" title="Placeholder"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"  xmlns:pen="http://www.pentaho.org/2008/xul">

  <toolbar id="mainToolbar">
    <toolbarspacer width="10"/>
    <toolbarbutton id="openButton" image="mantle/images/open_32.png" onclick="mainToolbarHandler.openClicked()" tooltiptext="${openEllipsis}"/>
    <toolbarspacer width="20"/>
    <toolbarbutton id="showBrowserButton" image="mantle/images/browser_show_32.png" downimage="mantle/images/browser_hide_32.png" type="toggle" onclick="mainToolbarHandler.showBrowserClicked()" tooltiptext="${toggleSolutionBrowser}"/>
  </toolbar>

</window>

Pour le menu « Fichier », je ne sais pas comment faire pour la simple raison que je n’ai pas (encore ?) eu besoin de le modifier donc pas de problème, pas de recherche et donc pas de solution. En revanche si certains savent comment faire et de préférence sans avoir à recomplier Mantle, je veux bien l’astuce à des fins de connaissance personnelle. :)


Page suivante »