/*
	FONCTIONS UTILES :

	> DOM_outerText( node )
	> DOM_outerVisibleText( node )
	> DOM_outerHTML( node )
	> DOM_innerHTML( node )
	> DOM_outerColorHTML( node )
	> DOM_getStyle( p_oNode, p_styleProp )
	> DOM_getParentWindow( p_oNode ) ;
		
	> DOM_removeAllChilds( p_oNode )

	> DOM_showNode( p_oNode )
	> DOM_hideNode( p_oNode )

	> DOM_setNodeWidth ( p_oNode, w )
	> DOM_setNodeHeight ( p_oNode, h )

	> DOM_getNodePosX
	> DOM_getNodePosY( p_oNode )
	> DOM_getNodeWidth( p_oNode )
	> DOM_getNodeHeight( p_oNode )

	> DOM_hideOrShow( p_oNode )
	> DOM_execJavascript( p_oNode )
	> DOM_GetChildNodeByTagName( p_oNode, p_sNodeName, p_optionalParamName, p_optionalParamValue )
	> DOM_GetParentNodeByTagName( p_oNode, p_sNodeName, p_optionalParamName, p_optionalParamValue )
	
	API :
	
	CONSTRUCTEUR

		DOM_Manager( p_jsName )
		
	METHODES :
	
		DOM_Path	getPath ( node )
		node		appendHTML ( node, monHTML )
		node		appendText ( node, datas )
		node		appendElement ( node, tag_name, aAttributs, aValues )
		int			getNodePos ( node )
		node		getNodeByPath ( path )
		string		getJSName ( )
		void		addActionListener ( pFunction )
		void		_sendEvent ( eventCode, aMessages, NumMessages )
		void		_actionListener ( eventCode, aMessages, NumMessages )				{	}
		node		getDocumentNodeByNode( node );


	CONSTRUCTEUR

		DOM_Path ( p_node, p_dom )

	METHODES :

		int			getNumNodes (  )
		node		getRoot (  )
		string		toString ( )
		string		toHTML ( )
	

	---------------------------------------------------------------------------------------------------


	DOCUMENTATION - PENSE BETE :

	
	--- [ node Object ] ---

		<NamedNodeMap>	<node>.attributes;		// tableau d'objet attributes
		<NamedNodeMap>	<node>.childNodes;		// tableau d'objet elements enfants
		<NamedNodeMap>	<node>.data
		<node>			<node>.firstChild;					// premier enfant de l'element
		<node>			<node>.lastChild;					// dernier...
		<node>			<node>.nextSibling
		string			<node>.nodeName
		int				<node>.nodeType
		string			<node>.nodeValue
		<node>			<node>.parentNode
		<node>			<node>.previousSibling
		string			<node>.text
		string			<node>.xml	( IE !! )
		
		string			<node>.getAttribute( name )			// Recupere la valeur de l'attribut
		Attr			<node>.getAttributeNode( name )		// Recupere l'objet attribut	( IE6+ !!! )
		<node>			<node>.getElementById( id )			// no comment...
		<NodeList>		<node>.getElementsByTagName( name )	// no comment...
		boolean			<node>.hasChildNodes( );

		<node>			document.documentElement;				// pointe vers l'element parent du document

		
		// noeuds
		<node>.appendChild( <node> )
		<node>.insertBefore( newChild, refChild );
		<node> <node>.cloneNode( bool_clone_childs );	// fait une copie d'un element avec oui ou non ses enfants
		<node>.removeChild( <node> );
		<node>.replaceChild( <new_node>, <old_node> );

		// texte
		<node>.appendData( texte )						// rajoute du texte à la fin
		<node_text>.deleteData( offset, count ); 		// efface un certain nbr de caracteres
		<node>.insertData( offset, texte )				// insert du texte à la position
		<node>.replaceData( offset, count, texte )		// remplace count caracteres à la pos offset par texte
		<node> <node>.splitText( offset );				// coupe le noeud courant en 2 noeuds, et renvoie le nouveau créé
		string <node>.substringData( offset, count );	// remplace count caracteres à la pos offset par texte

		// attributs
		<node> document.createAttribute( name );		// Les 2 ...
		<element>.setAttribute( name, value );			//	  ...sont liées
		<element>.setAttributeNode( name );			//	  ...sont liées ( IE6+ !!! )
		<element>.removeAttribute( name );				// Efface par son nom
		<element>.removeAttributeNode( objAttr );		// Efface par son objet	( IE6+ !!! )

		// --- create node ---
		<node> document.createElement( name );
		<node> document.createTextNode( name );
		<node> document.createCDATASection( name );

		doc_frag = document.createDocumentFragment();
		<element>.appendChild( doc_frag );
		
		
		
		____________________________________________________________________________________________

		
	--- [ Attr Object ] ---

		<attr>.name
		<attr>.value

		____________________________________________________________________________________________

		
	--- [ NodeList Object ] ---

		int <NamedNodeMap>.length;					// nombre d'items
		<element> <NamedNodeMap>.item( int pos )			// renvoie l'item à la position pos

		____________________________________________________________________________________________

		
	--- [ NamedNodeMap Object ] ---
	
		int <NamedNodeMap>.length;					// nombre d'items
		<element> <NamedNodeMap>.item( int pos )			// renvoie l'item à la position pos

		<NamedNodeMap>.getNamedItem( str name )		// renvoie l'item nommée name
		<NamedNodeMap>.removeNamedItem( str name )		// efface et renvoie l'item effacée
		<NamedNodeMap>.setNamedItem( objItem )		// ajoute l'item ( seulement attribute ? )
		


	NOTES IMPORTANTES :
	
		Attributes / Style / IE
			Internet Explorer on Windows doesn't recognize styles created using setAttribute
		
*/

