/*
 * Copyright (c) Cyria creation 2004, 2005, 2006, 2007, 2008, 2009, 2010
 */
liste_dependances_modules = {
'menu_radial': ['menu', 'timer'],
'vendre': ['formulaire'],
'base.type_nourriture': [],
'menu_action': ['menu_radial', 'description', 'base.type_action', 'base.type_objet_nid', 'base.type_batiment'],
'skins': [],
'conseiller': ['mvc', 'ajax.xmlextras', 'cookie', 'base.type_conseil'],
'popup_personnage': ['description', 'infobulle', 'base.type_action'],
'village': ['infobulle', 'iframe'],
'message': [],
'base.type_param': [],
'iframe': ['timer'],
'epoz': [],
'menu': ['infobulle'],
'echoppe': ['description'],
'popup_recherche_perso': [],
'ajax.base': ['ajax.xmlextras'],
'ajax.xmlextras': ['ajax.sarissa', 'correctifs'],
'infos_perso': ['iframe'],
'popup_soins': ['menu_action', 'menu_radial', 'description', 'base.type_action', 'base.type_objet_nid', 'base.type_batiment', 'menu', 'timer', 'infobulle', 'jeu.inventaire_cache', 'base.type_objet_nid', 'base.type_nourriture', 'base.type_objet', 'base.type_batiment', 'base.type_action', 'infobulle'],
'base.type_batiment': [],
'popup': ['timer'],
'jeu.inventaire_cache': [],
'description': ['jeu.inventaire_cache', 'base.type_objet_nid', 'base.type_nourriture', 'base.type_objet', 'base.type_batiment', 'base.type_action', 'infobulle'],
'formulaire': [],
'infobulle': ['timer'],
'cookie': [],
'nid': ['mvc', 'base.type_objet_nid'],
'nid_connecte': ['nid', 'mvc', 'menu_action', 'base.type_objet_nid', 'description'],
'base.menu_echoppe': [],
'popup_boiteauxlettres_recu': [],
'correctifs': ['ajax.ajax'],
'timer': [],
'mesquineries': [],
'mvc': [],
'popup_rechercher_cible': [],
'manuel': [],
/* ajout manuel */
'ajax.ajax': [],
'ajax.sarissa': [],
'base.type_action': [],
'base.type_conseil': [],
'base.type_objet': [],
'base.type_objet_nid': []
}

function Global ()
{
}

Global.DEBUG = true;
Global._contexte = this;

Global.assert = function (test)
{
	if (Global.DEBUG && !test)
		alert ('assertion failed in ' + Global.assert.caller);
}

Global.publier = function (nom, valeur)
{
	Global.assert (nom);
	Global.assert (valeur);
//	Global.assert (!Global._contexte[nom]);

	Global._contexte[nom] = valeur;
}

Global.publierContexte = function (contexte)
{
	Global.Global.assert (contexte);
	
	for (var nom in contexte) {
		/* correctif surcharge prototype Object de vcXMLRPC
		 * importe par Epoz */
		if (nom == 'toXMLRPC')
			continue;

		if (nom.indexOf ('_') != 0)
			Global._contexte[nom] = contexte[nom];
	}
}

/**
 * Enrobe un appel de methode pour contourner l'acces impossible a this lors
 * d'un rappel d'evenement
 * @param objet   l'objet sur lequel appliquer la methode
 * @param methode la methode a appeler
 */
Global.associer = function (objet, methode) 
{
	Global.assert (objet);
	Global.assert (methode);

	return function () {
		return methode.apply (objet, arguments);
	};
}

/**
 * Affiche un message de deboggage horodate dans une fenetre de deboggage.
 * @param message le message a afficher
 */
Global.journal = function (message)
{
	var fenetre = window.open ('', 'journal');
	if (!fenetre)
		alert ('Echec d\'ouverture de la fenetre '
		       + 'du journal de deboggage');

	var date = new Date().toLocaleTimeString ();
	fenetre.document.write (date + ' ' + message + '<br />');
}

Global._est_definition = false;
Global.estDefinition = function () 
{
	return Global._est_definition;
}

Global.heriter = function (classe_fille, classe_mere)
{
	Global.assert (!Global.estDefinition ());
	Global.assert (classe_fille);
	Global.assert (classe_mere);

	Global._est_definition = true;
	classe_fille.prototype = new classe_mere;
	Global._est_definition = false;
}

function Module (nom, dependances, styles, definition)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (nom);
	Global.assert (dependances);
	Global.assert (styles);
	Global.assert (definition);

	this._nom = nom;
	this._dependances = dependances;
	this._definition = definition;

	Module._ajouter (this);

	Module._prechargerDependancesModules (nom);

	for (var i = 0; i < dependances.length; i++)
		Module.charger (Module._url (dependances[i]));

	for (var i = 0; i < styles.length; i++)
		Module.chargerStyle (styles[i]);

	if (this._estPret ())
		this._interpreter ();
}

/* FIXME : optimisation */
Module._prechargerDependancesModules = function (nom_module)
{
	Global.assert (nom_module);

	for (var i = 0; i < liste_dependances_modules[nom_module].length;i++) {
		var nom_sous_module = liste_dependances_modules[nom_module][i];
		
/* 		Module._prechargerDependancesModules (nom_sous_module); */
		Module.charger (Module._url(nom_sous_module));
	}
}

Module.prototype._valNom = function () 
{
	Global.assert (this._nom);
	
	return this._nom;
}

Module.prototype._valDependances = function ()
{
	Global.assert (this._dependances);
	
	return this._dependances;
}

Module.prototype._valDefinition = function () 
{
	Global.assert (this._definition);
	
	return this._definition;
}

Module.prototype._dependDe = function (nom)
{
	Global.assert (nom);
	
	return this._valDependances ().find (nom) != -1;
}

Module.prototype._estInterprete = function () 
{
	return !this._definition;
}

Module.prototype._estPret = function ()
{
	var dependances = this._valDependances ();
	for (var i = 0; i < dependances.length; i++) {
		var nom = dependances[i];

		if (!Module._estCharge (nom))
			return false;

		var module = Module._valModule (nom);
		if (!module._estInterprete ())
			return false;
	}

	return true;
}

Module.prototype._interpreter = function ()
{
	if (this._definition == null)
		return;

	var definition = this._valDefinition ();
	definition ();
	this._definition = null;

	this._interpreterDependants ();

	var nom = this._valNom ();
	Module._notifierFinChargement (Module._url (nom));	
}

Module.prototype._interpreterDependants = function ()
{
	for (var nom in Module._modules) {
		/* correctif surcharge prototype Object de vcXMLRPC
		 * importe par Epoz */
		if (nom == 'toXMLRPC')
			continue;

		var module = Module._valModule (nom);

		if (module._dependDe (this._valNom ()) && module._estPret ())
			module._interpreter ()
	}
}

Module._en_attente = new Array ();
Module._modules = new Object ();

Module._ajouter = function (module)
{
	Global.assert (module);
	Global.assert (Module._modules);

	var nom = module._valNom ();

	Global.assert (!Module._estCharge (nom));

	Module._modules[nom] = module;
}

Module._estCharge = function (nom) 
{
	Global.assert (nom);
	Global.assert (Module._modules);
	
	return Boolean (Module._modules[nom]);
}

Module._valModule = function (nom)
{
	Global.assert (nom);
	Global.assert (Module._modules);
	Global.assert (Module._estCharge (nom));
	
	return Module._modules[nom];
}

Module.chargementsSontTermines = function ()
{
	Global.assert (Module._en_attente);

	return Module._en_attente.length == 0;
}

Module._notifierAttente = function (adresse)
{
	Global.assert (Module._en_attente);
	
	Module._en_attente.push (adresse);
}

Module._estEnAttente = function (adresse) 
{
	Global.assert (adresse);
	Global.assert (Module._en_attente);

	return Module._en_attente.find (adresse) != -1;
}

Module._notifierFinChargement = function (adresse)
{
	Global.assert (adresse);
	Global.assert (Module._en_attente);
//	Global.assert (!Module.chargementsSontTermines ());

	if (!Module._estEnAttente (adresse))
		return;

	Module._en_attente.remove (adresse);
	if (Module.chargementsSontTermines ())
		Init.lancerTemporisation ();
}

Module._estEnChargement = function (adresse)
{
	Global.assert (adresse);

	var scripts = document.getElementsByTagName ('script');
	var regexp = new RegExp (adresse + '$');
	for (var i = 0; i < scripts.length; i++) {
		if (regexp.test (scripts[i].src))
			return true;
	}

	return false;
}

function serialiser (elt)
{
	var serialisation_fils = '';
	for (var i=0; i < elt.childNodes.length; i++)
		serialisation_fils += serialiser (elt.childNodes[i]);

	var serialisation_attributs = '';
	for (var i=0; elt.attributes && i < elt.attributes.length; i++) {
		if (!/^on/.test (elt.attributes[i].name)
		    && elt.attributes[i].value)
			serialisation_attributs += ' ' + elt.attributes[i].name
				+ '=' + elt.attributes[i].value;
	}

	return '<' + elt.tagName + ' (' + elt.nodeName  + ')'
		+ serialisation_attributs + '>\n'
		+ (elt.data ? elt.data : '')
		+ serialisation_fils
		+ '</' + elt.tagName + '>\n';
}

Module.charger = function (adresse)
{
	Global.assert (adresse);

	if (Module._estCharge (Module._nom (adresse))
	    || Module._estEnChargement (adresse))
		return;

	Init.arreterTemporisation ();
	Module._notifierAttente (adresse);

	if (adresse.indexOf ('jeu') == -1
	    && adresse.indexOf ('base') == -1)
		adresse = ('http://ressources' + (adresse.length % 4)
			   + '.nutsy.net'
			   + adresse);

	if (/MSIE/.test (navigator.userAgent)
	    && document.getElementById ('correctif_ie_ajout_entete')) { /* correctif ie */
		var head = document.getElementsByTagName ('head')[0];
		document.write ('<script src="' + adresse + '" language="javascript" type="text/javascript"></script>');
	} else {
		var elt = document.createElement ('script');
		elt.src = adresse;
		elt.language = 'javascript';
		elt.type = 'text/javascript';
		var head = document.getElementsByTagName ('head')[0];
		head.appendChild (elt);
	}
}

Module.chargerStyle = function (adresse)
{
	Global.assert (adresse);

	if (/MSIE/.test (navigator.userAgent)
	    && document.getElementById ('correctif_ie_ajout_entete')) { /* correctif ie */
		var head = document.getElementsByTagName ('head')[0];
		document.write ('<link href="' + adresse + '" rel="stylesheet" type="text/css" />');
	} else {
		var elt = document.createElement ('link');
		elt.href = adresse;
		elt.rel = 'stylesheet';
		elt.type = 'text/css';
		var entete = document.getElementsByTagName ('head')[0];
		entete.appendChild (elt);
	}
}

Module._nom = function (nom) 
{
	Global.assert (nom);
	
	return nom.replace(/^.*\/scripts\/(.*)\.js$/, '$1').replace ('/', '.');
}

Module._url = function (nom)
{
	Global.assert (nom);
	
	return '/scripts/' + nom.replace ('.', '/') + '.js';
}

/*
 * Initialisation
 */

function Init () 
{
}

Init._rappels = new Array ();
Init._rappels_fixes = new Array ();
Init._temporisation = null;
Init._page_est_chargee = false;

Init._pageEstChargee = function ()
{
	return Init._page_est_chargee;
}

Init.ajouterRappel = function (rappel, fixe)
{
	Global.assert (Init._rappels);
	Global.assert (Init._rappels_fixes);

	if (fixe)
		Init._rappels_fixes.push (rappel);
	else
		Init._rappels.push (rappel);
}

Init._init = function ()
{
	Global.assert (Init._rappels);
	Global.assert (Init._rappels_fixes);
	Global.assert (Init._pageEstChargee ());
	Global.assert (Module.chargementsSontTermines ());
	
	for (var i = 0; i < Init._rappels.length; i++) {
//		Global.journal ('Debut : ' + Init._rappels[i]);
		Init._rappels[i]();
//		Global.journal ('--> Fin');
	}
	Init._rappels = new Array ();

	for (var i = 0; i < Init._rappels_fixes.length; i++) {
//		Global.journal ('Debut Fixe : ' + Init._rappels_fixes[i]);
		Init._rappels_fixes[i]();
//		Global.journal ('--> Fin');
	}

	Init._page_est_chargee = false;
}


Init.lancerTemporisation = function () 
{
	if (!Init._pageEstChargee ()
	    || !Module.chargementsSontTermines ())
		return;

	if (Init._temporisation)
		Init.arreterTemporisation ();
	
	Init._temporisation = setTimeout (Init._init, 0);
}

Init.arreterTemporisation = function ()
{
	if (Init._temporisation)
		clearTimeout (Init._temporisation);
	
	Init._temporisation = null;
}

Init.finChargementPage = function ()
{
	/* FIXME - balise script interpretee 2 fois en xml */
//	Global.assert (!Init._pageEstChargee ());
	
	Init._page_est_chargee = true;
	Init.lancerTemporisation ();
}


/*
 * Ajout de fonctionalites aux objets de base
 */

Array.prototype.find_cmp = function (val, cmp)
{
	Global.assert (val);
	Global.assert (cmp);

	for (var i = 0; i < this.length; i++) {
		if (cmp (val, this[i]))
			return i;
	}
	
	return -1
}

Array.prototype.find = function (val) 
{
	Global.assert (val);

	return this.find_cmp (val,
			      function (val, elt) { return val == elt });
}

Array.prototype.remove = function (val) 
{
	Global.assert (val);

	this.splice (this.find (val), 1);
}

String.prototype.capitalize = function ()
{
	if (this == '')
		return '';
	else
		return this.substring (0, 1).toUpperCase () + this.slice (1);
}

function search_cmp (obj, val, cmp)
{
	Global.assert (obj);
	Global.assert (val);
	Global.assert (cmp);

	for (var clef in obj) {
		/* correctif surcharge prototype Object de vcXMLRPC
		 * importe par Epoz */
		if (clef == 'toXMLRPC')
			continue;

		if (cmp (val, obj[clef]))
			return clef;
	}

	return null;
}

function clamp (val, min, max) 
{
	return Math.max (Math.min (val, max), min);
}

var _topDocument = null;
function topDocument ()
{
	if (!_topDocument)
		_topDocument = window.top.document || document;

	return _topDocument;
}

/*
 * Manipulation calque
 */

/**
 * Retourn la valeur associee au style donne.
 * cf http://www.faqts.com/knowledge_base/view.phtml/aid/1780
 * @param elt l'element sur lequel recuperer le style
 * @param nom le nom du style, attention celui-ci ne doit pas etre compose
 * @return la valeur
 */
function style (elt, nom) 
{
	Global.assert (elt);
	Global.assert (nom);
	Global.assert (nom.indexOf ('-') == -1);

	if (elt.style[nom]) {
		return elt.style[nom];
	} else if (document.defaultView) {
		var style = document.defaultView.getComputedStyle (elt, '');
		return style.getPropertyValue (nom);
	} else if (elt.currentStyle) {
		return elt.currentStyle[nom];
	}
}

function scroll_x ()
{
	return window.pageXOffset
		|| document.documentElement.scrollLeft
		|| document.body.scrollLeft;
}

function scroll_y ()
{
	return window.pageYOffset
		|| document.documentElement.scrollTop
		|| document.body.scrollTop;
}

/* cf http://www.faqts.com/knowledge_base/view.phtml/aid/1001/fid/128
 * FIXME : bogue ie7 position fixed
 */
function min_x (elt)
{
	Global.assert (elt);
	Global.assert (elt.parentNode);

	var debut = elt;
	var left = 0;

	while (elt.offsetParent) {
		left += elt.offsetLeft - elt.scrollLeft;

		if (style (elt, 'position') == 'fixed')
			left += scroll_x ();

		elt = elt.offsetParent;
	}

	if (!document.all) {
		elt = debut;
		while (elt.parentNode
		       && elt.parentNode.tagName != 'BODY') {
			left -= elt.parentNode.scrollLeft;
			elt = elt.parentNode;
		}
	}

	return left;
}

function max_x (elt)
{
	Global.assert (elt);
	Global.assert (elt.parentNode);

	return min_x (elt) + elt.offsetWidth;
}

function min_y (elt)
{
	Global.assert (elt);
	Global.assert (elt.parentNode);

	var debut = elt;
	var top = 0;

	while (elt.offsetParent) {
		top += elt.offsetTop - elt.scrollTop;

		if (style (elt, 'position') == 'fixed')
			top += scroll_y ();

		elt = elt.offsetParent;
	}

	if (!document.all) {
		elt = debut;
		while (elt.parentNode
		       && elt.parentNode.tagName != "BODY") {
			top -= elt.parentNode.scrollTop;
			elt = elt.parentNode;
		}
	}

	return top;
}

function max_y (elt)
{
	Global.assert (elt);
	Global.assert (elt.parentNode);

	return min_y (elt) + elt.offsetHeight;
}

function survole (evt, elt)
{
	return event_x (evt) >= min_x (elt)
		&& event_y (evt) >= min_y (elt)
		&& event_x (evt) <= max_x (elt)
		&& event_y (evt) <= max_y (elt);
}

function contient (elt1, elt2)
{
	return min_x (elt1) <= min_x (elt2) && max_x (elt1) >= max_x (elt2)
	       && min_y (elt1) <= min_y (elt2) && max_y (elt1) >= max_y (elt2);
}

function chevauche (elt1, elt2)
{
	return !(max_x (elt1) <= min_x (elt2) || max_x (elt2) <= min_x (elt1)
	      || max_y (elt1) <= min_y (elt2) || max_y (elt2) <= min_y (elt1));
}

function changer_opacite (elt, opacite)
{
	elt.style.opacity = opacite;
	elt.style.MozOpacity = opacite;
	if (elt.filters)
		elt.style.filter = 'alpha(opacity=' + opacite * 100 + ')';
}

