function domTools() {}

domTools.TextNode = 3;
domTools.CDataSection = 4;

domTools.createOption = function( text ) {
  var value = ( arguments.length > 1 )
    ? arguments[ 1 ] : null;

  var oOption = document.createElement( 'option' );
  if ( !isNull( value ) )
    oOption.setAttribute( 'value', value );
  oOption.appendChild( document.createTextNode( text ) );
  return oOption;
}
domTools.removeChildren = function( oObject ) {
  if ( oObject.childNodes.length == 0 ) return ;
  while( oObject.childNodes.length > 0 )
    oObject.removeChild( oObject.firstChild );
}
domTools.getText = function( parentNode ) {
  var rv = '';
  var nodeType;
  for ( var i=0; i<parentNode.childNodes.length; i++ ) {
    nodeType = parentNode.childNodes[ i ].nodeType;
    if ( nodeType == domTools.TextNode || nodeType == domTools.CDataSection )
      rv += parentNode.childNodes[ i ].nodeValue.trim();
  }
  if ( 0 == rv.length ) rv = null;
  return rv;
}
domTools.removeClassName = function( node, className ) {
  var cName = node.className.split( className );
  var newName = '';
  for( var i=0; i<cName.length; i++ )
    if ( cName[ i ].length > 0 )
      newName += cName[ i ];
  node.className = newName;
}
domTools.addClassName = function( node, className ) {
  if ( node.className.indexOf( className ) == -1 )
    node.className += ' ' + className;
}
domTools.parentNode = function( childNode, parentTagName ) {
  var rv = childNode.parentNode;
  while( rv.tagName.toLowerCase() != parentTagName.toLowerCase() )
    rv = rv.parentNode;
  return rv;
}
domTools.getChildNodes = function( parentNode ) {
  var rv = new Array();
  for ( var i=0; i<parentNode.childNodes.length; i++ ) // ( var i in parentNode.childNodes )
    if ( typeof( parentNode.childNodes[ i ].tagName ) != 'undefined' && typeof( parentNode.childNodes[ i ].nodeType ) != 'undefined' )
      rv[ rv.length ] = parentNode.childNodes[ i ];
  if ( 0 == rv.length ) rv = null;
  return rv;
}
domTools.filterNodesByTagName = function( nodeList, expectedTagName ) {
  var rv = new Array();
  for ( var i=0; i<nodeList.length; i++ )
    if ( nodeList[ i ].tagName.toLowerCase() == expectedTagName.toLowerCase() )
      rv[ rv.length ] = nodeList[ i ];
  if ( 0 == rv.length ) rv = null;
  return rv;
}
domTools.createElement = function( tagName, attributes ) {
  var node = document.createElement( tagName );
  if ( !isNull( attributes ) ) {
    var oRegExp = new RegExp( '( [a-z0-9_-]+)="(.[^"]+)"', 'gi' );
    var computedCode = '';
    var matches = null;
    var attrName = attrValue = null;
    while( computedCode.length != attributes.length ) {
      matches = oRegExp.exec( attributes );
      if ( !isNull( matches ) ) {
        attrName = matches[ 1 ];
        attrValue = matches[ 2 ];
        node.setAttribute( attrName.trim(), attrValue );
        computedCode += matches[ 0 ];
      }
    }
  }
  return node;
}
domTools.createElements = function( targetNode, htmlCode ) {
  var openPos = closePos = -1;
  var leftText = null;
  var toComputeCode = htmlCode;
  var tagDeclaration = null;
  var selfCloseableTags = ',br,hr';
  var oRegExpTag = new RegExp( '([/a-z0-9:]+)(.[^><]*)?', 'i' );
  var matches = null;

  var tagName = attrs = null;

  var depth = 0;
  var parentNodes = new Array();
  parentNodes.push( targetNode );

  while( toComputeCode.length > 0 ) {
    openPos = toComputeCode.indexOf( '<' );
    closePos = toComputeCode.indexOf( '>' );
    if ( openPos != -1 ) {
      leftText = toComputeCode.substr( 0, openPos );
      if ( !isNull( leftText ) && leftText.length > 0 )
        parentNodes[ depth ].appendChild( document.createTextNode( leftText ) );
// alert( 'leftText: ' + leftText + ' - depth: ' + depth  );
      tagDeclaration = toComputeCode.substring( openPos + 1, closePos );
      if ( !isNull( tagDeclaration ) && tagDeclaration.length > 0 ) {
        matches = oRegExpTag.exec( tagDeclaration );
        if ( !isNull( matches ) ) {
          tagName = ( !isNull( matches[ 1 ] ) )
            ? matches[ 1 ] : null;
          attrs = ( !isNull( matches[ 2 ] ) )
            ? matches[ 2 ] : null;
          if ( !isNull( attrs ) ) {
            if ( attrs.substr( -2 ).trim() == '/' )
              attrs = attrs.substr( 0, attrs.length - 2 ).trim();
          }

          if ( !isNull( tagName ) ) {
            if ( tagName.indexOf( '/' ) == 0 ) { // c'est une balise fermante
//              tagName = tagName.substr( 1 );
              depth--;
            } else {
              var selfClosable = selfCloseableTags.indexOf( ',' + tagName ) != -1;
              var node = domTools.createElement( tagName, attrs );
              parentNodes[ depth ].appendChild( node );

              if ( !selfClosable ) { // c'est une balise qui devra être fermée
                depth++;
                parentNodes[ depth ] = node;
              }
            }
          }
// alert( tagDeclaration + '\n tagName: {' + tagName + '} attrs: {' + attrs + '}' );
        }
      }

      toComputeCode = toComputeCode.substr( closePos + 1 );
    } else {
      if ( !isNull( toComputeCode ) )
        parentNodes[ depth ].appendChild( document.createTextNode( toComputeCode ) );
      toComputeCode = '';
    }
  }
}