var NODE_ELEMENT				= 1;
var NODE_ATTRIBUTE				= 2;
var NODE_TEXT					= 3; 
var NODE_CDATA_SECTION			= 4; 
var NODE_ENTITY_REFERENCE		= 5; 
var NODE_ENTITY					= 6; 
var NODE_PROCESSING_INSTRUCTION	= 7; 
var NODE_COMMENT				= 8; 
var NODE_DOCUMENT				= 9; 
var NODE_DOCUMENT_TYPE			= 10; 
var NODE_DOCUMENT_FRAGMENT		= 11; 
var NODE_NOTATION				= 12; 

// --- Events ---
var DOM_EVENT_SELECT_PATH		= 1;

var DOM_Empty_Tags				= "[img][br][hr]";			// LOWER CASE !!!!


function DOM_Manager( p_jsName )
{
	this._jsName = p_jsName;				// nom de la variable Javascript pour pouvoir ecrire son nom quand on genere du HTML à la volé
	

	// --- renvoie un objet DOM_Path qui permet de recuperer l'arbre dans lequel on est ---
	this.getPath = function ( node )
	{
		return new DOM_Path( node, this );
	}
	
	
/*
	this.createNodeByString = function ( p_strXML )
	{
		
	
	}
*/

	// --- Fonction qui insere le HTML ( apres avoir parsé par HTML_Parser ) dans le noeud node
	this.appendHTML = function ( node, monHTML )
	{
		if ( ! node )
		{
			__DEBUG__( "DOM::appendHTML( ) .. param 1, <node> est null" );
			return;
		}
	
		var currentNode = node;
		var createdNode = null;
		var currentTag = null;
		
		// On parse le tag envoye
		var htmlParser = new HTML_Parser( );
		htmlParser.parseHTML( monHTML );

		currentTag = htmlParser.getRoot( );

		while ( currentTag )
		{
			switch( currentTag.getType( ) )
			{
				case HTML_ELEMENT :	createdNode = this.appendElement( currentNode, currentTag.getTagName( ), currentTag.getAttributs( ), currentTag.getValues( ) );
									break;
				case HTML_TEXT :	createdNode = this.appendText( currentNode, currentTag.getDatas( ) );
									break;
				
				// On ne fait rien
				default:
				case HTML_ROOT :
				
			}

			if ( currentTag.hasChilds( ) )
			{
				currentTag = currentTag._childs[ 0 ];
				if ( createdNode )
				{
					currentNode = createdNode;
//					alert( "move To " + this.getPath( currentNode ) );
				}
			}
			else
			{
				if ( currentTag.getNextTag( ) == null )
				{
					while ( currentTag.getParentNextTag( ) == null && currentTag.getType( ) != HTML_ROOT )
					{
//						alert( "move Back " + "\n\rFrom : " + this.getPath( currentNode ) + "\n\rTo : " + this.getPath( currentNode.parentNode ) );
						currentNode = currentNode.parentNode;
						currentTag = currentTag._parentTag;
					}
					
					currentNode = currentNode.parentNode;
					currentTag = currentTag.getParentNextTag( );
//					alert( "currentTag = " + currentTag );
				}
				else
				{
					if ( currentTag )
					currentTag = currentTag.getNextTag( );
				}
				
			}
		}
		
	}


	this.appendText = function ( node, datas )
	{
		var oNodeDocument = this.getDocumentNodeByNode( node );
//		var newTextNode = editor._rte.getDocument().createTextNode( datas )
		var newTextNode = oNodeDocument.createTextNode( datas )
		return node.appendChild( newTextNode );	// on renvoie le noeud créé ( et à la bonne position )
	}

	this.createDocumentFragmentFromHTML = function( p_oDoc, p_HTML )
	{
		var oDocFragment	= null;
		var node			= null;
		var currentNode	= null;
		var iNumNodes	= 0;
		var i				= 0;
		var nodeToClean	= null;
		
		if ( ie4 )
		{
			// On crée les noeuds à partir du HTML
			node = p_oDoc.createElement( "TEMP" )
			node.insertAdjacentHTML( "beforeEnd", p_HTML );
			
			// On crée le documentFragment et on le remplit !
			oDocFragment = p_oDoc.createDocumentFragment(  );
			currentNode = node.firstChild;
			do 
			{
				oDocFragment.appendChild( currentNode.cloneNode( true ) );
				currentNode = currentNode.nextSibling;
			} while( currentNode );
		}
		else
		{
			// A IMPLEMENTER POUR MOZILLA ...
		}
		return oDocFragment;
	}
	
	this.createTextNode = function ( oDoc, strText )
	{
		return oDoc.createTextNode( strText );
	}
	
	this.appendElement = function ( node, tag_name, aAttributs, aValues )
	{
		var oNodeDocument = this.getDocumentNodeByNode( node );
//		var newNode = editor._rte.getDocument().createElement( tag_name );
		var newNode = oNodeDocument.createElement( tag_name );
		
		if ( ! oNodeDocument.createAttribute ) return null;
		
		var i = 0;

		// Si les parametres attributs sont valides, on les ajoutes
		if ( aAttributs.length == aValues.length )
		{	
			for ( i = 0 ; i < aAttributs.length ; i++ )
			{
				oNodeDocument.createAttribute( aAttributs[ i ] );
				newNode.setAttribute( aAttributs[ i ], aValues[ i ], 0 );
			}
		}
		else
		{
			return null;		// nombre d'arguments / valeurs incoherent
		}
		// On ajoute le nouveau noeud
		return node.appendChild( newNode );		// on renvoie le noeud créé ( et à la bonne position )
	}
	
	this.moveNode = function ( p_sourceNode, p_destNode )
	{
		var oNodeDocument = this.getDocumentNodeByNode( p_sourceNode );
		p_destNode.parentNode.insertBefore( p_sourceNode.cloneNode( p_sourceNode ), p_destNode.nextSibling )
		p_sourceNode.parentNode.removeChild( p_sourceNode )


//		p_destNode.parentNode.replaceChild( p_destNode, p_sourceNode );
		
	}
	
	
	// --- Fonction qui renvoie la position d'un noeud par rapport à son parent ( de 0 à n ) ---
	this.getNodePos = function ( node )
	{
		var i = 0;
		while ( node )
		{
			node = node.previousSibling;
			i++;
		}
		return i - 1;
	}
	
	// --- Fonction qui renvoie le noeud se trouvant au chemin spécifié : chemin de type offest_document.offset.offset...offset.offest_noeud_cherche ---
	this.getNodeByPath = function ( path )
	{
		var node = document;
		var i = 0;
		var aOffsets = path.split( "." );
		
		for ( i = 1 ; i < aOffsets.length && node ; i++ )
		{
			node = node.childNodes.item( parseInt( aOffsets[ i ] ) );
		}
		return node;
	}
	
	
	this.getJSName = function ( )
	{
		return this._jsName;
	}
	
	
	this.getDocumentNodeByNode = function ( node )
	{
		var DocNode = node;
		
		while ( DocNode.parentNode )
		{
			DocNode = DocNode.parentNode;
			if ( DocNode.nodeType == NODE_DOCUMENT ) 
			{
				return DocNode;
			}
		}
		return document;	// par défaut on renvoie le document courrant ( objet HTML )
	}
	
	
	
	// --- GESTION DES EVENTS ---
	this.addActionListener = function ( pFunction )
	{
		this._actionListener = pFunction;
	}
	
	this._sendEvent = function ( eventCode, aMessages, NumMessages )
	{
		this._actionListener( eventCode, aMessages, NumMessages );
	}
	
	
	
	// --- Prototypes de fonction à étendre ---
	this._actionListener = function ( eventCode, aMessages, NumMessages )				{	}






	
	this.onDOMTreeSelect = function( oSourceItem, oEvent )		// oEvent.srcObject = this ( richtext )
	{
/*
		var oNode = oSourceItem.getLink( );
		var oRichEditor = oEvent.srcObject._oEditor;

		if ( oNode.nodeType != NODE_ELEMENT )
		{
			oNode = oNode.parentNode;
		}

		var oRange = new Document_Range( oRichEditor, true );
		oRange.selectionNode( oNode );
*/		
		/* --- On affiche le code HTML Colorisé --- */
/*
		var oDiv = getDiv( "DEBUG", false );
		writeToDiv( oDiv, DOM_outerColorHTML( oNode, 0, true ) )
*/
	}
	

	this.sendDOMStructureToTree = function ( oList, p_oNode )
	{
		var rootItem = createITEM( "item_root_normal" );
		rootItem.create( "BODY", "tree_bureau", "tree_bureau", this.onDOMTreeSelect, ITEM_LISTE, this );
		oList.clear( );
		oList.setRootItem( rootItem );
		rootItem.setCanBeDragged( false );

		var currentNode = p_oNode;

		rootItem.setLink( "", currentNode );
		currentNode = currentNode.firstChild;
		
		while( currentNode )
		{
			this.sendNodeToTree( currentNode, oList.getRootItem( ) );
			currentNode = currentNode.nextSibling;
		}
		oList.showAllChilds( );
		oList.paint( );
	}
	
	this.sendNodeToTree = function( oNode, oItem )
	{
        var tmpItem = createITEM( "item" );
		switch ( oNode.nodeType )
		{
			case NODE_ELEMENT :
		        tmpItem.create( oNode.nodeName, "tree_folder", "tree_folder_open", this.onDOMTreeSelect, ITEM_LISTE, this );
				break;
	
			case NODE_TEXT :
		        tmpItem.create( "Texte", "tree_bloc", "tree_bloc", this.onDOMTreeSelect, ITEM_LISTE, this );
				break;
	
			case NODE_CDATA_SECTION : 
				break;
	
			case NODE_ENTITY_REFERENCE :
				break;
	
			case NODE_COMMENT :
				break;
				
			case NODE_DOCUMENT_FRAGMENT :
				break;
		}
		tmpItem.setLink( "", oNode );
        oItem.appendItem( tmpItem );
		
		var currentNode = oNode.firstChild;
		
		while( currentNode )
		{
			this.sendNodeToTree( currentNode, tmpItem );
			currentNode = currentNode.nextSibling;
		}
	}
	





	
	
}