function frame_x (window)
{
	var left = 0;
	while (window.frameElement) {
		left += min_x (window.frameElement);
		window = window.parent;
	}
	return left;
}

function frame_y (window)
{
	var top = 0;
	while (window.frameElement) {
		top += min_y (window.frameElement);
		window = window.parent;
	}
	return top;
}

function zone_temporaire_ajouter (elt, doc)
{
	Global.assert (elt);

	if (!doc)
		doc = document;

	var zone_temporaire = doc.getElementById ('zone_temporaire');
	if (!zone_temporaire) {
		zone_temporaire = doc.createElement ('div');
		zone_temporaire.id = 'zone_temporaire';
		doc.body.appendChild (zone_temporaire);
	}
	
	zone_temporaire.appendChild (elt);
}

function zone_temporaire_vider ()
{
	var zone_temporaire = document.getElementById ('zone_temporaire');

	if (zone_temporaire)
		zone_temporaire.parentNode.removeChild (zone_temporaire);
}

/*
 * Gestion evenements
 */

function evenement_attacher (elt, type, rappel)
{
	Global.assert (elt);
	Global.assert (type);
	Global.assert (rappel);

	if (elt.addEventListener) {
		elt.addEventListener (type, rappel, false);
	} else if (elt.attachEvent) {
		elt.attachEvent ('on' + type,
				 Global.associer (elt, rappel));
	} else {
		Global.assert (!elt['on' + type]);
		elt['on' + type] = rappel;
	}
}

function evenement_supprimer (elt, type, rappel) 
{
	Global.assert (elt);
	Global.assert (type);
	Global.assert (rappel);

	if (elt.removeEventListener) {
		elt.removeEventListener (type, rappel, false);
	} else if (elt.attachEvent) {
		elt.removeEvent ('on' + type, rappel);
	} else {
		Global.assert (elt['on' + type] == rappel);
		elt['on' + type] = null;
	}
}

function event_x (evt)
{
	Global.assert (evt);


	return (evt.pageX ? evt.pageX : evt.clientX + scroll_x ())
}

function event_y (evt)
{
	Global.assert (evt);

	return (evt.pageY ? evt.pageY : evt.clientY + scroll_y ())
}

function event_target (evt)
{
	Global.assert (evt);

	return evt.target || evt.srcElement;
}

function event_window (evt)
{
	Global.assert (evt);

	return evt.view
		|| event_target (evt).ownerDocument.parentWindow;
}

function event_stop_propagation (evt)
{
	if (!evt) var evt = window.event;
	evt.cancelBubble = true;
	if (evt.stopPropagation)
		evt.stopPropagation ();
}

function event_is_mouse_out (evt)
{
	if (!evt) var evt = window.event;
	var target = evt.target || evt.srcElement;
	
	if (target != ul)
		return false;
	
	var relatedTarget = evt.relatedTarget || evt.toElement;
	while (relatedTarget != target
	       && relatedTarget.parentNode) {
		relatedTarget = relatedTarget.parentNode;
	}
	if (relatedTarget == target)
		return false;

	return true;
}

/*
 * Dialogue serveur
 */

function serveur_appeler (page)
{
	Global.assert (page);
	Global.assert (arguments.length % 2 == 1);

	var url = page;

	for (var i = 1; i < arguments.length; i+=2) {
		url += (i == 1 ? '?' : '&')
			+ arguments[i] + '=' + escape(arguments[i+1]);
	}

	var iframe;
/* 	if ( !(iframe = document.getElementById ('__acces_serveur')) ) { */
		iframe = document.createElement ('iframe');
/* 		iframe.setAttribute ('id', '__acces_serveur'); */
		iframe.style.display = 'none';
		zone_temporaire_ajouter (iframe);
/* 	} */

	iframe.contentWindow.location = url;
}

/**
 * Appelle une page sur le serveur.
 * Fonction historique.
 * @param url l'adresse de base de la page a appeler
 * @param ... une liste de parametres a ajouter a l'url par paire
 *            de titre, valeur
 */
/* function serveur_appeler (url) */
/* { */
/* 	Global.assert (url); */
/* 	Global.assert (arguments.length % 2 == 1); */

/* 	var url = XML.construireURL.apply (this, arguments); */
/* 	XML.charger (url, */
/* 		     new Function ()); */
/* } */

/*
 * Actions
 */

/**
 * Execute une action du jeu.
 * @param evt             l'evenement click de souris qui declenche l'action
 * @param ref_type_action la reference du type de l'action
 * @param ...             parametres : paires composees du nom du parametre
 *                        suivi de la valeur
 *                        ceux-ci ne doivent contenir aucun espace
 * @return false, pour arreter le traitement de l'evenement
 */
function action_executer (evt, ref_type_action)
{
	Global.assert (ref_type_action > 0);
	Global.assert (arguments.length % 2 == 0);

	var params = '';
	for (var i = 2; i < arguments.length; i+=2) {
		params += (params ? ' ' : '')
			+ arguments[i] + ' ' + arguments[i+1];
	}

	var location = '/jeu/action/proc_action_executer'
		+ '?ref_type_action:int='
		+ ref_type_action
		+ '&params:tokens=' + escape (params);
	
	iframe_surgir (evt, location);

	return false;
}

//Module.charger (Module._url ('ajax.ajax'));
//Module.charger (Module._url ('correctifs'));
//Module.charger (Module._url ('iframe'));
//Module.charger (Module._url ('popup'));