function DOM_GetChildNodeByTagName( p_oNode, p_sNodeName, p_optionalParamName, p_optionalParamValue )
{
	if ( typeof p_optionalParamName != "undefined" && typeof p_optionalParamValue != "undefined" )
	{
		p_optionalParamName = p_optionalParamName.toUpperCase( )
		p_optionalParamValue = p_optionalParamValue.toUpperCase( )
	}
	
	p_sNodeName = p_sNodeName.toUpperCase( );
	
	for ( var i = 0 ; i < p_oNode.childNodes.length ; i++ )
	{
		if ( p_oNode.childNodes[ i ].nodeName.toUpperCase( ) == p_sNodeName )
		{
			if ( typeof p_optionalParamName != "undefined" && typeof p_optionalParamValue != "undefined" )
			{
				if ( p_oNode.childNodes[ i ].getAttribute( p_optionalParamName, 0 ).toUpperCase( ) == p_optionalParamValue )
					return p_oNode.childNodes[ i ];
			}
			else
				return p_oNode.childNodes[ i ];
		}
	}
	return null;
}

function DOM_GetParentNodeByTagName( p_oNode, p_sNodeName, p_optionalParamName, p_optionalParamValue )
{
	if ( typeof p_optionalParamName != "undefined" && typeof p_optionalParamValue != "undefined" )
	{
		p_optionalParamName = p_optionalParamName.toUpperCase( )
		p_optionalParamValue = p_optionalParamValue.toUpperCase( )
	}
	
	p_sNodeName = p_sNodeName.toUpperCase( );
	
	
	if ( !p_oNode.parentNode ) 													return null;
	else if ( p_oNode.nodeName.toUpperCase( ) == p_sNodeName )	
	{
		if ( typeof p_optionalParamName != "undefined" && typeof p_optionalParamValue != "undefined" )	
		{
			if ( p_oNode.getAttribute( p_optionalParamName, 0 ).toUpperCase( ) == p_optionalParamValue )
				return p_oNode;
		}
		else
			return p_oNode.parentNode;
	}
	return DOM_GetParentNodeByTagName( p_oNode.parentNode, p_sNodeName, p_optionalParamName, p_optionalParamValue );
}



// --- Objet qui permet de recuperer et de gerer le chemin d'un noeud dans un document ---
function DOM_Path ( p_node )
{
	this._node		= p_node;
	this._nodePath	= Array( );			// tableau noeuds parents, de 0 ( pere ultime ) -> n ( node courant )
	this._numNodes	= 0;
	this._dom		= DOM;
	
	this.getNumNodes = function (  )	{		return this._numNodes;		}
	this.getRoot = function (  )		{		return this._nodePath[ 0 ];	}
	this.getLast = function (  )		{		return this._nodePath[ this._nodePath-1 ];	}
	this.getNodes = function ( )		{		return this._nodePath;		}
	
	// --- "Constructeur" ---
	if ( p_node )
	{
		var chaine		= "";
		var i = 0, pos	= 0;
		var node		= this._node;
		var node_path	= Array( );
		
		// On remonte dans l'arbre
		while ( node )
		{
			node_path[ pos++ ] = node;
			node = node.parentNode;
		}	

		// On inverse l'arbre de telle facon que nodPath[ 0 ] soit le pere ultime
		for ( i = 0 ; i < pos ; i++ )
		{
			this._nodePath[ i ] = node_path[ pos - i - 1 ]
			this._numNodes++;
		}
		
	}
	
	this.getParentByName = function( p_tagName )
	{
		for( var i = this._nodePath.length-1; i >= 0 ; i-- )
			if ( this._nodePath[ i ].nodeName.toUpperCase( ) == p_tagName.toUpperCase( ) )
				return this._nodePath[ i ];
	}
	
	this.getNextSiblingByName = function( p_tagName, p_oNode )
	{
		var oNode = p_oNode.nextSibling;
		while( oNode )
		{
			if ( oNode.nodeName == p_oNode.nodeName )	return oNode;
			oNode = oNode.nextSibling;
		}
	}
	this.getPreviousSiblingByName = function( p_tagName, p_oNode )
	{
		var oNode = p_oNode.previousSibling;
		while( oNode )
		{
			if ( oNode.nodeName == p_oNode.nodeName )	return oNode;
			oNode = oNode.previousSibling;
		}
	}
	
	
	// renvoie le chemin du noeud en String
	this.toString = function ( )
	{
		var i = 0;
		var chaine = "";
		
		for ( i = 0 ; i < this._numNodes ; i++ )
		{
			chaine += this._nodePath[ i ].nodeName;
			if ( i + 1 < this._numNodes ) chaine += " -> ";
		}
		
		return chaine;
	}
	

	// renvoie le chemin du noeud en HTML
	this.toHTML = function ( )
	{
		var i = 0;
		var chaine = "";
		var pos_path = "";
		
		for ( i = 0 ; i < this._numNodes ; i++ )
		{
			if ( pos_path != "" ) pos_path += ".";
			pos_path += this._dom.getNodePos( this._nodePath[ i ] )
			
			chaine += "<a href=\"javascript:" + this._dom.getJSName( ) + "._sendEvent(DOM_EVENT_SELECT_PATH,'" + pos_path + "',null);\">" + this._nodePath[ i ].nodeName + "</a>";
			if ( i + 1 < this._numNodes ) chaine += " - ";
		}
		
		return chaine;
	}
	
}


// Objet qui permet de parser toutes les tags enfants / parents facilement
function DOM_Parser( )
{
	this._oStartNode = null;
	this._oCurrentNode = null;
	
	this._bAllowNextSiblings = false;
	
	this._aArboNodes = Array( );
	this._iArboPos = 0;
	
	this._firstTime = false;
	
	this.init = function ( p_oNode, p_bAllowNextSiblings )			// p_bAllowNextSiblings, indique si le parser peut rechercher en dehors dans enfants de p_oNode, ces à dire les noeuds suivant, si false : que les childs
	{		
		this._oStartNode = p_oNode;
		this._oCurrentNode = null;		
		
		this._bAllowNextSiblings = p_bAllowNextSiblings;
		
		this._aArboNodes = null;
		this._aArboNodes = Array(  p_oNode );
		this._iArboPos = 0;
		this._firstTime = true;
	}
	
	this.getNextByName = function ( p_strName )
	{
		var oNode = this._oCurrentNode;
		p_strName = p_strName.toUpperCase( );
		
		while( ( oNode = this.getNext( ) )  )
		{
			if ( oNode.nodeName )
			{
				if ( oNode.nodeName.toUpperCase( ) == p_strName ) return oNode;
			}
		}
		return null;
	}
	
	this.getNext = function ( )
	{	
		if ( this._firstTime )
		{
			this._oCurrentNode = this._oStartNode;
			this._firstTime = false;
		}
		// Si enfant, on avance dans l'arbo ...	
		else if ( this._oCurrentNode.firstChild )
		{
			this._oCurrentNode = this._oCurrentNode.firstChild;
			this._iArboPos++;
		}
		else if ( this._oCurrentNode.nextSibling )
		{
			this._oCurrentNode = this._oCurrentNode.nextSibling
		}
		else
		{
			while( this._iArboPos-- > 0 )
			{
				if ( this._aArboNodes[ this._iArboPos ].nextSibling )
				{
//					if ( this._iArboPos == 0 && ! this._bAllowNextSiblings ) return false;
					this._oCurrentNode = this._aArboNodes[ this._iArboPos ].nextSibling;
					break;
				}
			}
			if ( this._iArboPos < 0 )
			{
				return null;
			}
		}
//		alert( " found " + this._oCurrentNode.nodeName + " value= '" + DOM_outerHTML( this._oCurrentNode.nodeName ) + "'" ) ;
		this._aArboNodes[ this._iArboPos ] = this._oCurrentNode;
		 return this._oCurrentNode;
		
	}

}



function DOM_innerHTML( node )
{
	if ( !node ) return "";
	var sHtml = "";
	for ( var i = 0 ; i < node.childNodes.length ; i++ )
	{
		sHtml += DOM_outerHTML( node.childNodes[ i ] );
	}
	return sHtml;
}