new Module ('ajax.ajax',
	    [], // 'ajax.xmlextras' dependance cyclique
	    [],
	    function () {

/*
 * Fonctions ajax
 */

function Ajax ()
{
}
Global.publier ('Ajax', Ajax);

Ajax._fixer_chemin_relatif_noeud = function (noeud, attribut, base)
{
	Global.assert (noeud);
	Global.assert (base);

	if (noeud.getAttribute (attribut)
	    && !/^(\w+:|\/|#)/.test (noeud.getAttribute (attribut))) {
		Global.journal (attribut + ': '
				+ noeud.getAttribute(attribut));
		noeud.setAttribute (attribut,
				    base + noeud.getAttribute (attribut));
		Global.journal ('-> ' + noeud.getAttribute (attribut));
	}
}

Ajax._fixer_chemins_relatifs = function (reponseXML, adresse)
{
	Global.assert (reponseXML);
	Global.assert (adresse);

	var base = adresse.split ('?')[0];
	base = base.substring(0, base.lastIndexOf ('/')) + '/';
	var corrections = {
		'action': ['form'],
		'background': ['body'],
		'cite': ['blockquote', 'q', 'del', 'ins'],
		'classid': ['object'],
		'codebase': ['object', 'applet'],
		'data': ['object'],
		'href': ['a', 'area', 'link', 'base'],
		'longdesc': ['img', 'frame', 'iframe'],
		'profile': ['head'],
		'src': ['script', 'input', 'frame', 'iframe', 'img'],
		'usemap': ['img', 'input', 'object']
	};

	for (var attribut in corrections) {
		/* correctif surcharge prototype Object de vcXMLRPC
		 * importe par Epoz */
		if (attribut == 'toXMLRPC')
			continue;

		for (var i = 0; i < corrections[attribut].length; i++) {
			var nom = corrections[attribut][i];
			var noeuds = reponseXML.getElementsByTagName (nom);
			for (var j = 0; j < noeuds.length; j++)
				Ajax._fixer_chemin_relatif_noeud (noeuds[j],
								  attribut,
								  base);

		}
	}
}

/**
 * Lors d'un raffraichissement d'une page chargee de facon differentielle,
 * redirige vers la page reelement affichee
 */
Ajax.rediriger_page_ajax = function () 
{
	var url = document.location.href;
	var marqueur_redirection = '#page:';
//	alert ('4:' + window.location.href);
	if (url.indexOf (marqueur_redirection) != -1) {
		var elements = url.split (marqueur_redirection);
		Global.assert (elements.length >= 1 && elements.length <= 2);
		document.location.replace (elements[elements.length - 1]);
	}
}
Ajax.rediriger_page_ajax ();


Ajax._rappelChargement = function (iframe, rappel)
{
	Global.assert (iframe);
	Global.assert (rappel);

	if (iframe.contentWindow.document.readyState == 'complete') {
		rappel ();
	} else {
		setTimeout (function () {
			Ajax._rappelChargement (iframe, rappel);
		}, 100);
	}
}

Ajax.appliquerTransformation = function (url, style, doc, rappel)
{
	Global.assert (url);
	Global.assert (style);

	if (!doc)
		doc = document;

	var iframe = doc.getElementById ('chargement');
	Global.assert (iframe);
	Global.assert (iframe.tagName.toLowerCase () == 'iframe');

	rappel_appliquer = function () {
		var reponseXML = iframe.contenDocument
				 || iframe.contentWindow.document;

//		XML._appliquerTransformationRappel (doc, reponseXML, style);

//		document.getElementById ('titre').innerHTML
//			=  reponseXML.getElementsByTagName ('title')[0].innerHTML;

		document.getElementById ('entete').innerHTML
			=  reponseXML.getElementsByTagName ('head')[0].innerHTML;

		document.getElementById ('bandeau_gauche').innerHTML
			=  reponseXML.getElementById ('bandeau_gauche').innerHTML;
		document.getElementById ('contenu').innerHTML
			= (reponseXML.getElementById ('contenu').innerHTML
			   + '<script type="text/javascript">'
			   + 'Init.finChargementPage ();'
			   + '</script>');

		if (rappel)
			rappel (reponseXML);
	}

	var content = iframe.contentDocument || iframe.contentWindow;
	content.location = url;

	if (iframe.document)
		Ajax._rappelChargement (iframe, rappel_appliquer);
	else
		iframe.onload = rappel_appliquer;
}

/**
 * Met a jour de facon differentielle la page courante, sans recharger
 * tout le document
 * @param adresse l'adresse du document a charger
 */
Ajax.chargerPage = function (adresse)
{
	Global.assert (adresse);

	window.adresse_ajax = adresse.replace ('async=1', '');
	zone_temporaire_vider ();

	var rappel = function (reponseXML) {
//		_fixer_chemins_relatifs (reponseXML, adresse);

		var hote = (document.location.protocol + '//'
			    + document.location.hostname);
		document.location = '#page:' + adresse.replace (hote, '');

/* 		var titres = document.getElementsByTagName ('title'); */
/* 		Global.assert (titres.length == 1); */
/* 		Global.assert (titres[0].childNodes.length == 1); */
/* 		Global.assert (titres[0].firstChild.nodeType == 3); //Node.TEXT_NODE) */
/* 		document.title = titres[0].firstChild.nodeValue; */

		window.scrollTo (0,0)
	};
	var url = adresse
		+ (adresse.indexOf ('?') == -1 ? '?' : '&') + 'async=1';

	XML.appliquerTransformation (url,
				      '/styles/copie.xsl',
				      document,
				      rappel);
}

});

new Module ('correctifs',
	    ['ajax.ajax'],
	    [],
	    function () {

/**
 * Parcours des feuilles de styles lors de l'initialisation.
 */
function Styles ()
{
}

Styles._rappels = new Array ();

/**
 * Ajouter une fonction de rappel appelee lors du parcours.
 * @param rappel la fonction de rappel
 */
Styles.ajouterRappelParcours = function (rappel)  
{
	Global.assert (rappel);
	Global.assert (Styles._rappels);

	Styles._rappels.push (rappel);
}

/**
 * Applique la regle a toutes les fonctions de rappel.
 * @param regle la regle css
 */
Styles._parcoursRappel = function (regle)
{
	Global.assert (regle);
	Global.assert (Styles._rappels);

	for (var i = 0; i < Styles._rappels.length; i++)
		Styles._rappels[i] (regle);
}

/**
 * Parcours toutes les regles des feuilles de style.
 */
Styles.parcours = function()
{
	Global.assert (Styles._rappels);

	if (Styles._rappels.length == 0)
		return;

	for (var i = 0; i < document.styleSheets.length; i++) {
		var feuille = document.styleSheets[i];

		if (feuille._est_deja_parcourue)
			continue;
		
		feuille._est_deja_parcourue = true;

		var regles = feuille.cssRules || feuille.rules;
		
		for (var j = 0; j < regles.length; j++) {
			if (!regles[j].type // correctif ie
			    || regles[j].type == 1) // CSSRule.STYLE_RULE
				Styles._parcoursRappel (regles[j]);
		}
	}
}
Init.ajouterRappel (Styles.parcours, true);

/**
 * Gestion du prechargement des images d'apres les feuilles de style.
 * Les fonds a precharger 
 */
function Prechargement ()
{
}

Prechargement._images = new Array ();

/**
 * Precharge une image.
 * @param adresse l'adresse de l'image
 */
Prechargement._prechargerImage = function (adresse)
{
	Global.assert (adresse);
	
	adresse = adresse.replace('url(','').replace(')','');

	var image = new Image ();
	image.src = adresse;

	Prechargement._images.push (image);
}

/**
 * Parcours une regle de la feuille de style afin de savoir s'il faut
 * precharger le fond.
 * @param regle la regle css a etudier
 */
Prechargement._init = function (regle)
{
	Global.assert (regle);

	if (regle.selectorText.indexOf ('preload') != -1
	    && regle.style.backgroundImage)
		Prechargement._prechargerImage (regle.style.backgroundImage);
}
/* Styles.ajouterRappelParcours (Prechargement._init); */

/**
 * Correctifs pour les differents navigateurs.
 */
var Correctifs = function ()
{
}
Global.publier ('Correctifs', Correctifs);

Correctifs.INTERNET_EXPLORER = 1;
Correctifs.MOZILLA = 2;

Correctifs.WINDOWS = 1;
Correctifs.LINUX = 2;
Correctifs.UNIX = 3;
Correctifs.MAC = 4;

/**
 * Retourne la description complete de l'agent du client.
 */
Correctifs.valAgent = function ()
{
	return navigator.userAgent.toLowerCase ();
}

/**
 * Retourne le nom du navigateur du client.
 */
Correctifs.valNavigateur = function () 
{
	var agent = Correctifs.valAgent ();

	if (/msie/.test (agent))
		return Correctifs.INTERNET_EXPLORER;
	else if (/mozilla/.test (agent))
		return Correctifs.MOZILLA;
	else
		return null;
}

/**
 * Retourne le nom du systeme d'exploitation du client.
 */
Correctifs.valSysteme = function ()
{
	var agent = Correctifs.valAgent ();

	if (/win/.test (agent))
		return Correctifs.WINDOWS;
	else if (/linux/.test (agent))
		return Correctifs.LINUX;
	else if (/x11/.test (agent))
		return Correctifs.UNIX;
	else if (/mac/.test (agent))
		return Correctifs.MAC;
	else
		return null;
}

/**
 * Corrige le support de la transparence suivant la propriete css3 opacity,
 * pour Internet Explorer.
 * @param regle la regle css a corriger
 */
Correctifs._ie_opacite = function (regle)
{
	Global.assert (regle);	

	var opacite = regle.style.opacity;
	if (typeof opacite != 'undefined' && opacite) 
		regle.style.filter = 'alpha(opacity=' + opacite * 100 + ')';
}
/*
 * desactive pour raison de cout
 */
/* if (Correctifs.valNavigateur () == Correctifs.INTERNET_EXPLORER) */
/* 	Styles.ajouterRappelParcours (Correctifs._ie_opacite); */

/**
 * Corrige le support de la transparence suivant la propriete css3 opacity,
 * pour Mozilla.
 * @param regle la regle css a corriger
 */
Correctifs._moz_opacite = function (regle)
{
	Global.assert (regle);	

	var opacite = regle.style.opacity;
	if (typeof opacite != 'undefined' && opacite)
		regle.style.MozOpacity = opacite;
}
/*
 * desactive pour raison de cout
 */
/* if (Correctifs.valNavigateur () == Correctifs.MOZILLA */
/*     && ! /rv:1\.4/.test (Correctifs.valAgent ())) { */
/* 	Styles.ajouterRappelParcours (Correctifs._moz_opacite); */
/* } */

/**
 * Supprime la transparence sous Mozilla 1.4 pour pallier a un support incorrect
 * sur certaines versions.
 * @param regle la regle css a corriger
 */
Correctifs._moz_1_4_opacite = function (regle)
{
	Global.assert (regle);
	
	if (typeof regle.style.MozOpacity != 'undefined'
	    && regle.style.MozOpacity)
		regle.style.MozOpacity = null;
}
if (Correctifs.valNavigateur () == Correctifs.MOZILLA
    && /rv:1\.4/.test (Correctifs.valAgent ())) {
	Styles.ajouterRappelParcours (Correctifs._moz_1_4_opacite);
}

/**
 * Corrige le support de la transparence pour les pngs 24 bits sous IE.
 * Attention ! Cela cree un bogue avec les liens contenus a l'interieur
 * des elements associes au style, il faut alors passer leur position
 * a relative.
 * @param regle la regle css a corriger
 */
Correctifs._ie_png_transparent = function (regle)
{
	Global.assert (regle);

	if (typeof regle.style.backgroundImage == 'undefined'
	    || !regle.style.backgroundImage)
		return;

	var adresse = regle.style.backgroundImage;
	adresse = adresse.replace('url(','').replace(')','');

	if (!/-trans\.png$/.test (adresse))
		return;

	regle.style.filter
		= ('progid:DXImageTransform.Microsoft.AlphaImageLoader('
		   + 'src=\'' + adresse + '\','
		   + 'sizingMethod=\'crop\''
		   + ')');
	regle.style.backgroundImage = 'none';
	/* correctif disparition fond ie */
	regle.style.zoom = '1';
}
/*
 * desactive pour raison de cout
 */
/* if (Correctifs.valNavigateur () == Correctifs.INTERNET_EXPLORER) */
/* 	Styles.ajouterRappelParcours (Correctifs._ie_png_transparent); */

/**
 * Un element flash est-il transparent.
 * @param elt l'element dom a etudier
 * @return si l'element est transparent
 */
Correctifs._flashEstTransparent = function (elt)
{
	Global.assert (elt);

	if (elt.id == 'banniere_pub'
	    || elt.id == 'banniere_accueil'
            || elt.id == 'banniere_boutique'
	    || elt.className == 'animation_tutoriel')
		return false;

	var fils = elt.firstChild;
	while (fils) {
		if ((fils.tagName == 'PARAM' || fils.tagName == 'param')
		    && fils.name == 'wmode' && fils.value == 'transparent')
			return true;
			
		fils = fils.nextSibling;
	}

	return false;
}

/**
 * Supprime les flashs transparents sous Linux afin de pallier aux
 * problemes du greffon de macromedia.
 */
Correctifs._moz_linux_transparence_flash = function ()
{
	var objets = document.getElementsByTagName ('object');

	for (var i = 0; i < objets.length; i++) {
		var elt = objets[i];

		if (/flash/.test (elt.codeBase)
		    && Correctifs._flashEstTransparent (elt))
			elt.style.display = 'none';
	}
}
if (Correctifs.valSysteme () == Correctifs.LINUX)
	Init.ajouterRappel (Correctifs._moz_linux_transparence_flash, true)

Correctifs._ie_flash = function ()
{
	var objets = document.getElementsByTagName ('object');

	for (var i = 0; i < objets.length; i++) {
		var elt = objets[i];

		var span = document.createElement('span');
		span.innerHTML = elt.outerHTML;
		elt.parentElement.replaceChild (span, elt);
	}
}
if (Correctifs.valNavigateur () == Correctifs.INTERNET_EXPLORER)
	Init.ajouterRappel (Correctifs._ie_flash);

/**
 * Transforme les liens du document afin de realiser uniquement une chargement
 * differentiel de la nouvelle page.
 * Ignore les liens lies a du javascript, ou ne portant pas l'extension .html.
 */
Correctifs._transformerLiensAjax = function ()
{
	var liens = document.getElementsByTagName ('a');
	
	for (var i = 0; i < liens.length; i++) {
		var elt = liens[i];
		var hote = (document.location.protocol + '//'
			    + document.location.hostname);
		
		if (!elt.onclick
		    && elt.href
		    && (/\.html(\?.*|#.*)?$/.test (elt.href)
			|| /\/forum\/$/.test (elt.href))
		    && elt.href.indexOf ('javascript:') == -1
		    && elt.href.indexOf ('#') != 0
		    && elt.href.indexOf (document.location + '#') != 0) {
			var rappel = function (evt) {
				Ajax.chargerPage (this.href);
				return false;
			};
			elt.onclick = rappel;
		}
	}
}
/*
 * Chargement asynchrone desactive pour cause de problemes sous IE
 */
/* Init.ajouterRappel (function () { */
/* 	if (document.getElementById ('correctif_transformer_liens_ajax')) */
/* 		Correctifs._transformerLiensAjax (); */
/* }, true); */

/*
 * Le slot entete est genere par defaut dans le corps (body) du document
 * pour contourner un bogue d'interpretaiton d'ie, mais cela pose des problemes
 * sous Mozilla et il doit donc etre redeplace derriere.
 */
Correctifs._deplacerSlotEntete = function (resultat)
{
	var entete = document.getElementById ('entete');
	if (entete) {
		var head = document.getElementsByTagName ('head')[0];
		head.appendChild (entete);
	}
}
/*
 * Chargement asynchrone desactive pour cause de problemes sous IE
 */
/* if (Correctifs.valNavigateur () == Correctifs.MOZILLA) */
/* 	Init.ajouterRappel (Correctifs._deplacerSlotEntete, false); */

Correctifs.ieInterpreterScripts = function (resultat)
{
	Global.assert (resultat);
	
	var scripts = resultat.getElementsByTagName ('script');
	var liste = new Array ();
	for (var i = 0; i < scripts.length; i++)
		liste.push (scripts[i]);

	for (var i = 0; i < liste.length; i++) {
		var ancien = liste[i];

		if (ancien.type != 'text/javascript')
			continue;
		
		var nouveau = resultat.createElement ('script');
		nouveau.language = 'javascript';
		nouveau.type = 'text/javascript';

		if (ancien.text)
			nouveau.text = ancien.text;
		else if (ancien.src)
			nouveau.src = ancien.src;

		ancien.parentNode.replaceChild (nouveau, ancien);
	}
}

/* function Correctifs._ie_position_fixed (elt) */
/* { */
/* 	if (elt.style.position != 'fixed') */
/* 		return; */
	
/* 	elt.style.position = 'absolute'; */
	
/* } */
/* dom_parcours_init_ajout_fonction (Correctifs._ie_position_fixed); */

/*
 * Correctif ie, pour classe :hover
 */

/* function _mouse_over (evt) */
/* { */
/* 	if (!evt) var evt = window.event; */
/* 	var elt = (evt.target ? evt.target : evt.srcElement); */

/* 	alert (over); */

/* 	elt.className_old = elt.className; */
/* 	elt.className = elt.className.replace (' ', ':hover ') + elt.className; */
/* } */

/* function _mouse_out (evt) */
/* { */
/* 	if (!evt) var evt = window.event; */
/* 	var elt = (evt.target ? evt.target : evt.srcElement); */

/* 	alert (out); */

/* 	elt.className = elt.className.old */
/* } */

/* function _class_search (name) */
/* { */
/* 	for (var i = 0; i < document.styleSheets.length; i++) { */
/* 		var rules = document.styleSheets[i].cssRules; */
/* 		if (!rules) */
/* 			rules = document.styleSheets[i].rules; */
		
/* 		if (rules[name]) */
/* 			return true; */
/* 	} */

/* 	return false; */
/* } */

/* function _mouse_over_enregistre (elt) */
/* { */
/* 	if (!elt.className) */
/* 		return; */

/* 	var classes = elt.className.split (' '); */

/* 	for (var i = 0; i < classes.length; i++) { */
/* 		if (elt.tag != 'a' */
/* 		    && _class_search (classes[i] + ':hover')) { */
/* 			alert (enregistre); */
/* 			elt.onmouseover = _mouse_over; */
/* 			elt.onmouseout = _mouse_out; */
/* 		} */
/* 	} */
/* } */

/* if (document.layers) */
/* 	dom_parcours_init_ajout_fonction (_mouse_over_enregistre); */
		
});

new Module ('ajax.sarissa',
	    [],
	    [],
	    function () {});

/**
 * ====================================================================
 * About
 * ====================================================================
 * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.
 * The library supports Gecko based browsers like Mozilla and Firefox,
 * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera
 * @version 0.9.7.6
 * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
 * ====================================================================
 * Licence
 * ====================================================================
 * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher, 
 * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher 
 * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If 
 * you make modifications under the ASL, i would appreciate it if you submitted those.
 * In case your copy of Sarissa does not include the license texts, you may find
 * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
 * <a href="http://www.apache.org">http://www.apache.org</a>.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * <p>Sarissa is a utility class. Provides "static" methods for DOMDocument, 
 * DOM Node serialization to XML strings and other utility goodies.</p>
 * @constructor
 */
function Sarissa(){};
Sarissa.PARSED_OK = "Document contains no parsing errors";
Sarissa.PARSED_EMPTY = "Document is empty";
Sarissa.PARSED_UNKNOWN_ERROR = "Not well-formed or other error";
var _sarissa_iNsCounter = 0;
var _SARISSA_IEPREFIX4XSLPARAM = "";
var _SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true;
var _SARISSA_HAS_DOM_CREATE_DOCUMENT = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument;
var _SARISSA_HAS_DOM_FEATURE = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature;
var _SARISSA_IS_MOZ = _SARISSA_HAS_DOM_CREATE_DOCUMENT && _SARISSA_HAS_DOM_FEATURE;
var _SARISSA_IS_SAFARI = (navigator.userAgent && navigator.vendor && (navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1 || navigator.vendor.indexOf("Apple") != -1));
var _SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1  && navigator.userAgent.toLowerCase().indexOf("opera") == -1;
if(!window.Node || !Node.ELEMENT_NODE){
    Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5,  ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12};
};

if(typeof XMLDocument == "undefined" && typeof Document !="undefined"){ XMLDocument = Document; } 

// IE initialization
if(_SARISSA_IS_IE){
    // for XSLT parameter names, prefix needed by IE
    _SARISSA_IEPREFIX4XSLPARAM = "xsl:";
    // used to store the most recent ProgID available out of the above
    var _SARISSA_DOM_PROGID = "";
    var _SARISSA_XMLHTTP_PROGID = "";
    var _SARISSA_DOM_XMLWRITER = "";
    /**
     * Called when the Sarissa_xx.js file is parsed, to pick most recent
     * ProgIDs for IE, then gets destroyed.
     * @private
     * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object
     * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled
     */
    Sarissa.pickRecentProgID = function (idList){
        // found progID flag
        var bFound = false;
        for(var i=0; i < idList.length && !bFound; i++){
            try{
                var oDoc = new ActiveXObject(idList[i]);
                o2Store = idList[i];
                bFound = true;
            }catch (objException){
                // trap; try next progID
            };
        };
        if (!bFound) {
            throw "Could not retreive a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")";
        };
        idList = null;
        return o2Store;
    };
    // pick best available MSXML progIDs
    _SARISSA_DOM_PROGID = null;
    _SARISSA_THREADEDDOM_PROGID = null;
    _SARISSA_XSLTEMPLATE_PROGID = null;
    _SARISSA_XMLHTTP_PROGID = null;
    if(!window.XMLHttpRequest){
        /**
         * Emulate XMLHttpRequest
         * @constructor
         */
        XMLHttpRequest = function() {
            if(!_SARISSA_XMLHTTP_PROGID){
                _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
            };
            return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);
        };
    };
    // we dont need this anymore
    //============================================
    // Factory methods (IE)
    //============================================
    // see non-IE version
    Sarissa.getDomDocument = function(sUri, sName){
        if(!_SARISSA_DOM_PROGID){
            _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
        };
        var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
        // if a root tag name was provided, we need to load it in the DOM object
        if (sName){
            // create an artifical namespace prefix 
            // or reuse existing prefix if applicable
            var prefix = "";
            if(sUri){
                if(sName.indexOf(":") > 1){
                    prefix = sName.substring(0, sName.indexOf(":"));
                    sName = sName.substring(sName.indexOf(":")+1); 
                }else{
                    prefix = "a" + (_sarissa_iNsCounter++);
                };
            };
            // use namespaces if a namespace URI exists
            if(sUri){
                oDoc.loadXML('<' + prefix+':'+sName + " xmlns:" + prefix + "=\"" + sUri + "\"" + " />");
            } else {
                oDoc.loadXML('<' + sName + " />");
            };
        };
        return oDoc;
    };
    // see non-IE version   
    Sarissa.getParseErrorText = function (oDoc) {
        var parseErrorText = Sarissa.PARSED_OK;
        if(oDoc.parseError.errorCode != 0){
            parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + 
                "\nLocation: " + oDoc.parseError.url + 
                "\nLine Number " + oDoc.parseError.line + ", Column " + 
                oDoc.parseError.linepos + 
                ":\n" + oDoc.parseError.srcText +
                "\n";
            for(var i = 0;  i < oDoc.parseError.linepos;i++){
                parseErrorText += "-";
            };
            parseErrorText +=  "^\n";
        }
        else if(oDoc.documentElement == null){
            parseErrorText = Sarissa.PARSED_EMPTY;
        };
        return parseErrorText;
    };
    // see non-IE version
    Sarissa.setXpathNamespaces = function(oDoc, sNsSet) {
        oDoc.setProperty("SelectionLanguage", "XPath");
        oDoc.setProperty("SelectionNamespaces", sNsSet);
    };   
    /**
     * Basic implementation of Mozilla's XSLTProcessor for IE. 
     * Reuses the same XSLT stylesheet for multiple transforms
     * @constructor
     */
    XSLTProcessor = function(){
        if(!_SARISSA_XSLTEMPLATE_PROGID){
            _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.6.0", "MSXML2.XSLTemplate.3.0"]);
        };
        this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID);
        this.processor = null;
    };
    /**
     * Imports the given XSLT DOM and compiles it to a reusable transform
     * <b>Note:</b> If the stylesheet was loaded from a URL and contains xsl:import or xsl:include elements,it will be reloaded to resolve those
     * @argument xslDoc The XSLT DOMDocument to import
     */
    XSLTProcessor.prototype.importStylesheet = function(xslDoc){
        if(!_SARISSA_THREADEDDOM_PROGID){
            _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
        };
        xslDoc.setProperty("SelectionLanguage", "XPath");
        xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
        // convert stylesheet to free threaded
        var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
        // make included/imported stylesheets work if exist and xsl was originally loaded from url
        if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
            converted.async = false;
            if (_SARISSA_THREADEDDOM_PROGID == "MSXML2.FreeThreadedDOMDocument.6.0") { 
                converted.setProperty("AllowDocumentFunction", true); 
                converted.resolveExternals = true; 
            }
            converted.load(xslDoc.url);
        } else {
            converted.loadXML(xslDoc.xml);
        };
        converted.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
        var output = converted.selectSingleNode("//xsl:output");
        this.outputMethod = output ? output.getAttribute("method") : "html";
        this.template.stylesheet = converted;
        this.processor = this.template.createProcessor();
        // for getParameter and clearParameters
        this.paramsSet = new Array();
    };

    /**
     * Transform the given XML DOM and return the transformation result as a new DOM document
     * @argument sourceDoc The XML DOMDocument to transform
     * @return The transformation result as a DOM Document
     */
    XSLTProcessor.prototype.transformToDocument = function(sourceDoc){
        // fix for bug 1549749
        if(_SARISSA_THREADEDDOM_PROGID){
            this.processor.input=sourceDoc;
            var outDoc=new ActiveXObject(_SARISSA_DOM_PROGID);
            this.processor.output=outDoc;
            this.processor.transform();
            return outDoc;
        }
        else{
            if(!_SARISSA_DOM_XMLWRITER){
                _SARISSA_DOM_XMLWRITER = Sarissa.pickRecentProgID(["Msxml2.MXXMLWriter.6.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);
            };
            this.processor.input = sourceDoc;
            var outDoc = new ActiveXObject(_SARISSA_DOM_XMLWRITER);
            this.processor.output = outDoc; 
            this.processor.transform();
            var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
            oDoc.loadXML(outDoc.output+"");
            return oDoc;
        };
    };
    
    /**
     * Transform the given XML DOM and return the transformation result as a new DOM fragment.
     * <b>Note</b>: The xsl:output method must match the nature of the owner document (XML/HTML).
     * @argument sourceDoc The XML DOMDocument to transform
     * @argument ownerDoc The owner of the result fragment
     * @return The transformation result as a DOM Document
     */
    XSLTProcessor.prototype.transformToFragment = function (sourceDoc, ownerDoc) {
        this.processor.input = sourceDoc;
        this.processor.transform();
        var s = this.processor.output;
        var f = ownerDoc.createDocumentFragment();
        if (this.outputMethod == 'text') {
            f.appendChild(ownerDoc.createTextNode(s));
        } else if (ownerDoc.body && ownerDoc.body.innerHTML) {
            var container = ownerDoc.createElement('div');
            container.innerHTML = s;
            while (container.hasChildNodes()) {
                f.appendChild(container.firstChild);
            }
        }
        else {
            var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
            if (s.substring(0, 5) == '<?xml') {
                s = s.substring(s.indexOf('?>') + 2);
            }
            var xml = ''.concat('<my>', s, '</my>');
            oDoc.loadXML(xml);
            var container = oDoc.documentElement;
            while (container.hasChildNodes()) {
                f.appendChild(container.firstChild);
            }
        }
        return f;
    };
    
    /**
     * Set global XSLT parameter of the imported stylesheet
     * @argument nsURI The parameter namespace URI
     * @argument name The parameter base name
     * @argument value The new parameter value
     */
    XSLTProcessor.prototype.setParameter = function(nsURI, name, value){
        // nsURI is optional but cannot be null 
        if(nsURI){
            this.processor.addParameter(name, value, nsURI);
        }else{
            this.processor.addParameter(name, value);
        };
        // update updated params for getParameter 
        if(!this.paramsSet[""+nsURI]){
            this.paramsSet[""+nsURI] = new Array();
        };
        this.paramsSet[""+nsURI][name] = value;
    };
    /**
     * Gets a parameter if previously set by setParameter. Returns null
     * otherwise
     * @argument name The parameter base name
     * @argument value The new parameter value
     * @return The parameter value if reviously set by setParameter, null otherwise
     */
    XSLTProcessor.prototype.getParameter = function(nsURI, name){
        nsURI = nsURI || "";
        if(this.paramsSet[nsURI] && this.paramsSet[nsURI][name]){
            return this.paramsSet[nsURI][name];
        }else{
            return null;
        };
    };
    /**
     * Clear parameters (set them to default values as defined in the stylesheet itself)
     */
    XSLTProcessor.prototype.clearParameters = function(){
        for(var nsURI in this.paramsSet){
            for(var name in this.paramsSet[nsURI]){
                if(nsURI){
                    this.processor.addParameter(name, null, nsURI);
                }else{
                    this.processor.addParameter(name, null);
                };
            };
        };
        this.paramsSet = new Array();
    };
}else{ /* end IE initialization, try to deal with real browsers now ;-) */
    if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){
        /**
         * <p>Ensures the document was loaded correctly, otherwise sets the
         * parseError to -1 to indicate something went wrong. Internal use</p>
         * @private
         */
        Sarissa.__handleLoad__ = function(oDoc){
            Sarissa.__setReadyState__(oDoc, 4);
        };
        /**
        * <p>Attached by an event handler to the load event. Internal use.</p>
        * @private
        */
        _sarissa_XMLDocument_onload = function(){
            Sarissa.__handleLoad__(this);
        };
        /**
         * <p>Sets the readyState property of the given DOM Document object.
         * Internal use.</p>
         * @private
         * @argument oDoc the DOM Document object to fire the
         *          readystatechange event
         * @argument iReadyState the number to change the readystate property to
         */
        Sarissa.__setReadyState__ = function(oDoc, iReadyState){
            oDoc.readyState = iReadyState;
            oDoc.readystate = iReadyState;
            if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function")
                oDoc.onreadystatechange();
        };
        Sarissa.getDomDocument = function(sUri, sName){
            var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
            if(!oDoc.onreadystatechange){
            
                /**
                * <p>Emulate IE's onreadystatechange attribute</p>
                */
                oDoc.onreadystatechange = null;
            };
            if(!oDoc.readyState){
                /**
                * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p>
                * <ul><li>1 == LOADING,</li>
                * <li>2 == LOADED,</li>
                * <li>3 == INTERACTIVE,</li>
                * <li>4 == COMPLETED</li></ul>
                */
                oDoc.readyState = 0;
            };
            oDoc.addEventListener("load", _sarissa_XMLDocument_onload, false);
            return oDoc;
        };
        if(window.XMLDocument){
            // do nothing
        }// TODO: check if the new document has content before trying to copynodes, check  for error handling in DOM 3 LS
        else if(_SARISSA_HAS_DOM_FEATURE && window.Document && !Document.prototype.load && document.implementation.hasFeature('LS', '3.0')){
            //Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good
            /**
            * <p>Factory method to obtain a new DOM Document object</p>
            * @argument sUri the namespace of the root node (if any)
            * @argument sUri the local name of the root node (if any)
            * @returns a new DOM Document
            */
            Sarissa.getDomDocument = function(sUri, sName){
                var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
                return oDoc;
            };
        }
        else {
            Sarissa.getDomDocument = function(sUri, sName){
                var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
                // looks like safari does not create the root element for some unknown reason
                if(oDoc && (sUri || sName) && !oDoc.documentElement){
                    oDoc.appendChild(oDoc.createElementNS(sUri, sName));
                };
                return oDoc;
            };
        };
    };//if(_SARISSA_HAS_DOM_CREATE_DOCUMENT)
};
//==========================================
// Common stuff
//==========================================
if(!window.DOMParser){
    if(_SARISSA_IS_SAFARI){
        /*
         * DOMParser is a utility class, used to construct DOMDocuments from XML strings
         * @constructor
         */
        DOMParser = function() { };
        /** 
        * Construct a new DOM Document from the given XMLstring
        * @param sXml the given XML string
        * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). 
        * @return a new DOM Document from the given XML string
        */
        DOMParser.prototype.parseFromString = function(sXml, contentType){
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(sXml), false);
            xmlhttp.send(null);
            return xmlhttp.responseXML;
        };
    }else if(Sarissa.getDomDocument && Sarissa.getDomDocument() && Sarissa.getDomDocument(null, "bar").xml){
        DOMParser = function() { };
        DOMParser.prototype.parseFromString = function(sXml, contentType){
            var doc = Sarissa.getDomDocument();
            doc.loadXML(sXml);
            return doc;
        };
    };
};