function DOM_outerHTML( node )
{
	var html = "";
	var i = 0;
	var nodeName = "";
		
	switch (node.nodeType)
	{
//		case NODE_DOCUMENT :
//			return;
			
		case NODE_ELEMENT :
		
			var cssStyle = "";
			
			nodeName = node.nodeName.toLowerCase( );
			
			// On regarde ( pour images ) si le node possède un style, et si oui un height, width, que l'on va virer de style pour le mettre en attribute
			/*
				Cette partie met à jours la chaine style="xxxxx" qui sera réafectée en part2
			*/
			if ( nodeName == "img" ) 
			{
				if ( ie4 && node.style )	cssStyle = DOM_outerIEStyleAttribute( node );
				else						cssStyle = node.getAttribute( "style" );	

				if ( cssStyle ) {
					cssStyle = cssStyle.toLowerCase( );
					var p1 = cssStyle.indexOf( "width:" );
					if ( p1 >= 0 ) {
						p2 = cssStyle.indexOf( "px;", p1 );
						node.setAttribute( "width", internalTrim( cssStyle.substring( p1+6, p2 ) ), 0 )
						cssStyle = cssStyle.substring( 0, p1 ) + cssStyle.substring( p2+3, cssStyle.length );
						if ( p2 >= 0 ) {
							p1 = cssStyle.indexOf( "height:" );
							p2 = cssStyle.indexOf( "px;", p2 );
							node.setAttribute( "height", internalTrim( cssStyle.substring( p1+7, p2 ) ), 0 )
							cssStyle = cssStyle.substring( 0, p1 ) + cssStyle.substring( p2+3, cssStyle.length );
						}
					}
				}
				// Si non renseigné, et bien on le renseigne ! Pwet
				else
				{
					node.setAttribute( "width", node.offsetWidth, 0 ) 
					node.setAttribute( "height", node.offsetHeight, 0 ) 
				}
			}
		
			html += "<" + nodeName;
			
			/* part2 --- Corrige BUG IE ( getAttribute("style") ne renvoie pas la valeur, mais un objet ) --- */
			if ( ie4 && node.style )
			{
				if ( cssStyle == "" ) cssStyle = DOM_outerIEStyleAttribute( node )
				if ( cssStyle ) html += " style=\"" + cssStyle + "\"";
			}
			else if ( !ie4 && cssStyle )
			{
				node.setAttribute( "style", cssStyle, 0 );
			}

			for ( i = 0 ; i < node.attributes.length ; i++ )
			{
				if( node.attributes.item( i ).nodeValue && ( node.attributes.item( i ).nodeValue.length > 0 || typeof node.attributes.item( i ).nodeValue == "number" ) )
				{
					var ParameterName = node.attributes.item(i).nodeName.toLowerCase( );
					/* On n'oublie pas d'exclure les params poubelle... YEHH */
					if( ParameterName != "_moz_resizing" &&
						ParameterName != "contenteditable" &&
						ParameterName != "loop" &&
						ParameterName != "start" ) {
						html += " " + ParameterName + "=\"" + node.attributes.item(i).nodeValue + "\"";
					}
				}
			}

			// On regarde s'il s'agit ou non d'un TAG vide (autoclosed) comme BR
			if( node.childNodes.length == 0 && DOM_Empty_Tags.indexOf( nodeName ) > 0 )
			{
				html += "/>";
			}
			else
			{
//				html += ">" + node.innerHTML + "</" + node.nodeName + ">";
				html += ">";
				var nextNode = node.firstChild;
				while ( nextNode )
				{
					html += DOM_outerHTML( nextNode );
					nextNode = nextNode.nextSibling
				}
				html += "</" + nodeName + ">";

			}
			break;

		case NODE_TEXT :
			html += node.nodeValue;
			break;

		case NODE_CDATA_SECTION : 
			html += "<![CDATA[" + node.nodeValue + "]]>";
			break;

		case NODE_ENTITY_REFERENCE :
			html += "&" + node.nodeName + ";";
			break;

		case NODE_COMMENT :
			html += "<!--" + node.nodeValue + "-->";
			break;
			
		case NODE_DOCUMENT_FRAGMENT :
			for ( i = 0 ; i < node.childNodes.length ; i++ )
			{
				html += DOM_outerHTML( node.childNodes[ i ] );
			}
			break;
	}
	
	return html;
}


/*
	L'attribute style d'un node sous IE n'est pas une simple value ... donc on doit la décortiquer !
*/
function DOM_outerIEStyleAttribute( p_oNode )
{
	return p_oNode.style.cssText
}

function DOM_outerVisibleText( node )
{
	return DOM_outerText( node, true );
}


function DOM_outerText( node, p_bOptionalOnlyVisibleNodes )
{
	if ( !node ) return "";
	var html = "";
	var i = 0;
	
	if ( node.nodeType == NODE_ELEMENT && p_bOptionalOnlyVisibleNodes != "undefined" && 
		p_bOptionalOnlyVisibleNodes && node.style.display == "none" ) 
		return "";
	
	switch (node.nodeType)
	{
		case NODE_CDATA_SECTION :
			html += internalTrim( node.nodeValue ); 
			break;
		case NODE_ELEMENT :
			var nextNode = node.firstChild;
			while ( nextNode )
			{
				html += DOM_outerText( nextNode, p_bOptionalOnlyVisibleNodes );
				nextNode = nextNode.nextSibling;
			}
			break;

		case NODE_TEXT :
			html += internalTrim( node.nodeValue );
			break;

		case NODE_ENTITY_REFERENCE :
			html += "&" + node.nodeName + ";";
			break;
			
		case NODE_DOCUMENT_FRAGMENT :
			for ( i = 0 ; i < node.childNodes.length ; i++ )
			{
				html += DOM_outerText( node.childNodes[ i ], p_bOptionalOnlyVisibleNodes );
			}
			break;
		case NODE_COMMENT :
			if ( node.nodeValue.indexOf( "[CDATA[" ) == 0 )
				html += node.nodeValue.replace( "[CDATA[", "" ).replace( "]]", "" );
			else
				html += node.nodeValue;
			break;
		default:
			alert( "DOM_outerText noeud non traité : nodeType = " + node.nodeType )
			break;
	}
	return html;
}



/* --- Version dev en couleur ! --- */
function DOM_outerColorHTML( node, colonne )
{
	/* Pour l'instant desactivée car il faudrait se baser sur le moteur de rendu du DOM_outerHTML, et ajouter la couleur dessus, et ne pas dupliquer le code comme c'etait le cas !!! */
	return internalReplace( DOM_outerHTML( node ), "<", "&lt;" );
	
/*
	var html = "";
	var i = 0;

	var endOfTag = "";
	var mustStartLine = false;
	var mustEndLine = false;
		
	var currentNodeName = node.nodeName.toLowerCase( );
	
	switch (node.nodeType)
	{
	
		case NODE_ELEMENT :
		
			switch( currentNodeName )
			{
				case "p" :
				case "body" :
					mustStartLine = true;
					mustEndLine = true;
					colonne++;
					break;
					
				case "tbody" :
				case "table" :
					mustStartLine = true;
					mustEndLine = true;
					break;

				case "br" :
					mustEndLine = true;
					break;

				case "tr" :
					mustStartLine = true;
					mustEndLine = true;
					colonne++;
					break;

				case "td" :
					mustStartLine = true;
					colonne++;
					break;
				default:
			}

			if ( mustStartLine )	for ( i = 0 ; i < colonne - 1 ; i++ ) html += "&nbsp;&nbsp;&nbsp;&nbsp;"
		
			html += "<span class='HTMLTag_" + node.nodeName + "'>&lt;" + currentNodeName;
			// --- Corrige BUG IE ( getAttribute("style") ne renvoie pas la valeur, mais un objet ) ---
			if ( ie4 && node.style )
			{
				var cssForStyle = DOM_outerIEStyleAttribute( node )
				if ( cssForStyle ) html += " style=\"" + cssForStyle + "\"";
				html += " style=</span><span class='HTMLTag_params'>\"" + cssForStyle + "\"</span><span class='HTMLTag_" + node.nodeName + "'>";
			}

			for ( i = 0 ; i < node.attributes.length ; i++ )
			{
				if( node.attributes.item( i ).nodeValue != null && node.attributes.item( i ).nodeValue.length > 0 )
				{
					html += " ";
					html += node.attributes.item(i).nodeName;
					html += "=</span><span class='HTMLTag_params'>\"";
					html += node.attributes.item(i).nodeValue;
					html += "\"</span><span class='HTMLTag_" + node.nodeName + "'>";
				}
			}

			isOnNewLine = false;
			
			// On regarde s'il s'agit ou non d'un TAG vide (autoclosed) comme BR
			if( node.childNodes.length == 0 && DOM_Empty_Tags.indexOf( node.nodeName ) > 0 )
			{
				html += "/&gt;</span>";
				if ( mustEndLine ) 
				{
					html += "<br>";
					isOnNewLine = true;
				}
			}
			else
			{
				html += "&gt;</span>" 
				if ( mustEndLine ) 
				{
					html += "<br>";
					isOnNewLine = true;
				}

				html += "<span class='text'>"
				var nextNode = node.firstChild;
				while ( nextNode )
				{
					html += DOM_outerColorHTML( nextNode, colonne );
					nextNode = nextNode.nextSibling
				}
				html += "</span>";

				if ( mustStartLine )	for ( i = 0 ; i < colonne - 1 ; i++ ) html += "&nbsp;&nbsp;&nbsp;&nbsp;"
				html += "<span class='HTMLTag_" + node.nodeName + "'>&lt;/" + currentNodeName + "&gt;</span>";
				
				if ( mustEndLine || mustStartLine )
					html += "<br>"
				
			}

			

			break;

		case NODE_TEXT :
			html += node.nodeValue;
			break;

		case NODE_CDATA_SECTION : 
			html += "<![CDATA[" + node.nodeValue + "]]>";
			break;

		case NODE_ENTITY_REFERENCE :
			html += "&" + node.nodeName + ";";
			break;

		case NODE_COMMENT :
			html += "<!--" + node.nodeValue + "-->";
			break;
			
		case NODE_DOCUMENT_FRAGMENT :
			for ( i = 0 ; i < node.childNodes.length ; i++ )
			{
				html += DOM_outerColorHTML( node.childNodes[ i ], colonne );
			}
			break;
	}
//	alert(html);


	
	return html;
*/
}







// permet d'effacer les parametres vide d'un noeud, sert specialement à nettoyer le code qu'IE genere avec sa fonction "insertAdjacentHTML()" ?!? Peut etre lors d'un insert node ?!?
function DOM_cleanUpEmptyParams( p_oNode, p_bRecursive )
{
	var currentNode;
	var i = 0;
	var aListParamToDel = Array( );
	var oAttributes= p_oNode.attributes;

	if ( p_oNode.nodeName == "BODY" )
	{
		alert( p_oNode.nodeName + ": " + p_oNode.getAttribute( "class" ) );
	}
	if ( oAttributes )
	{
		// on recupere les parametres vides
		for ( i = 0 ; i < oAttributes.length ; i++ )
		{
			if ( oAttributes[ i ].nodeValue == "" )
			{
				aListParamToDel[ aListParamToDel.length ] = oAttributes.item( i ).name;
			}
		}
				
		// puis on nettoie le noeud...
		if ( aListParamToDel.length > 0 )
		{
			for ( i = 0 ; i < aListParamToDel.length ; i++ )
			{
				p_oNode.removeAttribute( aListParamToDel[ i ], 0 );
			}
		}
	}
	
	// ...et ses enfants ?!?
	currentNode = p_oNode.firstChild;
	if ( currentNode && p_bRecursive )
	{
		while( currentNode )
		{
			DOM_cleanUpEmptyParams( currentNode, true );
			currentNode = currentNode.nextSibling;
		}
	}
}