if((typeof(document.importNode) == "undefined") && _SARISSA_IS_IE){
    try{
        /**
        * Implementation of importNode for the context window document in IE
        * @param oNode the Node to import
        * @param bChildren whether to include the children of oNode
        * @returns the imported node for further use
        */
        document.importNode = function(oNode, bChildren){
            var tmp;
            if(oNode.nodeName == "tbody" || oNode.nodeName == "tr"){
                tmp = document.createElement("table");
            }
            else if(oNode.nodeName == "td"){
                tmp = document.createElement("tr");
            }
            else if(oNode.nodeName == "option"){
                tmp = document.createElement("select");
            }
            else{
                tmp = document.createElement("div");
            };
            if(bChildren){
                tmp.innerHTML = oNode.xml ? oNode.xml : oNode.outerHTML;
            }else{
                tmp.innerHTML = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).outerHTML;
            };
            return tmp.getElementsByTagName("*")[0];
        };
    }catch(e){ };
};
if(!Sarissa.getParseErrorText){
    /**
     * <p>Returns a human readable description of the parsing error. Usefull
     * for debugging. Tip: append the returned error string in a &lt;pre&gt;
     * element if you want to render it.</p>
     * <p>Many thanks to Christian Stocker for the initial patch.</p>
     * @argument oDoc The target DOM document
     * @returns The parsing error description of the target Document in
     *          human readable form (preformated text)
     */
    Sarissa.getParseErrorText = function (oDoc){
        var parseErrorText = Sarissa.PARSED_OK;
        if(!oDoc.documentElement){
            parseErrorText = Sarissa.PARSED_EMPTY;
        } else if(oDoc.documentElement.tagName == "parsererror"){
            parseErrorText = oDoc.documentElement.firstChild.data;
            parseErrorText += "\n" +  oDoc.documentElement.firstChild.nextSibling.firstChild.data;
        } else if(oDoc.getElementsByTagName("parsererror").length > 0){
            var parsererror = oDoc.getElementsByTagName("parsererror")[0];
            parseErrorText = Sarissa.getText(parsererror, true)+"\n";
        } else if(oDoc.parseError && oDoc.parseError.errorCode != 0){
            parseErrorText = Sarissa.PARSED_UNKNOWN_ERROR;
        };
        return parseErrorText;
    };
};
Sarissa.getText = function(oNode, deep){
    var s = "";
    var nodes = oNode.childNodes;
    for(var i=0; i < nodes.length; i++){
        var node = nodes[i];
        var nodeType = node.nodeType;
        if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){
            s += node.data;
        } else if(deep == true
                    && (nodeType == Node.ELEMENT_NODE
                        || nodeType == Node.DOCUMENT_NODE
                        || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){
            s += Sarissa.getText(node, true);
        };
    };
    return s;
};
if(!window.XMLSerializer 
    && Sarissa.getDomDocument 
    && Sarissa.getDomDocument("","foo", null).xml){
    /**
     * Utility class to serialize DOM Node objects to XML strings
     * @constructor
     */
    XMLSerializer = function(){};
    /**
     * Serialize the given DOM Node to an XML string
     * @param oNode the DOM Node to serialize
     */
    XMLSerializer.prototype.serializeToString = function(oNode) {
        return oNode.xml;
    };
};

/**
 * strips tags from a markup string
 */
Sarissa.stripTags = function (s) {
    return s.replace(/<[^>]+>/g,"");
};
/**
 * <p>Deletes all child nodes of the given node</p>
 * @argument oNode the Node to empty
 */
Sarissa.clearChildNodes = function(oNode) {
    // need to check for firstChild due to opera 8 bug with hasChildNodes
    while(oNode.firstChild) {
        oNode.removeChild(oNode.firstChild);
    };
};
/**
 * <p> Copies the childNodes of nodeFrom to nodeTo</p>
 * <p> <b>Note:</b> The second object's original content is deleted before 
 * the copy operation, unless you supply a true third parameter</p>
 * @argument nodeFrom the Node to copy the childNodes from
 * @argument nodeTo the Node to copy the childNodes to
 * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false
 */
Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {
    if((!nodeFrom) || (!nodeTo)){
        throw "Both source and destination nodes must be provided";
    };
    if(!bPreserveExisting){
        Sarissa.clearChildNodes(nodeTo);
    };
    var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;
    var nodes = nodeFrom.childNodes;
    if(typeof(ownerDoc.importNode) != "undefined")  {
        for(var i=0;i < nodes.length;i++) {
            nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
        };
    } else {
        for(var i=0;i < nodes.length;i++) {
            nodeTo.appendChild(nodes[i].cloneNode(true));
        };
    };
};

/**
 * <p> Moves the childNodes of nodeFrom to nodeTo</p>
 * <p> <b>Note:</b> The second object's original content is deleted before 
 * the move operation, unless you supply a true third parameter</p>
 * @argument nodeFrom the Node to copy the childNodes from
 * @argument nodeTo the Node to copy the childNodes to
 * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is
 */ 
Sarissa.moveChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {
    if((!nodeFrom) || (!nodeTo)){
        throw "Both source and destination nodes must be provided";
    };
    if(!bPreserveExisting){
        Sarissa.clearChildNodes(nodeTo);
    };
    var nodes = nodeFrom.childNodes;
    // if within the same doc, just move, else copy and delete
    if(nodeFrom.ownerDocument == nodeTo.ownerDocument){
        while(nodeFrom.firstChild){
            nodeTo.appendChild(nodeFrom.firstChild);
        };
    } else {
        var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;
        if(typeof(ownerDoc.importNode) != "undefined") {
           for(var i=0;i < nodes.length;i++) {
               nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
           };
        }else{
           for(var i=0;i < nodes.length;i++) {
               nodeTo.appendChild(nodes[i].cloneNode(true));
           };
        };
        Sarissa.clearChildNodes(nodeFrom);
    };
};

/** 
 * <p>Serialize any object to an XML string. All properties are serialized using the property name
 * as the XML element name. Array elements are rendered as <code>array-item</code> elements, 
 * using their index/key as the value of the <code>key</code> attribute.</p>
 * @argument anyObject the object to serialize
 * @argument objectName a name for that object
 * @return the XML serializationj of the given object as a string
 */
Sarissa.xmlize = function(anyObject, objectName, indentSpace){
    indentSpace = indentSpace?indentSpace:'';
    var s = indentSpace  + '<' + objectName + '>';
    var isLeaf = false;
    if(!(anyObject instanceof Object) || anyObject instanceof Number || anyObject instanceof String 
        || anyObject instanceof Boolean || anyObject instanceof Date){
        s += Sarissa.escape(""+anyObject);
        isLeaf = true;
    }else{
        s += "\n";
        var itemKey = '';
        var isArrayItem = anyObject instanceof Array;
        for(var name in anyObject){
            s += Sarissa.xmlize(anyObject[name], (isArrayItem?"array-item key=\""+name+"\"":name), indentSpace + "   ");
        };
        s += indentSpace;
    };
    return s += (objectName.indexOf(' ')!=-1?"</array-item>\n":"</" + objectName + ">\n");
};

/** 
 * Escape the given string chacters that correspond to the five predefined XML entities
 * @param sXml the string to escape
 */
Sarissa.escape = function(sXml){
    return sXml.replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&apos;");
};

/** 
 * Unescape the given string. This turns the occurences of the predefined XML 
 * entities to become the characters they represent correspond to the five predefined XML entities
 * @param sXml the string to unescape
 */
Sarissa.unescape = function(sXml){
    return sXml.replace(/&apos;/g,"'")
        .replace(/&quot;/g,"\"")
        .replace(/&gt;/g,">")
        .replace(/&lt;/g,"<")
        .replace(/&amp;/g,"&");
};
//   EOF

new Module ('ajax.xmlextras',
	    ['ajax.sarissa', 'correctifs'],
	    [],
	    function () {

function XML ()
{
}
Global.publier ('XML', XML);

/** 
 * Cree un un objet Document
 * @return le document ou null si navigateur non supporte
 */
XML.creerDocument = function (uri, name)
{
	if (typeof Sarissa.getDomDocument != 'undefined')
		return Sarissa.getDomDocument (uri, name);

	alert ('Votre navigateur ne peut pas créer de document DOM');
	return null;
}

/**
 * Cree un objet Request
 * Attention ! Ne sert que pour une seule requete
 * @return l'objet Request ou null si navigateur non supporte
 */
XML.creerXMLHttpRequest = function ()
{
	if (typeof XMLHttpRequest != 'undefined')
		return new XMLHttpRequest ();
	
	alert ('Votre navigateur ne peut pas créer de requête HTTP');
	return null;
}

/**
 * Cree un seriliseur d'objet DOM XML
 * @return le seriliseur ou null si navigateur non supporte
 */
XML.creerXMLSerializer = function ()
{
	if (typeof XMLSerializer != 'undefined')
		return new XMLSerializer ();

	alert ('Votre navigateur ne peut pas sérialiser en XML');
	return null;
}

XML.creerXSLTProcessor = function ()
{
	if (typeof XSLTProcessor != 'undefined')
		return new XSLTProcessor ();
	
	alert ('Votre navigateur ne peut pas créer de processeur XSLT');
	return null;
}

XML.creerNoeudPage = function ()
{
	var document = XML.creerDocument ();
	var page = document.createElement ('page');;
	document.appendChild (page);
	
	return document;
}

/**
 * Construit une URL valide avec le parametres donnes
 * @param url l'url de base
 * @param ... une liste de parametres a ajouter a l'url par paire
 *            de titre, valeur
 */
XML.construireURL = function (url)
{
	Global.assert (url);
	Global.assert (arguments.length % 2 == 1);

	for (var i = 1; i < arguments.length; i += 2) {
		url += (i == 1 ? '?' : '&')
			+ arguments[i] + '=' + escape (arguments[i+1]);
	}

	return url;
}

/**
 * Execute une requete http.
 * Attention fonction de bas niveau a utiliser en connaissance de cause.
 * @param methode        une chaine decrivant la methode a utiliser pour
 *                       executer la requete tel que 'GET' ou 'POST'
 * @param url            l'adresse complete de la page a appeler
 * @param est_asynchrone fagnon indiquant si la requete doit etre executee de
 *                       maniere asychrone ou non
 * @param rappel         fonction de rappel appelee lorsque la page a ete chargee
 *                       prend en parametre l'objet XMLHttpRequest
 * @param message        le corps du message a inclure dans la requete
 *                       (optionnel)
 * @param en_tetes       dictionnaire d'en-tetes http a ajouter a la requete
 *                       (optionnel)
 */
XML.envoyer = function (methode, url, est_asynchrone,
			rappel, message, en_tetes)
{
	Global.assert (methode);
	Global.assert (url);
	Global.assert (rappel);

	/* correctif ie : empeche le cache
	 */
	url += ((url.indexOf ('?') == -1 ? '?' : '&')
		+ 'no_cache=' + new Date().getTime());

	var requete = XML.creerXMLHttpRequest ();
	requete.open (methode, url, est_asynchrone);
	for (titre in en_tetes) {
		/* correctif surcharge prototype Object de vcXMLRPC
		 * importe par Epoz */
		if (titre == 'toXMLRPC')
			continue;

		requete.setRequestHeader (titre, en_tetes[titre]);
	}
	requete.onreadystatechange = function () {
		if (requete.readyState != 4)
			return;
		
		if (requete.status == 200 || requete.status == 0)
			rappel (requete);
		else
			alert ('Status renvoyé "' + requete.statusText
			       + '" (' + requete.status + ') invalide');
	}

	requete.send (message);

	if (!est_asynchrone)
		rappel (requete);
}

/**
 * Charge un document XML.
 * @param url    l'adresse complete du document a charger
 * @param rappel fonction de rappel appelee lorsque le document a ete chargee
 *               prend en parametre le document charge
 */
XML.charger = function (url, rappel)
{
	Global.assert (url);
	Global.assert (rappel);

	var rappel_charger = function (requete) {
		Global.assert (requete);
		Global.assert (requete.responseText);
		Global.assert (requete.responseXML
                        && requete.responseXML.childNodes.length > 0);
	
		if (document.body)
			document.body.style.cursor = 'auto';
		rappel (requete.responseXML);
	}

	if (document.body)
		document.body.style.cursor = "wait";
	XML.envoyer ('GET', url, true, rappel_charger);
}

/**
 * Transforme un noeud suivant la feuille de style XSLT donnee.
 * @param doc    le document qui contiendra le fragment resultant de
 *               la transformation
 * @param source le noeud source a transformer
 * @param style  l'url de la feuille de style
 */
XML.transformer = function (doc, source, style)
{
	Global.assert (doc);
	Global.assert (source);
	Global.assert (style);

	var document_style = XML.creerDocument ();
	document_style.async = false;
	document_style.load (style);	

	var processeur = XML.creerXSLTProcessor ();
	processeur.importStylesheet (document_style);

	var resultat = processeur.transformToFragment (source, doc);

	/* correctif ie : pour transformer le document retourne en fragment
	 */
	if (resultat.nodeType == Node.DOCUMENT_NODE) {
		var fragment = doc.createDocumentFragment ();
		var div = fragment.createElement ('div');
		div.innerHTML = Sarissa.serialize (resultat);
		var fils;
		while (fils = div.firstChild) {
			fragment.appendChild (fils);
		}

		resultat = fragment;
	}

	/* correctif ie : interpretation des balises scripts
	 */
	if (Correctifs.valNavigateur () == Correctifs.INTERNET_EXPLORER)
		Correctifs.ieInterpreterScripts (resultat);

	return resultat;
}

/**
 * Interprete le noeud resultant d'une transformation pour mettre a jour le
 * document fourni.
 * @param doc   le document a mettre a jour
 * @param noeud le noeud resultant de la transformation
 */
XML._interpreterNoeudTransformation = function (doc, noeud)
{
	Global.assert (doc);
	Global.assert (noeud);

	if (noeud.getAttribute ('cyt:fils')) {
		var fils = noeud.firstChild;
		while (fils) {
			var suivant = fils.nextSibling;
			if (fils.nodeType != Node.TEXT_NODE) {
				XML._interpreterNoeudTransformation (doc,
								     fils);
			}
			fils = suivant;
		}
	} else if (noeud.getAttribute ('cyt:insererEnTete')) {
		var id = noeud.getAttribute ('cyt:insererEnTete');
		var destination = doc.getElementById (id);
		
		if (!destination.hasChildNodes ())
			destination.appendChild (noeud);
		else
			destination.insertBefore (noeud,
						  destination.firstChild);
	} else if (noeud.getAttribute ('cyt:insererPied')) {
		var id = noeud.getAttribute ('cyt:insererPied');
		var destination = doc.getElementById (id);
		
		destination.appendChild (noeud);
	} else if (noeud.getAttribute ('cyt:insererAvant')) {
		var id = noeud.getAttribute ('cyt:insererAvant');
		var destination = doc.getElementById (id);
		
		Global.assert (destination.parentNode);
		destination.parentNode.insertBefore (noeud, destination);
	} else if (noeud.getAttribute ('cyt:remplacer')) {
		var id = noeud.getAttribute ('cyt:remplacer');
		var destination = doc.getElementById (id);		

		/* FIXME */
		if (!destination && id == 'titre')
			destination = doc.getElementsByTagName ('title')[0];

		Global.assert (destination.parentNode);
		destination.parentNode.replaceChild (noeud, destination);
	} else if (noeud.getAttribute ('cyt:supprimer')) {
		var id = noeud.getAttribute ('cyt:supprimer');
		var destination = doc.getElementById (id);
		
		Global.assert (destination.parentNode);
		destination.parentNode.removeChild (destination);
	} else {
		alert ('Transformation : element invalide');
	}
}

/**
 * Fonction de rappel de appliquerTransformation.
 * Transforme et interprete le resultat de la transormation pour mettre a jour
 * le document fournis.
 * @param doc    le document a mettre a jour
 * @param source le document XML qui vient juste d'etre charge
 * @param style  l'url de la feuille de style
 */
XML._appliquerTransformationRappel = function (doc, source, style)
{
	Global.assert (doc);
	Global.assert (source);
	Global.assert (style);

	var resultat = XML.transformer (doc, source, style);

	Global.assert (resultat);
	Global.assert (resultat.hasChildNodes ());
	Global.assert (resultat.childNodes.length == 1);

	var racine = resultat.firstChild;
	XML._interpreterNoeudTransformation (doc, racine);
}

/**
 * Charge et transforme le document appele. Met a jour automatiquement
 * le document fourni a l'aide des informations des noeuds generes
 * par la transformation.
 * @param url    l'adresse complete du document a charger
 * @param style  l'url de la feuille de style
 * @param doc    le document a mettre a jour
 * @param rappel fonction de rappel appelee lorsque le document a ete chargee
 *               prend en parametre le document charge
 *               (optionnel)
 */
XML.appliquerTransformation = function (url, style, doc, rappel)
{
	Global.assert (url);
	Global.assert (style);

	if (!doc)
		doc = document;

	rappel_appliquer = function (reponseXML) {
		XML._appliquerTransformationRappel (doc, reponseXML, style);

		if (rappel)
			rappel (reponseXML);
	}

	XML.charger (url, rappel_appliquer);
}

});

new Module ('cookie',
	    [],
	    [],
	    function () {

function Cookie ()
{
}
Global.publier ('Cookie', Cookie);

Cookie.modifier = function (nom, valeur, duree)
{
	Global.assert (nom);

	if (duree) {
		var date = new Date ();
		date.setTime (date.getTime() + duree);
		valeur += '; expires=' + date.toGMTString();
	}
	
	document.cookie = nom + '=' + valeur + '; path=/';
}

Cookie.valeur = function (nom)
{
	Global.assert (nom);

	var liste = document.cookie.split (';');
	for (var i=0; i < liste.length; i++) {
		var cookie = liste[i];
		var regexp = new RegExp ('^\\s*' + nom + '=(.*)\\s*$');
		var resultat = regexp.exec (cookie);
		if (resultat)
			return resultat[1];
	}

	return null;
}

Cookie.effacer = function  (nom)
{
	Global.assert (nom);

	Cookie.modifier (nom, '', -1);
}

});

new Module ('timer',
	    [],
	    [],
	    function () {

/**
 * Cree un Timer.
 * @interval interval en milisecondes
 * @rappel   fonction de rappel du timer
 * @repeter  repeter le timer en boucle
 */
function Timer (interval, rappel, repeter)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (interval > 0);
	Global.assert (rappel);

	this._interval = interval;
	this._rappel = rappel;
	this._repeter = repeter;
	this._timeout = null;
	this._compteur = 0;
	this._estTermine = false;
}
Global.publier ('Timer', Timer);

/**
 * Compteur du timer.
 * @return le nombre de rappels
 */
Timer.prototype.valCompteur = function ()
{
	return this._compteur;
}

Timer.prototype.estLance = function ()
{
	return this._timeout != null;
}

Timer.prototype.estTermine = function ()
{
	return this._estTermine;
}

Timer.prototype._executerRappel = function ()
{
	if (!this._repeter)
		this._estTermine = true;
	this._rappel (this);
	this._compteur++;
}

Timer.prototype.lancer = function () 
{
	Global.assert (!this.estLance ());

	this._compteur = 0;
	this._estTermine = false;

	var rappel = Global.associer (this,
				      this._executerRappel);

	if (this._repeter)
		this._timeout = setInterval (rappel,
					     this._interval);
	else
		this._timeout = setTimeout (rappel,
					    this._interval);
}

Timer.prototype.desactiver = function ()
{
	Global.assert (this.estLance ());
	
	if (this._repeter)
		clearInterval (this._timeout);
	else
		clearTimeout (this._timeout);

	this._estTermine = true;
	this._timeout = null;
}

Timer.prototype.reinitialiser = function ()
{
	this.desactiver ();
	this.lancer ();
}

function Apparition (valeur_debut, valeur_fin, duree, rappel)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (duree > 0);
	Global.assert (rappel);

	this._valeur_debut = valeur_debut;
	this._valeur_fin = valeur_fin;
	this._duree = duree;
	this._interval = 20;
	this._rappel = rappel;
	
	var rappel = Global.associer (this,
				      this._executerRappel);

	var timer = new Timer (this._interval, rappel, true);
	timer.lancer ();
}
Global.publier ('Apparition', Apparition);

Apparition.prototype._executerRappel = function (timer)
{
	Global.assert (timer);

	var progression = timer.valCompteur() * this._interval / this._duree;
	
	if (progression > 1)
		timer.desactiver ();

	this._rappel (this._valeur_debut
		      + progression * (this._valeur_fin - this._valeur_debut));
}

});

new Module ('iframe',
	    ['timer'],
	    [],
	    function () {

/**
 * Cadre interne au document courant, presentant une vue d'une autre page web.
 * @param id    l'identifiant du cadre.
 * @param titre le titre de la fenetre.
 */
function IFrame ()
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	zone_temporaire_ajouter (this.valElement ());
}
Global.publier ('IFrame', IFrame);

/**
 * Accesseur sur l'objet dom du menu.
 * @return l'objet html
 */
IFrame.prototype.valElement = function () 
{
	if (!this._element) {
		var masque = document.getElementById ('masque');
		if (!masque) {
			masque = document.createElement ('div');
			masque.id = 'masque';
			zone_temporaire_ajouter (masque);
		}
		masque.style.height = document.body.offsetHeight + 'px';
		masque.style.display = 'block';

		var iframe = document.createElement ('iframe');
		iframe.id = 'iframe';
		iframe.frameBorder = 0;
		iframe.scrolling = 'no';
		/* correctif ie */
		iframe.allowTransparency = true;

		var truc = this;
		this._onload = function () {
			masque.onmouseover = function () { truc.cacher (); };
		}

		this._element = iframe;
	}

	return this._element;
}

IFrame.prototype._onLoadTimeout = function (timer)
{
	var iframe = this.valElement ();
	if (iframe.contentWindow.document.readyState == 'complete') {
		timer.desactiver ();
		this._onload ();
	}
}

/**
 * Change la page de l'iframe.
 * @param url l'adresse de la page
 */
IFrame.prototype.allerA = function (url)
{
	Global.assert (url);

	var iframe = this.valElement ();
	var content = iframe.contentDocument || iframe.contentWindow;
	content.location = url;

	if (url == 'about:blank')
		iframe.onload = null;
	else if (this._onload && iframe.document)
		new Timer (200,
			   Global.associer (this, this._onLoadTimeout),
			   1).lancer();
	else if (this._onload)
		iframe.onload = this._onload;
}

/**
 * Affiche la fenetre.
 */
IFrame.prototype.afficher = function ()
{
	this.valElement().style.display = 'block';

	var masque = document.getElementById ('masque');
	masque.style.display = 'block';
}

/**
 * Cache la fenetre.
 */
IFrame.prototype.cacher = function ()
{
	var iframe = this.valElement();
	iframe.style.display = 'none';

	var masque = document.getElementById ('masque');
	masque.style.display = 'none';

	this.allerA ('about:blank');

	masque.onmouseover = null;
}

/**
 * Fait surgir la fenetre a l'endroit ou le click a eu lieu.
 * @return false
 */
IFrame.prototype.surgir = function (evt)
{
	if (!evt) var evt = window.event;

	this.afficher ();

	var min_x = document.documentElement.scrollLeft
		|| document.body.scrollLeft;
	var max_x = min_x + (window.innerWidth
			     || document.documentElement.clientWidth
			     || document.body.clientWidth);
	var min_y = document.documentElement.scrollTop
		|| document.body.scrollTop;
	var max_y = min_y + (window.innerHeight
			     || document.documentElement.clientHeight
			     || document.body.clientHeight)
		
	var elt = this.valElement ();
	elt.style.left = clamp (event_x (evt) - elt.offsetWidth / 2,
				min_x,
				max_x - elt.offsetWidth) + 'px';
	elt.style.top = clamp (event_y (evt) - elt.offsetHeight / 2,
			       min_y,
			       max_y - elt.offsetHeight) + 'px';

	return false;
}

/**
 * Rait surgir une iframe sous l'element selectionne.
 * Lors du premier evenement, creer l'iframe et l'attacge a l'objet associe
 * @param evt   l'evenement de survol qui declenche l'apparition
 * @param elt   l'element sur lequel l'iframe sera attache
 * @return false
 */
function iframe_surgir (evt, url)
{
	Global.assert (url);
	
	var iframe = IFrame.IFRAME;
	if (!iframe)
		iframe = IFrame.IFRAME = new IFrame ();

	iframe.allerA (url);
	return iframe.surgir (evt);
}
Global.publier ('iframe_surgir', iframe_surgir);

});

new Module ('popup',
	    ['timer'],
	    [],
	    function () {

function glisser_rappel (evt, cible, dx, dy)
{
	Global.assert (cible);
	
	if (!evt) evt = window.event;

	/* bogue mozilla : la position de l'evenement lors d'un deplacement
	 * est situee par rapport a la fenetre initiale ou a eu le commencement
	 * et non la fenetre courante ou se trouve l'evenement 
	 */
	cible.style.left = event_x (evt)
		+ (document.all ? frame_x (event_window (evt)) : 0) - dx + 'px';
	cible.style.top = event_y (evt)
		+ (document.all ? frame_y (event_window (evt)) : 0) - dy + 'px';

	return false;
}

function glisser_terminer (cible)
{
	Global.assert (cible);

	document.onmousemove = null;
	document.onmouseup = null;

	return false;
}

function glisser_commencer (evt, cible)
{
	if (!evt) evt = window.event;
	var cible = cible || event_target (evt);

	var dx = event_x (evt) + frame_x (event_window (evt)) - min_x (cible);
	var dy = event_y (evt) + frame_y (event_window (evt)) - min_y (cible);
	document.onmousemove
		= function (evt) { return glisser_rappel (evt, cible,
							  dx, dy); };
	document.onmouseup
		= function (evt) { return glisser_terminer (cible); };

	return false;
}

/**
 * Fenetre interne a la fenetre du navigateur.
 * @param id    l'identifiant de la fenetre.
 */
function Popup (id)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (id);
	Global.assert (!Popup.LISTE[id]);
	
	this._id = id;
	this._element = null;
	this._titre = null;
	this._iframe = null;

	Popup.LISTE[id] = this;
	
	document.body.appendChild (this.valElement ());
}
Global.publier ('Popup', Popup);

Popup.LISTE = new Array ();
Popup.ZINDEX_MAX = 2;

Popup.prototype._transmettreEvenementsIFrame = function ()
{
	var iframe = this._iframe;
	var content = iframe.contentDocument || iframe.contentWindow.document;

	content.onmousemove = function (evt) {
		if (!evt) evt = iframe.contentWindow.event;

/* 	alert ('event_x : ' + event_x (evt) + '\n' */
/* 	       + 'event_y : ' + event_y (evt) + '\n' */
/* 	       + 'window_x : ' + frame_x (window) + '\n' */
/* 	       + 'window_y : ' + frame_y (window) + '\n' */
/* 	       + 'frame_x : ' + frame_x (event_window (evt)) + '\n' */
/* 	       + 'frame_y : ' + frame_y (event_window (evt))); */

		if (topDocument ().onmousemove)
			topDocument ().onmousemove (evt);

		/* bogue ie : pas de retour direct de la valeur
		 * de topDocument ().onmousemove */
	};
	content.onmouseup = function (evt) {
		if (!evt) evt = iframe.contentWindow.event;
		if (topDocument ().onmouseup)
			topDocument ().onmouseup (evt);

		/* bogue ie : pas de retour direct de la valeur
		 * de topDocument ().onmousemove */
	};

	var popup = this.valElement ();
	content.onmousedown = function (evt) {
		if (!evt) evt = iframe.contentWindow.event;
		if (popup.onmousedown)
			popup.onmousedown (evt);

		/* bogue ie : pas de retour direct de la valeur
		 * de topDocument ().onmousemove */
	};
}

/**
 * Accesseur sur l'objet dom du menu.
 * @return l'objet html
 */
Popup.prototype.valElement = function () 
{
	if (!this._element) {
		var truc = this;

		var popup = document.createElement ('div');
		popup.id = this._id;
		popup.className = 'popup';
		popup.onmousedown = Global.associer (this,
						     this.passerAuPremierPlan);

		var fermer = document.createElement ('a');
		fermer.href = '#';
		fermer.className = 'fermer';
		fermer.onclick = function () { truc.cacher (); return false; };
		popup.appendChild (fermer);

		var titre = document.createElement ('h5');
		var texte_titre
			= document.createTextNode ('Chargement ...');
		titre.appendChild (texte_titre);
		titre.onmousedown = function (evt) {
			truc._transmettreEvenementsIFrame ();
			return glisser_commencer (evt, popup);
		};
		this._titre = titre;
		popup.appendChild (titre);

		var iframe = document.createElement ('iframe');
		iframe.frameBorder = 0;
		iframe.scrolling = 'no';
		popup.appendChild (iframe);

		this._iframe = iframe;
		this._element = popup;
	}

	return this._element;
}

/**
 * Modifie le titre de la fenetre.
 * @param texte le texte a inserer dans le titre de la fenetre.
 */
Popup.prototype.modifTitre = function (texte)
{
	var texte_titre
		= document.createTextNode (texte);

	if (!this._titre)
		this.valElement ();
	var titre = this._titre;

	titre.replaceChild (texte_titre, titre.firstChild);
}

Popup.prototype._redimensionner = function () 
{
	var iframe = this._iframe;
	var content = iframe.contentDocument || iframe.contentWindow.document;
	
	if (!content.body.style.width)
		content.body.style.width = iframe.offsetWidth + 'px';
	if (!content.body.style.height)
		content.body.style.height = iframe.offsetHeight + 'px';
}

Popup.prototype.valContentDocument = function ()
{
	var iframe = this._iframe;
	return iframe.contentDocument || iframe.contentWindow.document;
}

/* bogue ie : ne pas affecter directement iframe.onload
 */
Popup.prototype._onload = function ()
{
	var iframe = this._iframe;
	var content = iframe.contentDocument || iframe.contentWindow.document;
	
	this.modifTitre (content.title);

/* 	this._redimensionner (); */
	this._transmettreEvenementsIFrame ();
}

Popup.prototype._onLoadTimeout = function (timer)
{
	var iframe = this._iframe;
	if (iframe.contentWindow.document.readyState == 'complete') {
		timer.desactiver ();
		this._onload ();
	}
}

/**
 * Change la page de la popup.
 * @param url l'adresse de la page
 */
Popup.prototype.allerA = function (url)
{
	Global.assert (url);

	var iframe = this._iframe;
	var content = iframe.contentDocument || iframe.contentWindow.document;
	content.location = url;

	this.modifTitre ('Chargement ...');

	if (this._onload && iframe.document)
		new Timer (1000,
			   Global.associer (this,
					    this._onLoadTimeout),
			   1).lancer();
	else if (this._onload)
		iframe.onload = Global.associer (this, this._onload);
}

Popup.prototype.passerAuPremierPlan = function ()
{
	var elt = this.valElement ();
	if (!elt.style.zIndex || elt.style.zIndex < Popup.ZINDEX_MAX)
	    elt.style.zIndex = Popup.ZINDEX_MAX++;
}

/**
 * Affiche la fenetre.
 */
Popup.prototype.afficher = function ()
{
	this.valElement().style.display = 'block';
}

/**
 * Cache la fenetre.
 */
Popup.prototype.cacher = function ()
{
	this.valElement().style.display = 'none';
	this.allerA ('about:blank');
}

/**
 * Fait surgir la fenetre a l'endroit ou le click a eu lieu.
 * @return false
 */
Popup.prototype.surgir = function (evt)
{
	if (!evt) var evt = window.event;

	this.passerAuPremierPlan ();

	this.afficher ();

	var min_x = document.documentElement.scrollLeft
		|| document.body.scrollLeft;
	var max_x = min_x + (window.innerWidth
			     || document.documentElement.clientWidth
			     || document.body.clientWidth);
	var min_y = document.documentElement.scrollTop
		|| document.body.scrollTop;
	var max_y = min_y + (window.innerHeight
			     || document.documentElement.clientHeight
			     || document.body.clientHeight);
		
	var elt = this.valElement ();
	elt.style.left = clamp (event_x (evt) - elt.offsetWidth / 2,
				min_x,
				max_x - elt.offsetWidth) + 'px';
	elt.style.top = clamp (event_y (evt),
			       min_y,
			       max_y - elt.offsetHeight) + 'px';

	return false;
}

/**
 * Fait surgir une fenetre sous l'element selectionne.
 * Lors du premier evenement, cree la fenetre et l'attache a
 * l'objet associe.
 * @param evt   l'evenement de survol qui declenche l'apparition
 * @param url   l'adresse de la page a afficher
 * @param id    l'identifiant de la fenetre
 * @return false
 */
function popup_surgir (evt, url, id)
{
	Global.assert (url);
	Global.assert (id);

	if (document != topDocument ())
		return topDocument ().popup_surgir (evt, url, id);

	var popup = Popup.LISTE[id];
	if (!popup)
		popup = new Popup (id);
	
	popup.allerA (url);
	return popup.surgir (evt);
}
Global.publier ('popup_surgir', popup_surgir);
document.popup_surgir = popup_surgir;

});