/*
	Version optimisée de htmlToNodes, au lieu de parser nous meme on ecrit le HTML puis on recupere le noeud
*/
function DOM_htmlToNodesVBetaNaze( p_xhtml, p_bInutileMaintenant )
{
	var id = 0;
	var pos1, pos2;
	pos1 = p_xhtml.indexOf( "id=" );
	pos1+= 4;
	pos2 = p_xhtml.indexOf( "\"", pos1 );
	id = p_xhtml.substring( pos1, pos2 );
	document.write( p_xhtml );
	
	var oNode = document.getElementById( id );

	if ( !oNode )
	{
		alert( "unable to create template id : " + id );
		alert( "HTML = " + oNode );
	}
//	else
//		oNode.style.display = "none";

	document.write( DOM_outerHTML( oNode.cloneNode( true ) ) );

	return oNode;

}

/*
	Ancienne version mais qui fait bien ce qu'elle dit, pas comme l'autre !!!;)
*/
function DOM_htmlToNodes( p_xhtml, p_bReturnFirstNodeOnly, p_oOptionalDocument )
{
	var oParser = new XML_Parser( );
	var oRootDoc = oParser.parseXML( p_xhtml );
	var oNodes = new Array( );

	if ( oRootDoc )
	{
		for( var i = 0 ; i < oRootDoc.childNodes.length ; i++ )
		{
			oNodes[ i ] = XML_getNodes( oRootDoc.childNodes.item( i ), null, p_oOptionalDocument );
		}
	}
	if ( p_bReturnFirstNodeOnly ) return oNodes[ 0 ];
	return oNodes;
}

function XML_getNodes( p_oXmlNode, p_oRefNode, p_oOptionalDocument )
{
	var i = 0;
	var oDocument = document;

	// Si jamais on spŽcifie un document autre que le document courant pour la crŽation des noeus ( exemple : pour inserer dans une iframe ... )
	if ( typeof p_oOptionalDocument != "undefined" && p_oOptionalDocument ) oDocument = p_oOptionalDocument;
	
	if ( !p_oXmlNode ) return null;
	var oNode = null;
	
	switch( p_oXmlNode.nodeType )
	{
		case XML_Node.ELEMENT_NODE :
			oNode = oDocument.createElement( p_oXmlNode.nodeName );
			if ( p_oRefNode ) p_oRefNode.appendChild( oNode );
			break;
		case XML_Node.ATTRIBUTE_NODE :
		
			// patch pour IE dans le cas d'un colspan ou d'une class
			if ( p_oXmlNode.nodeName == "class" && ie4 )
				p_oRefNode.className = p_oXmlNode.nodeValue;
			else if ( p_oXmlNode.nodeName == "id" )
				p_oRefNode.setAttribute( "id", p_oXmlNode.nodeValue, 0 );		
			else
			if ( p_oXmlNode.nodeName == "colspan" && ie4 )
				p_oRefNode.setAttribute( "colSpan", p_oXmlNode.nodeValue, 0 );
			else if ( p_oXmlNode.nodeName != "" )
				try
				{
					p_oRefNode.setAttribute( p_oXmlNode.nodeName, p_oXmlNode.nodeValue, 0 );
				}
				catch( e )
				{
					alert( "erreur sur la value :" + p_oXmlNode.nodeName );
				}
			break;

		case XML_Node.CDATA_SECTION_NODE :
//			oNode = oDocument.createCDATASection( p_oXmlNode.nodeValue );  [ALEX] SEMBLERAIT POSER PROBLEME DANS FIREFOX
			oNode = oDocument.createTextNode( p_oXmlNode.nodeValue );
			if ( p_oRefNode ) p_oRefNode.appendChild( oNode );
			break;

			
		case XML_Node.TEXT_NODE :
			oNode = oDocument.createTextNode( p_oXmlNode.nodeValue );
			if ( p_oRefNode ) p_oRefNode.appendChild( oNode );
			break;
	}

	if ( p_oXmlNode.attributes )
	{
		for( i = 0 ; i < p_oXmlNode.attributes.length ; i++ )
			XML_getNodes( p_oXmlNode.attributes.item( i ), oNode, oDocument );
	}	
	for( i = 0 ; i < p_oXmlNode.childNodes.length ; i++ )
		XML_getNodes( p_oXmlNode.childNodes.item( i ), oNode, oDocument );
	
	return oNode;
}

function DOM_findNodeById( p_baseNode, p_id )
{
	var oNode = p_baseNode;
	while ( oNode )
	{
		if ( oNode.hasChildNodes( ) )
		{
			var returnNode = DOM_findNodeById( oNode.firstChild, p_id );
			if ( returnNode ) return returnNode;
		}
		if ( oNode.nodeType == NODE_ELEMENT && oNode.getAttribute( "id" ) == p_id ) return oNode;
		oNode = oNode.nextSibling;
	}
	return null;
}


function DOM_removeAllChilds( p_oNode )
{
	if ( ! p_oNode ) return;
	var num_nodes = p_oNode.childNodes.length;
	for ( var i = 0 ; i < num_nodes ; i++ )
	{
		p_oNode.removeChild( p_oNode.childNodes[ 0 ] )
	}

}

function DOM_showNode( p_oNode )
{
	if (!p_oNode ) return;
	var tagName = p_oNode.nodeName.toUpperCase( );
	/* Pour les tr/td/table, un cas special s'offre à nous, chouette ... ;) */
	if ( ( tagName == "TR" )  && !ie4 )
		p_oNode.style.display = "table-row";
	else if ( ( tagName == "TD" )  && !ie4 )
		p_oNode.style.display = "table-cell";
	else if ( tagName == "A" || tagName == "IMG" || tagName == "B" || tagName == "U" || tagName == "I" || tagName == "SPAN" )
		p_oNode.style.display = "inline";
	else				
		p_oNode.style.display = "block";
}


function DOM_hideNode( p_oNode )
{
	if (!p_oNode ) return 
	p_oNode.style.display = "none";
}