new Module ('mvc',
	    [],
	    [],
	    function () {

/*
 * FIXME : recuperation temporaire des nouvelles fonctionalites de global.js
 * en attendant une synchronisation
 */

function Iterateur ()
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;
}

Iterateur.prototype.suivant = function ()
{
	Global.erreurNonImplemente ('Iterateur.suivant');
}

Iterateur.prototype.trouver = function (filtre)
{
	Global.assert (filtre);

	while (valeur = this.suivant ()) {
		if (filtre (valeur))
			return valeur;
	}
	
	return null;
}


Array.Iterateur = function (tableau)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (tableau);

	Iterateur.call (this);

	this._tableau = tableau;
	this._i = 0;
}
Global.heriter (Array.Iterateur, Iterateur);

Array.Iterateur.prototype.suivant = function ()
{
	Global.assert (this._tableau);
	Global.assert (typeof this._i == 'number');
	Global.assert (this._i >= 0 && this._i <= this._tableau.length);
	
	if (this._i < this._tableau.length)
		return this._tableau[this._i++];
	else
		return null;
}

Array.prototype.iterateur = function ()
{
	return new Array.Iterateur (this);
}

Array.prototype.indexDeFiltre = function (filtre)
{
	Global.assert (filtre);

	for (var i = 0; i < this.length; i++) {
		if (filtre (this[i]))
			return i;
	}
	
	return -1;
}

Array.prototype.indexDe = function (val) 
{
	Global.assert (val);

	return this.indexDeFiltre (function (elt) { return elt == val });
}

Array.prototype.supprimer = function (val) 
{
	Global.assert (val);

	var index = this.indexDe (val);
	
	Global.assert (index != -1);

	this.splice (index, 1);
}

/*
 *
 */

function Observateur ()
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	this._liste_observables = new Array ();
}

Observateur.prototype._valListeObservables = function ()
{
	Global.assert (this._liste_observables);
	
	return this._liste_observables;
}

Observateur.prototype._abonnerA = function (observable)
{
	Global.assert (observable);
	Global.assert (observable.abonnerObservateur);
	
	observable.abonnerObservateur (this);

	var liste_observables = this._valListeObservables ();
	liste_observables.push (observable);
}

Observateur.prototype.detacher = function ()
{
	var iterateur = this._valListeObservables ().iterateur ();
	var observable;
	while (observable = iterateur.suivant ())
		observable.detacherObservateur (this);

	this._liste_observables = new Array ();
}

Observateur.prototype.synchroniser = undefined;

Observateur.prototype.synchroniserAjout = undefined;

Observateur.prototype.synchroniserSuppression = undefined;

function Observable ()
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	this._liste_observateurs = new Array ();
}

Observable.prototype._valListeObservateurs = function ()
{
	Global.assert (this._liste_observateurs);

	return this._liste_observateurs;
}

Observable.prototype.abonnerObservateur = function (observateur)
{
	Global.assert (observateur);

	var liste_observateurs = this._valListeObservateurs ();
	liste_observateurs.push (observateur);
}

Observable.prototype.detacherObservateur = function (observateur)
{
	Global.assert (observateur);

	var liste_observateurs = this._valListeObservateurs ();
	liste_observateurs.supprimer (observateur);
}

Observable.prototype._notifierSignal = function (nom_signal)
{
	Global.assert (typeof nom_signal == 'string' || !nom_signal);

	var nom_rappel;
	if (nom_signal)
		nom_rappel = ('synchroniser' + nom_signal.capitaliser ());

	var arguments_rappel = new Array ();
	for (var i = 1; i < arguments.length; i++)
		arguments_rappel.push (arguments[i]);

	var iterateur = this._valListeObservateurs ().iterateur ();
	var observateur;
	while (observateur = iterateur.suivant ()) {
		if (nom_rappel && observateur[nom_rappel])
			observateur[nom_rappel].apply (observateur,
						       arguments_rappel);
		else
			observateur.synchroniser ();
	}
}

Observable.prototype._notifierModification = function ()
{
	this._notifierSignal ();
}

Observable.prototype._notifierAjout = function (objet)
{
	Global.assert (objet);

	this._notifierSignal ('ajout', objet);
}

Observable.prototype._notifierSuppression = function (objet)
{
	Global.assert (objet);

	this._notifierSignal ('suppression', objet);
}

function VueTransitoire (objet)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (objet);

	Observateur.call (this);

	this._objet = objet;
}
Global.heriter (VueTransitoire, Observateur);

VueTransitoire.prototype._valObjet = function ()
{
	Global.assert (this._objet);
	
	return this._objet;
}

function Vue (objet)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Global.assert (objet);

	VueTransitoire.call (this, objet);

	this._element = null;

	this._abonnerA (objet);
}
Global.heriter (Vue, VueTransitoire);

Vue.prototype.valElement = function ()
{
	Global.assert (this._creerElement);

	if (!this._element) {
		var element = this._creerElement ();

		Global.assert (element);
		
		this._element = element;
		if (this.synchroniser)
			this.synchroniser ();
	}

	return this._element;
}

Global.publier ('Observable', Observable);
Global.publier ('Vue', Vue);

});