function DOM_setNodeVisible( p_oNode )
{
	p_oNode.style.visibility = "visible";
}

function DOM_setNodeInvisible( p_oNode )
{
	p_oNode.style.visibility = "hidden";
}


function DOM_getNodeWidth ( p_oNode )
{
	var width = 0;
	if ( p_oNode.style.width && p_oNode.offsetWidth <= 0 ) width = p_oNode.style.width.replace( "px", "" );
//	if ( !ie4 )	return parseInt( p_oNode.offsetWidth - 2 );
	else width = parseInt( p_oNode.offsetWidth - 2 );
	
	if ( width<0 ) width = 0;
	return width;
}

function DOM_getNodeHeight ( p_oNode )
{
	var height = 0;
	if ( p_oNode.style.height && p_oNode.offsetHeight <= 0 ) height = p_oNode.style.height.replace( "px", "" );
//	if ( !ie4 )	return parseInt( p_oNode.offsetHeight - 2 );
	else height = parseInt( p_oNode.offsetHeight - 2 );

	if ( height<0 ) height = 0;
	return height;
}

function DOM_setNodeWidth ( p_oNode, w )
{
	if ( ! p_oNode ) return;
	
	var iPaddingLeft = parseInt( DOM_getStyle( p_oNode, "padding-left" ).replace("px", "") );
	var iPaddingRight = parseInt( DOM_getStyle( p_oNode, "padding-right" ).replace("px", "") );
	var iBorderLeft = parseInt( p_oNode.style.borderLeftWidth )
	var iBorderRight = parseInt( p_oNode.style.borderRightWidth )
	var totalPaddingHorizontal = 0;
	if ( !isNaN( iPaddingLeft ) ) totalPaddingHorizontal += iPaddingLeft;
	if ( !isNaN( iPaddingRight ) ) totalPaddingHorizontal += iPaddingRight;
	if ( !isNaN( iBorderLeft ) ) totalPaddingHorizontal += iBorderLeft;
	if ( !isNaN( iBorderRight ) ) totalPaddingHorizontal += iBorderRight;
	p_oNode.style.width = (w - totalPaddingHorizontal  )  + "px";
}

function DOM_setNodeHeight( p_oNode, h )
{
	if ( ! p_oNode ) return;
	var iPaddingTop = parseInt( DOM_getStyle( p_oNode, "padding-top" ).replace("px", "") );
	var iPaddingBottom = parseInt( DOM_getStyle( p_oNode, "padding-bottom" ).replace("px", "") );
	var iBorderTop = parseInt( p_oNode.style.borderTopWidth )
	var iBorderBottom = parseInt( p_oNode.style.borderBottomWidth )
	var totalPaddingVertical = 0;
	if ( !isNaN( iPaddingTop ) ) totalPaddingVertical += iPaddingTop;
	if ( !isNaN( iPaddingBottom ) ) totalPaddingVertical += iPaddingBottom;
	if ( !isNaN( iBorderTop ) ) totalPaddingVertical += iBorderTop;
	if ( !isNaN( iBorderBottom ) ) totalPaddingVertical += iBorderBottom;
	p_oNode.style.height = (h - totalPaddingVertical)  + "px";
}


function DOM_getNodePosX( p_oNode )
{
	var curleft = 0;
	if ( p_oNode.offsetParent )		{
		while ( p_oNode.offsetParent )		{		curleft += p_oNode.offsetLeft;	p_oNode = p_oNode.offsetParent;	}
	}
	else if ( p_oNode.x )	{ curleft += p_oNode.x;	}
	
	return curleft;
}


function DOM_setFloat( p_oNode, sFloatValue )
{
	if ( ie4 )	p_oNode.style.styleFloat = sFloatValue;
	else		p_oNode.style.cssFloat = sFloatValue;
}

function DOM_setNodePosX( p_oNode, p_iValue )
{
	p_oNode.style.left = p_iValue + "px";
}

function DOM_setNodePosY( p_oNode, p_iValue )
{
	p_oNode.style.top = p_iValue + "px";
}

function DOM_moveNodeTo( p_oNode, p_x, p_y )
{
	DOM_setNodePosX( p_oNode, p_x );
	DOM_setNodePosY( p_oNode, p_y );
}

function DOM_getFloat( p_oNode, sFloatValue )
{
	if ( ie4 )	return p_oNode.style.styleFloat;
	else		return p_oNode.style.cssFloat;
}

function DOM_getNodePosY( p_oNode )
{
	var curtop = 0;
	if ( p_oNode.offsetParent )		{
		while (p_oNode.offsetParent)		{	curtop += p_oNode.offsetTop;p_oNode = p_oNode.offsetParent;	}
	}
	else if ( p_oNode.y )	{	curtop += p_oNode.y;	}

	return curtop;
}


function DOM_getStyle( p_oNode, p_styleProp )
{
	var sStyleValue = "";
	if ( p_oNode.currentStyle )
		sStyleValue = p_oNode.currentStyle[ p_styleProp ];
	else if ( window.getComputedStyle )
		sStyleValue = document.defaultView.getComputedStyle( p_oNode, null ).getPropertyValue( p_styleProp );
	
	if ( typeof sStyleValue == "undefined" ) sStyleValue = ""
	return sStyleValue;
}

function DOM_hideOrShow( p_oNode )
{
	if ( p_oNode.style.display == "none" )	DOM_showNode( p_oNode )
	else									DOM_hideNode( p_oNode )
}


function DOM_execJavascript( p_oNode )
{
	var aJScripts = p_oNode.getElementsByTagName( "SCRIPT" );
	for ( var i = 0 ; i < aJScripts.length ; i++ )
	{
		eval( aJScripts[ i ].innerHTML );
	}

	return aJScripts.length;	// On retourne le nombre de scripts HTML executés
}

function DOM_getParentWindow( p_oNode )
{
	// On test la précense d'une iframe
	if ( ismozilla )
		return p_oNode.defaultView;
		
	return p_oNode.parentWindow;
}




var DOM = new DOM_Manager( "DOM" );