new Module ('base.type_conseil',
	    [],
	    [],
	    function () {

var type_conseil = {
33: {
nom : 'Alerte : maladie',
etapes : ['33#1120', '33#1121', '33#1122']
},
39: {
nom : 'Alerte : mesquinerie échec',
etapes : ['39#1123', '39#1124']
},
29: {
nom : 'Alerte : mesquinerie envoi',
etapes : ['29#1125']
},
38: {
nom : 'Alerte : mesquinerie victime',
etapes : ['38#1126', '38#1127', '38#1128']
},
24: {
nom : 'Alerte : nouveau message',
etapes : ['24#1130', '24#1131']
},
30: {
nom : 'Alerte : objet endommagé',
etapes : ['30#1132', '30#1133', '30#1134']
},
35: {
nom : 'Alerte : plus d\'alertes SMS',
etapes : ['35#1135', '35#1136', '35#1137']
},
27: {
nom : 'Alerte : plus de nourriture',
etapes : ['27#1147', '27#1148', '27#1149']
},
37: {
nom : 'Alerte : plus de points d\'action',
etapes : ['37#1150', '37#1151', '37#1152', '37#1153']
},
31: {
nom : 'Alerte : visite d\'un écureuil',
etapes : ['31#1170', '31#1171']
},
19: {
nom : 'Astuce : Bonus du nid',
etapes : ['19#1172', '19#1173']
},
53: {
nom : 'Astuce : Collecteau',
etapes : ['53#1174', '53#1175', '53#1176']
},
15: {
nom : 'Tutoriel : Visiter un village voisin',
etapes : ['15#978', '15#979', '15#980']
},
47: {
nom : 'Alerte : faim (beaucoup)',
etapes : ['47#1330', '47#1331', '47#1332', '47#1333']
},
10: {
nom : 'Tutoriel : Le forum',
etapes : ['10#1216', '10#1217', '10#1218', '10#1219']
},
18: {
nom : 'Tutoriel : Boîte aux lettres',
etapes : ['18#1220', '18#1221', '18#1222']
},
16: {
nom : 'Tutoriel : Visiter un nid',
etapes : ['16#1238', '16#1239', '16#1240']
},
26: {
nom : 'Alerte : presque plus de savon',
etapes : ['26#1245', '26#1246']
},
43: {
nom : 'Alerte : niveau supérieur "notable"',
etapes : ['43#14']
},
12: {
nom : 'Tutoriel : Journal d\'évènements',
etapes : ['12#1083', '12#1084', '12#1085']
},
14: {
nom : 'Tutoriel : L\'hibernation',
etapes : ['14#1086', '14#1087', '14#1088']
},
66: {
nom : 'Alerte : niveau supérieur "esprit des forêts"',
etapes : ['66#1368']
},
11: {
nom : 'Tutoriel : Aide du jeu',
etapes : ['11#1247', '11#1248']
},
13: {
nom : 'Tutoriel : La banque',
etapes : ['13#1254', '13#1255', '13#1256']
},
7: {
nom : 'Tutoriel : Fabrication, établis',
etapes : ['7#1257', '7#1258', '7#1259', '7#1260']
},
2: {
nom : 'Tutoriel : S\'occuper de l\'écureuil',
etapes : ['2#1261', '2#1262', '2#1263', '2#1264']
},
3: {
nom : 'Tutoriel : Aménager son nid',
etapes : ['3#1265', '3#1266', '3#1267', '3#1268', '3#1269']
},
8: {
nom : 'Tutoriel : Le marché',
etapes : ['8#1277', '8#1278', '8#1279', '8#1280']
},
4: {
nom : 'Tutoriel : Campagne de foot',
etapes : ['4#1296', '4#1297', '4#1298', '4#1299', '4#1300', '4#1301']
},
9: {
nom : 'Tutoriel : Mesquiner',
etapes : ['9#1305', '9#1306', '9#1307', '9#1308', '9#1304']
},
41: {
nom : 'Alerte : niveau supérieur "acrobate"',
etapes : ['41#1309']
},
63: {
nom : 'Alerte : niveau supérieur "apprenti"',
etapes : ['63#1310']
},
34: {
nom : 'Alerte : niveau supérieur "jeunot"',
etapes : ['34#1311']
},
25: {
nom : 'Alerte : campagne prête',
etapes : ['25#1337', '25#1338', '25#1339', '25#1340']
},
40: {
nom : 'Alerte : niveau supérieur "villageois"',
etapes : ['40#1314']
},
32: {
nom : 'Alerte : niveau supérieur "prince des bois"',
etapes : ['32#1315']
},
44: {
nom : 'Alerte : niveau supérieur "maitre des cimes"',
etapes : ['44#1316', '44#1317']
},
42: {
nom : 'Alerte : niveau supérieur "aventurier"',
etapes : ['42#1318', '42#1319']
},
1: {
nom : 'Tutoriel : Bienvenue',
etapes : ['1#1324', '1#1325', '1#1326']
},
55: {
nom : 'Astuce : Modération',
etapes : ['55#1327', '55#1328', '55#1329']
},
54: {
nom : 'Astuce :  Recyclotritus',
etapes : ['54#1344', '54#1345', '54#1346']
},
5: {
nom : 'Tutoriel : Exploration',
etapes : ['5#1352', '5#1353', '5#1347', '5#1348', '5#1349', '5#1350', '5#1351']
},
51: {
nom : 'Tutoriel : Le module de communication',
etapes : ['51#1355', '51#1354']
},
6: {
nom : 'Tutoriel : Vente au brocanteur',
etapes : ['6#1356', '6#1357', '6#1358', '6#1359', '6#1360']
},
52: {
nom : 'Tutoriel : Vente au marché',
etapes : ['52#1361', '52#1362', '52#1363', '52#1364', '52#1365']
},
67: {
nom : 'Alerte : niveau supérieur grand gourou des plaines',
etapes : ['67#1369']
},
68: {
nom : 'Alerte : niveau supérieur "mânes des orées"',
etapes : ['68#1370']
},
45: {
nom : 'Astuce : PUB : Banque - Noisette',
etapes : ['45#1436', '45#1437', '45#1438']
},
20: {
nom : 'Alerte : faim',
etapes : ['20#1371', '20#1372', '20#1373', '20#1374']
},
50: {
nom : 'Alerte : plus d\'eau (beaucoup)',
etapes : ['50#1375', '50#1376', '50#1377']
},
46: {
nom : 'Astuce : PUB : Banque - Objets saison',
etapes : ['46#1439', '46#1440', '46#1441']
},
48: {
nom : 'Alerte : propreté (beaucoup)',
etapes : ['48#1378', '48#1379', '48#1380', '48#1381']
},
49: {
nom : 'Alerte : soif (beaucoup)',
etapes : ['49#1382', '49#1383', '49#1384']
},
56: {
nom : 'Astuce : PUB : Banque - Points d\'action',
etapes : ['56#1442', '56#1443', '56#1444']
},
22: {
nom : 'Astuce : PUB : Banque - soutien',
etapes : ['22#1445', '22#1446', '22#1447']
},
28: {
nom : 'Alerte : plus d\'eau',
etapes : ['28#1399', '28#1400', '28#1401']
},
36: {
nom : 'Alerte : plus de noisettes',
etapes : ['36#1402', '36#1403', '36#1404']
},
23: {
nom : 'Alerte : propreté',
etapes : ['23#1405', '23#1406', '23#1407', '23#1408']
},
21: {
nom : 'Alerte : soif',
etapes : ['21#1409', '21#1410', '21#1411']
},
61: {
nom : 'Alerte : faim (oligo-éléments)',
etapes : ['61#1418', '61#1419', '61#1420', '61#1421']
},
62: {
nom : 'Alerte : faim (sels minéraux)',
etapes : ['62#1422', '62#1423', '62#1424', '62#1425']
},
60: {
nom : 'Alerte : faim (vitamines)',
etapes : ['60#1426', '60#1427', '60#1428', '60#1429']
},
17: {
nom : 'Astuce : Le saviez-vous ?',
etapes : ['17#1433', '17#1434', '17#1435']
}
}
Global.publier ('type_conseil', type_conseil);

var type_conseil_etape = {
'38#1126': {
ordre : 1126,
message : 'Vous venez de recevoir une mesquinerie. Vengeance !',
transition : 'en savoir plus'
},
'38#1127': {
ordre : 1127,
message : 'Pour connaitre l\'expéditeur, lisez votre courrier dans votre boîte aux lettres.',
transition : 'message suivant'
},
'38#1128': {
ordre : 1128,
message : 'Vous pouvez vous venger en utilisant votre cabane à mesquineries au pied de votre nid.',
transition : 'message suivant'
},
'30#1132': {
ordre : 1132,
message : 'Votre nid contient des objets endommagés.',
transition : 'en savoir plus'
},
'30#1133': {
ordre : 1133,
message : 'Pour réparer un objet abimé, placez le dans votre inventaire,',
transition : 'message suivant'
},
'30#1134': {
ordre : 1134,
message : 'Pour cela, choisissez <em>Inventaire</em> dans le bandeau de navigation. Cliquez ensuite le lien <em>Réparer un objet</em>.',
transition : 'message suivant'
},
'37#1150': {
ordre : 1150,
message : 'Vous n\'avez plus de points d\'actions.',
transition : 'en savoir plus'
},
'37#1151': {
ordre : 1151,
message : 'Vous gagnez 1 point d\'action toutes les 2 heures.',
transition : 'message suivant'
},
'37#1152': {
ordre : 1152,
message : 'Le nombre de points d\'action maximal est de 18.',
transition : 'message suivant'
},
'37#1153': {
ordre : 1153,
message : 'Vous pouvez également acheter des points d\'action à la <em>banque</em>, afin de progresser plus rapidement.',
transition : 'message suivant'
},
'31#1170': {
ordre : 1170,
message : 'Vous avez reçu la visite d\'un écureuil.',
transition : 'en savoir plus'
},
'31#1171': {
ordre : 1171,
message : 'Pour visiter un nid, cliquez sur le nid de votre ami dans le village puis cliquez sur l\'icone <em>Visiter</em>.',
transition : 'message suivant'
},
'19#1172': {
ordre : 1172,
message : 'Le saviez-vous ? Les objets que vous placez dans votre nid vous rapportent des points.',
transition : 'message suivant'
},
'19#1173': {
ordre : 1173,
message : 'Essayer de jouer les premières places en décorant celui-ci avec des objets luxueux.',
transition : 'message suivant'
},
'9#1305': {
ordre : 1305,
message : 'Pour cela vous devez posséder des mesquineries dans votre inventaire.',
transition : 'message suivant'
},
'9#1306': {
ordre : 1306,
message : 'Cliquez sur la cabane en bas à droite de votre nid puis choisissez votre cible grâce à l\'outil de recherche.',
transition : 'message suivant'
},
'9#1307': {
ordre : 1307,
message : 'Choisissez ensuite votre mesquinerie dans votre liste à gauche de l\'écran, et cliquez sur envoyer.',
transition : 'message suivant'
},
'47#1330': {
ordre : 1330,
message : 'Votre écureuil est vraiment affamé ! Nourrissez le de toute urgence.',
transition : 'en savoir plus'
},
'47#1331': {
ordre : 1331,
message : 'Lorsque que votre personnage est affamé, il perd des points de bonheur.',
transition : 'message suivant'
},
'5#1352': {
ordre : 1352,
message : 'Il y a de nombreuses autres zones d\'exploration à découvrir dans le village,  n\'hésitez pas à vous y promener !',
transition : 'message suivant'
},
'51#1355': {
ordre : 1355,
message : 'Pour cela, choisissez le lien <em>chat</em> de votre barre de navigation.',
transition : 'message suivant'
},
'47#1332': {
ordre : 1332,
message : 'Pour nourrir celui-ci, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'6#1356': {
ordre : 1356,
message : 'Pour obtenir des noisettes rapidement, vous pouvez également vendre directement vos objets au brocanteur.',
transition : 'message suivant'
},
'6#1357': {
ordre : 1357,
message : 'Le brocanteur rachète tous vos objets à la moitié du prix de base.',
transition : 'message suivant'
},
'9#1308': {
ordre : 1308,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_mesquiner2.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_mesquiner2.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-lash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'34#1311': {
ordre : 1311,
message : 'Vous venez de passer au niveau <em>Jeunot / Jeunette</em>.',
transition : 'message suivant'
},
'47#1333': {
ordre : 1333,
message : 'Cliquez ensuite sur <em>Manger</em> et choisissez votre nourriture. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'40#1314': {
ordre : 1314,
message : 'Vous venez de passer au niveau <em>Villageois(e)</em>.',
transition : 'message suivant'
},
'4#1296': {
ordre : 1296,
message : 'Pour gagner des noisettes, vous pouvez désormais participer à des campagnes de football.',
transition : 'message suivant'
},
'4#1297': {
ordre : 1297,
message : 'Si vous avez déposé votre ballon dans votre nid, remettez-le dans votre <strong>Inventaire</strong>.',
transition : 'message suivant'
},
'10#1216': {
ordre : 1216,
message : 'Venez interagir avec les autres joueurs et participer aux discussions sur le forum !',
transition : 'message suivant'
},
'10#1217': {
ordre : 1217,
message : 'Il s\'agit d\'un lieu de rencontres et d\'échanges entre joueurs dans lequel vous pourrez vous impliquer dans la communauté Nutsy.net.',
transition : 'message suivant'
},
'10#1218': {
ordre : 1218,
message : 'Celui-ci est également une mine d\'informations, d\'astuces et d\'entre-aide pour le jeu.',
transition : 'message suivant'
},
'10#1219': {
ordre : 1219,
message : 'Pour y accéder, cliquez sur le lien <em>Forum</em> en haut de chaque page.',
transition : 'message suivant'
},
'4#1298': {
ordre : 1298,
message : 'Allez à la taverne via le bandeau de navigation et rejoignez les autres joueurs dans une campagne de foot.',
transition : 'message suivant'
},
'4#1299': {
ordre : 1299,
message : 'Quand la partie aura atteint le nombre minimum de participants, le créateur pourra lancer la campagne.',
transition : 'message suivant'
},
'4#1300': {
ordre : 1300,
message : 'De nombreuses autres campagnes sont disponibles à la taverne. Essayez les !',
transition : 'message suivant'
},
'4#1301': {
ordre : 1301,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_campagnes_02.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_campagnes_02.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-lash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'43#14': {
ordre : 14,
message : 'Vous venez de passer au niveau <em>Notable</em>.',
transition : 'message suivant'
},
'26#1245': {
ordre : 1245,
message : 'Vous n\'avez presque plus de savons en stock.',
transition : 'en savoir plus'
},
'26#1246': {
ordre : 1246,
message : 'Pour en acheter, allez au marché dans l\'échoppe <em>Accessoires</em>, ou rejoignez un <em>Raid sur la fabrique de savon</em> à la taverne.',
transition : 'message suivant'
},
'29#1125': {
ordre : 1125,
message : 'Votre mesquinerie a bien atteint sa cible. Attention à la vengeance !',
transition : 'message suivant'
},
'27#1147': {
ordre : 1147,
message : 'Vous n\'avez plus rien à manger en stock !',
transition : 'en savoir plus'
},
'27#1148': {
ordre : 1148,
message : 'Partez découvrir les zones d\'exploration dans les différents quartiers de votre village.',
transition : 'message suivant'
},
'27#1149': {
ordre : 1149,
message : 'Si vous êtes paresseux ou pressé, vous pouvez également acheter de quoi vous nourrir directement sur le marché.',
transition : 'message suivant'
},
'5#1353': {
ordre : 1353,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_explorer_02.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_explorer_02.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'51#1354': {
ordre : 1354,
message : 'Communiquez en direct avec vos amis grâce au chat, et rencontrez les autres joueurs de Nutsy.net !',
transition : 'message suivant'
},
'41#1309': {
ordre : 1309,
message : 'Vous venez de passer au niveau <em>Acrobate des feuillages</em>.',
transition : 'message suivant'
},
'63#1310': {
ordre : 1310,
message : 'Vous venez de passer au niveau <em>Apprenti(e)</em>.',
transition : 'message suivant'
},
'13#1254': {
ordre : 1254,
message : 'Quand vous manquez de noisettes, allez faire un tour à la banque.',
transition : 'message suivant'
},
'13#1255': {
ordre : 1255,
message : 'Pour accéder à celle-ci, cliquez sur le lien <em>Banque</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'13#1256': {
ordre : 1256,
message : 'Vous pourrez y obtenir des noisettes en envoyant un sms surtaxé ou en appelant un numéro surtaxé.',
transition : 'message suivant'
},
'2#1261': {
ordre : 1261,
message : 'Pour rendre votre écureuil heureux vous devez le nourrir, le laver et en prendre soin tous les jours.',
transition : 'message suivant'
},
'2#1262': {
ordre : 1262,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'2#1263': {
ordre : 1263,
message : 'Cliquez ensuite sur les différentes actions afin d\'interagir avec votre écureuil.',
transition : 'message suivant'
},
'2#1264': {
ordre : 1264,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_manger_06.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_manger_06.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'3#1265': {
ordre : 1265,
message : 'Vous devez également aménager le nid de votre écureuil et en faire un endroit douillet.',
transition : 'message suivant'
},
'3#1266': {
ordre : 1266,
message : 'Dans la page nid, cliquez sur un objet de votre inventaire puis placez-le dans votre nid.',
transition : 'message suivant'
},
'3#1267': {
ordre : 1267,
message : 'Vous devez ensuite choisir un emplacement libre, puis cliquez pour relacher l\'objet.',
transition : 'message suivant'
},
'3#1268': {
ordre : 1268,
message : 'Pour interagir avec un objet ou le déplacer à nouveau, cliquez sur celui-ci, un menu rouge apparaîtra.',
transition : 'message suivant'
},
'25#1337': {
ordre : 1337,
message : 'Une de vos campagnes est prête à être démarrée.',
transition : 'en savoir plus'
},
'25#1338': {
ordre : 1338,
message : 'Dès que le nombre minimum de participants est atteint, vous pouvez démarrer une campagne.',
transition : 'message suivant'
},
'24#1130': {
ordre : 1130,
message : 'Vous avez du courrier ! Consultez votre boîte aux lettres.',
transition : 'en savoir plus'
},
'24#1131': {
ordre : 1131,
message : 'Pour lire vos messages, cliquez sur la boîte aux lettres dans le jardin au pied de votre nid.',
transition : 'message suivant'
},
'25#1339': {
ordre : 1339,
message : 'Pour cela rendez vous à la taverne, via le bandeau de navigation.',
transition : 'message suivant'
},
'25#1340': {
ordre : 1340,
message : 'Votre campagne apparaît en rouge, vous pouvez désormais cliquer sur <em>Démarrer la campagne</em>.',
transition : 'message suivant'
},
'35#1135': {
ordre : 1135,
message : 'Vous ne possédez plus aucune alerte SMS.',
transition : 'en savoir plus'
},
'35#1136': {
ordre : 1136,
message : 'Les alertes SMS vous permette d\'être prévenu directement sur votre portable lorsque qu\'un évènement survient pour votre personnage.',
transition : 'message suivant'
},
'35#1137': {
ordre : 1137,
message : 'Rendez vous à la banque pour créditer votre réserve d\'alertes SMS !',
transition : 'message suivant'
},
'53#1174': {
ordre : 1174,
message : 'Le saviez-vous ? Vous pouvez recharger votre réserve d\'eau grâce au collecteau.',
transition : 'message suivant'
},
'53#1175': {
ordre : 1175,
message : 'Le collecteau vous permet de remplir votre réserve d\'eau sans utiliser de point d\'action.',
transition : 'message suivant'
},
'53#1176': {
ordre : 1176,
message : 'N\'hésitez plus ! le collecteau, c\'est ce qu\'il vous faut !',
transition : 'message suivant'
},
'3#1269': {
ordre : 1269,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_amenager_02.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_amenager_02.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'6#1358': {
ordre : 1358,
message : 'Choisissez <em>Inventaire</em> dans le bandeau de navigation, cliquez ensuite sur <em>la noisette</em> pour mettre en vente un objet. ',
transition : 'message suivant'
},
'6#1359': {
ordre : 1359,
message : 'Vous pouvez désormais choisir <em>Vendre au brocanteur</em> pour vous débarrasser plus rapidement de l\'objet.',
transition : 'message suivant'
},
'6#1360': {
ordre : 1360,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_vendre2.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_vendre2.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-lash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'52#1361': {
ordre : 1361,
message : 'Négociez et gagnez des noisettes en vendant vos objets à des écureuils sur le marché.',
transition : 'message suivant'
},
'52#1362': {
ordre : 1362,
message : 'Choisissez <em>Inventaire</em> dans le bandeau de navigation, cliquez ensuite sur <em>la noisette</em> pour mettre en vente un objet. ',
transition : 'message suivant'
},
'52#1363': {
ordre : 1363,
message : 'Indiquez alors votre prix en fonction de la concurrence sur le marché et du nombre d\'objets à vendre.',
transition : 'message suivant'
},
'52#1364': {
ordre : 1364,
message : 'Il ne reste plus qu\'à attendre les acheteurs potentiels.',
transition : 'message suivant'
},
'33#1120': {
ordre : 1120,
message : 'Votre écureuil est malade et ne se sent pas bien.',
transition : 'en savoir plus'
},
'33#1121': {
ordre : 1121,
message : 'Pour le guérir, choisissez <em>Soins</em> dans le bandeau de navigation, puis l\'action <em>Soigner</em>.',
transition : 'message suivant'
},
'15#978': {
ordre : 978,
message : 'Vous pouvez rendre visite aux villages voisins.',
transition : 'message suivant'
},
'15#979': {
ordre : 979,
message : 'Pour visiter un village voisin, choisissez <em>Village</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'15#980': {
ordre : 980,
message : 'Cliquez ensuite sur <em>visiter un autre village</em> sous la carte des quartiers pour trouver votre destination.',
transition : 'message suivant'
},
'33#1122': {
ordre : 1122,
message : 'Pour vous soigner, vous devez posséder les remèdes appropriés. Vous pouvez vous procurer ceux-ci sur le marché.',
transition : 'message suivant'
},
'39#1123': {
ordre : 1123,
message : 'Votre mesquinerie a échoué. Tentez à nouveau votre chance !',
transition : 'en savoir plus'
},
'39#1124': {
ordre : 1124,
message : 'Votre cible peut se protéger de vos attaques à l\'aide de parades. Peut-être devriez vous tenter un autre type de mesquinerie ?',
transition : 'message suivant'
},
'18#1220': {
ordre : 1220,
message : 'Vous pouvez communiquer par courrier avec vos amis.',
transition : 'message suivant'
},
'18#1221': {
ordre : 1221,
message : 'Pour relever votre courrier, cliquez sur votre boîte aux lettres en bas de votre nid.',
transition : 'message suivant'
},
'18#1222': {
ordre : 1222,
message : 'Pour envoyer une lettre, cliquez sur <em>Envoyer un message</em>, rédigez celui-ci, puis cliquez sur <em>Envoyer</em>.',
transition : 'message suivant'
},
'16#1238': {
ordre : 1238,
message : 'Vous pouvez rendre visite à vos voisins  si ceux-ci le permettent.',
transition : 'message suivant'
},
'16#1239': {
ordre : 1239,
message : 'Pour visiter un nid, allez dans le quartier du village où il se trouve, ou bien utilisez l\'outil de recherche du village.',
transition : 'message suivant'
},
'16#1240': {
ordre : 1240,
message : 'Cliquez ensuite sur son arbre puis sur l\'icone <em>Visiter le nid</em>.',
transition : 'message suivant'
},
'12#1083': {
ordre : 1083,
message : 'Vous pouvez consulter l\'historique de vos actions ainsi que les objets gagnés dans le journal des évènements.',
transition : 'message suivant'
},
'12#1084': {
ordre : 1084,
message : 'Pour ouvrir celui-ci choisissez <em>Historique</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'12#1085': {
ordre : 1085,
message : 'Vous y trouverez également des informations sur votre écureuil et ses scores.',
transition : 'message suivant'
},
'14#1086': {
ordre : 1086,
message : 'Lorsque vous vous absentez longtemps, loin de votre écureuil, vous pouvez le mettre en hibernation.',
transition : 'message suivant'
},
'14#1087': {
ordre : 1087,
message : 'A votre retour, vous retrouverez votre écureuil dans le même état où vous l\'aurez laissé.',
transition : 'message suivant'
},
'14#1088': {
ordre : 1088,
message : 'Pour lancer l\'hibernation, choisissez <em>Soins</em> dans le bandeau de navigation, puis <em>Mettre en hibernation</em>.',
transition : 'message suivant'
},
'11#1247': {
ordre : 1247,
message : 'Au moindre problème, n\'hésitez pas à consulter l\'aide du jeu.',
transition : 'message suivant'
},
'11#1248': {
ordre : 1248,
message : 'Vous trouverez les liens Manuel et FAQ (Foire Aux Questions) en haut de chaque page.',
transition : 'message suivant'
},
'52#1365': {
ordre : 1365,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_vendre2.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_vendre2.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-lash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'8#1277': {
ordre : 1277,
message : 'Allez régulièrement faire un tour au marché, soyez à l\'affût de la moindre bonne affaire !',
transition : 'message suivant'
},
'8#1278': {
ordre : 1278,
message : 'Pour allez au marché, cliquez sur le lien <em>Marché</em> puis choisissez votre échoppe.',
transition : 'message suivant'
},
'8#1279': {
ordre : 1279,
message : 'Les objets sur fond bleu représentent les objets de la coopérative. Les autres sont ceux vendus par d\'autres écureuils.',
transition : 'message suivant'
},
'8#1280': {
ordre : 1280,
message : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" class="animation_tutoriel">\n  <param name="movie" value="/manuel/tutorial_marche_02.swf">\n  <param name="quality" value="high">\n  <param name="wmode" value="transparent" />\n  <embed src="/manuel/tutorial_marche_02.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-lash"  wmode="transparent"></embed>\n</object>',
transition : 'message suivant'
},
'7#1257': {
ordre : 1257,
message : 'Vous pouvez fabriquer des objets grâce aux établis puis vendre votre production sur le marché.',
transition : 'message suivant'
},
'7#1258': {
ordre : 1258,
message : 'Vous pourrez découvrir différents établis sur le marché comme le métier à tisser, la ruche, la presse, ...',
transition : 'message suivant'
},
'7#1259': {
ordre : 1259,
message : 'Une fois votre établi acheté, placez le dans votre nid et cliquez sur celui-ci pour découvrir les fabrications disponibles.',
transition : 'message suivant'
},
'7#1260': {
ordre : 1260,
message : 'Pour fabriquer un objet, vous devez avoir  les points d\'action et les matériaux nécessaires dans votre inventaire.',
transition : 'message suivant'
},
'66#1368': {
ordre : 1368,
message : 'Vous venez de passer au niveau <em>Esprit des forêts</em>.',
transition : 'message suivant'
},
'9#1304': {
ordre : 1304,
message : 'Vous avez maintenant la possibilité de mesquiner un autre écureuil.',
transition : 'message suivant'
},
'32#1315': {
ordre : 1315,
message : 'Vous venez de passer au niveau <em>Prince des bois</em>.',
transition : 'message suivant'
},
'44#1316': {
ordre : 1316,
message : 'Vous venez de passer au niveau <em>Maître des cimes</em>.',
transition : 'message suivant'
},
'44#1317': {
ordre : 1317,
message : 'Vous pouvez désormais réaliser l\'action <em>prendre un bain</em> sans PA sur la baignoire (3 étoiles d\'écologie).',
transition : 'message suivant'
},
'42#1318': {
ordre : 1318,
message : 'Vous venez de passer au niveau <em>Aventurier(e)</em>.',
transition : 'message suivant'
},
'42#1319': {
ordre : 1319,
message : 'Vous pouvez désormais réaliser l\'action <em>boire du lait</em> qui vous fera économiser 1 PA sur le réfrigérateur (1 étoile de cuisine).',
transition : 'message suivant'
},
'1#1324': {
ordre : 1324,
message : 'Bienvenue sur Nutsy.net !',
transition : 'message suivant'
},
'1#1325': {
ordre : 1325,
message : 'Cet assistant vous guidera tout au long du jeu.',
transition : 'message suivant'
},
'1#1326': {
ordre : 1326,
message : 'Il vous apprendra à vous occuper de votre écureuil et vous accompagnera dans la découverte de l\'univers Nutsy.net.',
transition : 'message suivant'
},
'55#1327': {
ordre : 1327,
message : 'Participez à la vie du forum et à sa convivialité.',
transition : 'message suivant'
},
'55#1328': {
ordre : 1328,
message : 'N\'hésitez pas à rapporter les abus (insultes,...) aux modérateurs en cliquant sur <em>Rapporter un abus</em>',
transition : 'message suivant'
},
'55#1329': {
ordre : 1329,
message : 'Le message sera alors examiné par l\'équipe de modération du site et éventuellement supprimé.',
transition : 'message suivant'
},
'54#1344': {
ordre : 1344,
message : 'Le saviez vous ? Vous pouvez recycler vos objets en utilisant le recyclotritus.',
transition : 'en savoir plus'
},
'54#1345': {
ordre : 1345,
message : 'Grâce au recyclotritus vous pouvez obtenir des matériaux pour environ 80% de la valeur de l\'objet recyclé.',
transition : 'message suivant'
},
'54#1346': {
ordre : 1346,
message : 'Foncez au marché pour vous le procurer ! Vous ne le regretterez pas.',
transition : 'message suivant'
},
'5#1347': {
ordre : 1347,
message : 'Besoin d\'objets ? Besoin de nourriture ? Explorez votre village et ramenez ce qu\'il vous faut !',
transition : 'message suivant'
},
'5#1348': {
ordre : 1348,
message : 'Déplacez vous dans les différents quartiers de votre village, afin de trouver les tentes des campeurs.',
transition : 'message suivant'
},
'5#1349': {
ordre : 1349,
message : 'Cliquez sur la zone d\'exploration (le campement) et choisissez <em>Explorer</em>.',
transition : 'message suivant'
},
'5#1350': {
ordre : 1350,
message : 'Choisissez alors le ballon de foot, pour le rechercher en priorité.',
transition : 'message suivant'
},
'5#1351': {
ordre : 1351,
message : 'Deux heures plus tard, votre écureuil sera de retour avec les différents objets trouvés et votre ballon de foot.',
transition : 'message suivant'
},
'67#1369': {
ordre : 1369,
message : 'Vous venez de passer au niveau <em>Grand gourou des plaines</em>.',
transition : 'message suivant'
},
'68#1370': {
ordre : 1370,
message : 'Vous venez de passer au niveau <em>Mânes des orées</em>.',
transition : 'message suivant'
},
'20#1371': {
ordre : 1371,
message : 'Votre écureuil a un petit creux.',
transition : 'en savoir plus'
},
'20#1372': {
ordre : 1372,
message : 'Vous devez nourrir votre personnage chaque jour de manière équilibrée.',
transition : 'message suivant'
},
'20#1373': {
ordre : 1373,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'20#1374': {
ordre : 1374,
message : 'Cliquez ensuite sur <em>Manger</em> et choisissez votre nourriture. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'50#1375': {
ordre : 1375,
message : 'Vous n\'avez pratiquement plus une goutte d\'eau en réserve.',
transition : 'en savoir plus'
},
'50#1376': {
ordre : 1376,
message : 'Pour refaire les niveaux, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'50#1377': {
ordre : 1377,
message : 'Cliquez ensuite sur l\'action <em>Aller chercher de l\'eau</em>. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'48#1378': {
ordre : 1378,
message : 'Votre écureuil est vraiment très sale et repoussant !',
transition : 'en savoir plus'
},
'48#1379': {
ordre : 1379,
message : 'Pensez à laver votre personnage régulièrement. Si celui-ci sent mauvais, vous perdrez des points de sociabilité.',
transition : 'message suivant'
},
'48#1380': {
ordre : 1380,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'48#1381': {
ordre : 1381,
message : 'Cliquez ensuite sur l\'action <em>Laver</em>. Ceci vous coûtera 1 point d\'action et nécessitera 1 savon en réserve.',
transition : 'message suivant'
},
'49#1382': {
ordre : 1382,
message : 'Votre écureuil est complètement déshydraté.',
transition : 'en savoir plus'
},
'49#1383': {
ordre : 1383,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'49#1384': {
ordre : 1384,
message : 'Cliquez ensuite sur <em>Boire</em>. Cette action nécessitera 1 point d\'action et suffisamment d\'eau en réserve.',
transition : 'message suivant'
},
'28#1399': {
ordre : 1399,
message : 'Attention ! votre réserve d\'eau baisse dangereusement.',
transition : 'en savoir plus'
},
'28#1400': {
ordre : 1400,
message : 'Pour refaire les niveaux, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'28#1401': {
ordre : 1401,
message : 'Cliquez ensuite sur l\'action <em>Aller chercher de l\'eau</em>. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'36#1402': {
ordre : 1402,
message : 'Vous n\'avez pratiquement plus aucune noisette !',
transition : 'en savoir plus'
},
'36#1403': {
ordre : 1403,
message : 'Pour acheter des noisettes, choisissez <em>Banque</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'36#1404': {
ordre : 1404,
message : 'Vous pouvez également participer à des campagnes à la Taverne au centre de votre village.',
transition : 'message suivant'
},
'23#1405': {
ordre : 1405,
message : 'Votre écureuil aurait besoin d\'une petite douche.',
transition : 'en savoir plus'
},
'23#1406': {
ordre : 1406,
message : 'Pensez à laver votre personnage régulièrement. Si celui-ci sent mauvais, vous perdrez des points de sociabilité.',
transition : 'message suivant'
},
'23#1407': {
ordre : 1407,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'23#1408': {
ordre : 1408,
message : 'Cliquez ensuite sur l\'action <em>Laver</em>. Ceci vous coûtera 1 point d\'action et nécessitera 1 savon en réserve.',
transition : 'message suivant'
},
'21#1409': {
ordre : 1409,
message : 'Votre écureuil a soif.',
transition : 'en savoir plus'
},
'21#1410': {
ordre : 1410,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'21#1411': {
ordre : 1411,
message : 'Cliquez ensuite sur <em>Boire</em>. Cette action nécessitera 1 point d\'action et suffisamment d\'eau en réserve.',
transition : 'message suivant'
},
'61#1418': {
ordre : 1418,
message : 'Votre écureuil a une carence en oligo-éléments.',
transition : 'en savoir plus'
},
'61#1419': {
ordre : 1419,
message : 'Vous devez nourrir votre personnage chaque jour de manière équilibrée.',
transition : 'message suivant'
},
'61#1420': {
ordre : 1420,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'61#1421': {
ordre : 1421,
message : 'Cliquez ensuite sur <em>Manger</em> et choisissez votre nourriture. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'62#1422': {
ordre : 1422,
message : 'Votre écureuil a besoin de sels minéraux.',
transition : 'en savoir plus'
},
'62#1423': {
ordre : 1423,
message : 'Vous devez nourrir votre personnage chaque jour de manière équilibrée.',
transition : 'message suivant'
},
'62#1424': {
ordre : 1424,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'62#1425': {
ordre : 1425,
message : 'Cliquez ensuite sur <em>Manger</em> et choisissez votre nourriture. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'60#1426': {
ordre : 1426,
message : 'Votre écureuil a besoin d\'un bon coup de vitamines.',
transition : 'en savoir plus'
},
'60#1427': {
ordre : 1427,
message : 'Vous devez nourrir votre personnage chaque jour de manière équilibrée.',
transition : 'message suivant'
},
'60#1428': {
ordre : 1428,
message : 'Pour cela, choisissez <em>Soins</em> dans le bandeau de navigation.',
transition : 'message suivant'
},
'60#1429': {
ordre : 1429,
message : 'Cliquez ensuite sur <em>Manger</em> et choisissez votre nourriture. Cela vous coûtera 1 point d\'action.',
transition : 'message suivant'
},
'17#1433': {
ordre : 1433,
message : 'Le saviez-vous ? Nutsy.net a été lancé officiellement le 17 novembre 2004.',
transition : 'message suivant'
},
'17#1434': {
ordre : 1434,
message : 'Il a été développé pendant plus d\'un an et demi par quatre étudiants motivés.',
transition : 'message suivant'
},
'17#1435': {
ordre : 1435,
message : 'N\'hésitez pas à les soutenir en envoyant des SMS à la banque pour permettre à l\'aventure de continuer.',
transition : 'message suivant'
},
'45#1436': {
ordre : 1436,
message : 'Envie de faire du shopping ? Il vous manque des noisettes ? N\'attendez plus !! Allez faire un tour à la banque !',
transition : 'en savoir plus'
},
'45#1437': {
ordre : 1437,
message : 'Obtenez des crédits en envoyant un SMS surtaxé ou en téléphonant à un numéro surtaxé.',
transition : 'message suivant'
},
'45#1438': {
ordre : 1438,
message : 'Rendez vous à la page Banque pour en savoir plus !',
transition : 'message suivant'
},
'46#1439': {
ordre : 1439,
message : 'Décorez votre nid avec les objets de saison ou effectuez les campagnes associées',
transition : 'en savoir plus'
},
'46#1440': {
ordre : 1440,
message : 'Obtenez des crédits en envoyant un SMS surtaxé ou en téléphonant à un numéro surtaxé.',
transition : 'message suivant'
},
'46#1441': {
ordre : 1441,
message : 'Rendez vous à la page Banque pour en savoir plus !',
transition : 'message suivant'
},
'56#1442': {
ordre : 1442,
message : 'Besoin de quelques points d\'action supplémentaires ? N\'attendez plus !! Allez faire un tour à la banque !',
transition : 'message suivant'
},
'56#1443': {
ordre : 1443,
message : 'Obtenez des crédits en envoyant un SMS surtaxé ou en téléphonant à un numéro surtaxé.',
transition : 'message suivant'
},
'56#1444': {
ordre : 1444,
message : 'Rendez vous à la page Banque pour en savoir plus !',
transition : 'message suivant'
},
'22#1445': {
ordre : 1445,
message : 'Venez soutenir l\'équipe du jeu en vous rendant à la banque de votre village !',
transition : 'en savoir plus'
},
'22#1446': {
ordre : 1446,
message : 'Pour soutenir Nutsy.net, envoyez un SMS de temps en temps pour aider aux évolutions du jeu.',
transition : 'message suivant'
},
'22#1447': {
ordre : 1447,
message : 'Nutsy.net est un jeu gratuit sur internet qui n\'existerait pas sans votre soutien. Merci d\'avance.',
transition : 'message suivant'
}
}
Global.publier ('type_conseil_etape', type_conseil_etape);

});

new Module ('conseiller',
            ['mvc', 'ajax.xmlextras', 'cookie', 'base.type_conseil'],
	    [],
	    function () {

/**
 * Cree un conseiller.
 */
function Conseiller ()
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;

	Observable.call (this);

	this._ref_type_conseil = null;
	this._position_etape = null;

	this._chargerConseil ();
}
Global.heriter (Conseiller, Observable);

Conseiller.INTERVAL_RAFRAICHISSEMENT = 600000;

/**
 * Accesseur sur le type de conseil courant.
 * @return la reference du type de conseil
 */
Conseiller.prototype._valRefTypeConseil = function ()
{
	Global.assert (this._ref_type_conseil);

	return this._ref_type_conseil;
}

/**
 * Modifie le type de conseil courant, et stocke sa valeur dans un cookie
 * pour la conserver lors du prochain rechargement.
 * @param ref_type_conseil la reference du type de conseil
 */
Conseiller.prototype._modifierRefTypeConseil = function (ref_type_conseil)
{
	Global.assert (ref_type_conseil);
	
	this._ref_type_conseil = ref_type_conseil;
	Cookie.modifier ('conseiller_ref_type_conseil', ref_type_conseil);
}

/**
 * Efface la reference au type de conseil courant.
 * Supprime egalement le cookie associe.
 */
Conseiller.prototype._effacerRefTypeConseil = function ()
{
	this._ref_type_conseil = null;
	Cookie.effacer ('conseiller_ref_type_conseil');
}

/**
 * Accesseur sur la position courante dans les messages du type conseil.
 * @return la position
 */
Conseiller.prototype._valPositionEtape = function ()
{
	Global.assert (this._position_etape);

	return this._position_etape;
}

/**
 * Modifie la position courante dans les messages du type conseil, et stocke
 * sa valeur dans un cookie pour la conserver lors du prochain rechargement.
 * @param position_etape la position
 */
Conseiller.prototype._modifierPositionEtape = function (position_etape)
{
	Global.assert (position_etape);
	
	this._position_etape = position_etape;
	Cookie.modifier ('conseiller_position_etape',
			 position_etape);

	this._notifierModification ();
}

/**
 * Efface la position courante dans les messages du type conseil.
 * Supprime egalement le cookie associe.
 */
Conseiller.prototype._effacerPositionEtape = function ()
{
	this._position_etape = null;
	Cookie.effacer ('conseiller_position_etape');

	this._notifierModification ();
}

Conseiller.prototype.aConseilCourant = function ()
{
	return this._ref_type_conseil != null;
}

Conseiller.prototype.valConseilCourant = function ()
{
	var ref_type_conseil = this._valRefTypeConseil ();

	var conseil = type_conseil[ref_type_conseil];
	Global.assert (conseil);

	return conseil;
}

/**
 * Relation d'ordre pour comparer les ordre d'affichage des etapes.
 * @param etape1 la premiere etape
 * @param etape2 la deuxieme etape
 * @return la relation d'ordre suivant le prototype de cmp
 */
Conseiller._compare_ordre = function (etape1, etape2) {
	return etape1['ordre'] - etape2['ordre'];
}

/**
 * Retourne la liste des etapes ordonnee du type de conseil courant.
 * @return la liste
 */
Conseiller.prototype._listeEtapes = function ()
{
	var conseil = this.valConseilCourant ();

	var liste_etapes = new Array ();
	for (var i = 0; i < conseil.etapes.length; i++) {
		var etape = type_conseil_etape [conseil.etapes[i]];
		Global.assert (etape);
		
		liste_etapes.push (etape);
	}
	Global.assert (liste_etapes.length > 0);

	liste_etapes.sort (Conseiller._compare_ordre);
	
	return liste_etapes;
}

Conseiller.prototype.valEtapeCourante = function ()
{
	var ref_type_conseil = this._valRefTypeConseil ();
	var position_etape = this._valPositionEtape ();

	var liste_etapes = this._listeEtapes ();
	Global.assert (position_etape - 1 < liste_etapes.length);
	var etape_courante = liste_etapes[position_etape - 1];

	/* FIXME : devrait provenir de la base */
	if (position_etape == liste_etapes.length)
		etape_courante['transition'] = 'terminer';

	return etape_courante;
}

/**
 * Methode de rappel pour le traitement de la reponse a la requete
 * de chargerConseil.
 * Recupere et affiche le conseil courant, ou demarre une temporisation afin de
 * reexecuter la consultation plus tard s'il n'y en a pas.
 * @param reponse la reponse a la requete
 */
Conseiller.prototype._chargerConseilRappel = function (reponse)
{
	Global.assert (reponse);
	
	var liste_conseils = reponse.getElementsByTagName ('conseil');
	Global.assert (liste_conseils.length == 1);
	
	var conseil = liste_conseils[0];
	var ref_type_conseil = conseil.getAttribute ('ref_type_conseil');
	
	if (ref_type_conseil) {
		this._modifierRefTypeConseil (ref_type_conseil);
		this._modifierPositionEtape (1);

		this._notifierModification ();
	} else {
		setTimeout (Global.associer (this, this._chargerConseil),
			    Conseiller.INTERVAL_RAFRAICHISSEMENT);
	}
}

/**
 * Charge le conseil courant depuis la sauvegarde du contexte dans les cookies,
 * ou depuis la base a defaut, puis affiche celui-ci.
 */
Conseiller.prototype._chargerConseil = function ()
{
	var tab_recup_conseil = Cookie.valeur ('conseiller_ref_type_conseil');
	var tab_recup_etape = Cookie.valeur ('conseiller_position_etape');
	
	if (tab_recup_conseil && tab_recup_etape ) {
		this._modifierRefTypeConseil (parseInt (tab_recup_conseil));
		this._modifierPositionEtape (parseInt (tab_recup_etape));
		
		this._notifierModification ();
	} else {
		/* absence de cookie => base */
		var rappel = Global.associer (this,
					       this._chargerConseilRappel)
		XML.charger ('/jeu/conseiller/conseil_recuperer.xml',
			     rappel); 
	}
}

/**
 * Termine l'execution du conseil courant.
 */
Conseiller.prototype.terminerConseil = function ()
{
	var ref_type_conseil = this._valRefTypeConseil ();	

	this._effacerRefTypeConseil ();
	this._effacerPositionEtape ();

	this._notifierModification ();

	var rappel = Global.associer (this, this._chargerConseil);
	XML.charger ('/jeu/conseiller/proc_conseil_terminer'
		     + '?ref_type_conseil:int=' + ref_type_conseil,
		     rappel);
}

/**
 * Passe a l'etape suivante du conseil courant.
 */
Conseiller.prototype.passerEtapeSuivante = function ()
{
	var position_etape = this._valPositionEtape ();

	var liste_etapes = this._listeEtapes ();
	Global.assert (position_etape < liste_etapes.length);

	this._modifierPositionEtape (position_etape + 1);

	this._notifierModification ();
}

function VueConseiller (conseiller)
{
	/* passer l'initialisation pour les prototypes des sous classes
	 */
	if (Global.estDefinition ()) return;
	
	Global.assert (conseiller);

	Vue.call (this, conseiller);
}
Global.heriter (VueConseiller, Vue);

VueConseiller.prototype._valConseiller = function ()
{
	return this._valObjet ();
}

VueConseiller.prototype._creerElement = function ()
{
	Global.assert (!this._element);

	var conseiller = this._valConseiller ();

	var element = document.createElement ('div');
	element.id = 'conseiller';

	return element;
}

VueConseiller.prototype.synchroniser = function ()
{
	var element = this.valElement ();
	var conseiller = this._valConseiller ();

	while (element.firstChild)
		element.removeChild (element.firstChild);

	if (!conseiller.aConseilCourant ())
		return;

	var etape = conseiller.valEtapeCourante ();

	var message = document.createElement ('div');
	message.id = 'conseiller_message';
	message.innerHTML = etape['message'];
	element.appendChild (message);

	var transition = document.createElement ('div');
	transition.id = 'conseiller_transition';
	element.appendChild (transition);

	if (etape['transition'] == 'message suivant'
	    || etape['transition'] ==  'en savoir plus') {
		var lien_suivant = document.createElement ('a');
		lien_suivant.href = '#';
		lien_suivant.onclick
			= Global.associer (conseiller,
					   conseiller.passerEtapeSuivante);

		var texte = '» ' + etape['transition'];
		var texte_suivant = document.createTextNode (texte);
		lien_suivant.appendChild (texte_suivant);

		transition.appendChild (lien_suivant);
	}

	if (etape['transition'] == 'en savoir plus'
	    || etape['transition'] == 'terminer') {
		var lien_terminer = document.createElement ('a');
		lien_terminer.href = '#';
		lien_terminer.onclick
			= Global.associer (conseiller,
					   conseiller.terminerConseil);

		var texte_terminer = document.createTextNode ('» terminer');
		lien_terminer.appendChild (texte_terminer);

		transition.appendChild (lien_terminer);
	}

	if (etape['transition'] == 'javascript') {
		alert ('VueConseiller.synchroniser : '
		       + 'transition javascript non implementee');
	}
}

function _init_conseiller () 
{
        var noeud_conseiller = document.getElementById ('conseiller');
        if (noeud_conseiller) {
	    var conseiller = new Conseiller ();
	    var vue_conseiller = new VueConseiller (conseiller);


	    noeud_conseiller.parentNode.replaceChild (vue_conseiller.valElement (),
	        				    noeud_conseiller);
	}
}
Init.ajouterRappel (_init_conseiller, false);

});

