//------------------------------------------------------------------------------
/** @author Бреславский А.В. (Joonte Ltd.) */
//------------------------------------------------------------------------------
var Tag = function($Name){
  //----------------------------------------------------------------------------
  // Имя
  this.Name = ($Name?$Name:'');
  // Атрибуты
  this.Attribs = {};
  // Дети
  this.Childs = [];
  // Текстовое содержимое
  this.Text = '';
};
//------------------------------------------------------------------------------
Tag.prototype.AddAttrib = function($Name,$Value){
  //----------------------------------------------------------------------------
  this.Attribs[$Name] = $Value;
};
//------------------------------------------------------------------------------
Tag.prototype.AddChild = function($Child){
  //----------------------------------------------------------------------------
  this.Childs.push($Child);
};
//------------------------------------------------------------------------------
Tag.prototype.ToObject = function($Lists){
  //----------------------------------------------------------------------------
  if(!$Lists)
    $Lists = ['ListElement'];
  //----------------------------------------------------------------------------
  var $Childs = this.Childs;
  //----------------------------------------------------------------------------
  if($Childs.length > 0){
    //--------------------------------------------------------------------------
    var $j = 1;
    //--------------------------------------------------------------------------
    var $Result = {};
    //--------------------------------------------------------------------------
    for(var $i in $Childs){
      //------------------------------------------------------------------------
      var $Child = $Childs[$i];
      //------------------------------------------------------------------------
      if(typeof($Child) != 'object')
        continue;
      //------------------------------------------------------------------------
      $Name = $Child.Name;
      //------------------------------------------------------------------------
      for(var $i=0;$i<$Lists.length;$i++){
        //----------------------------------------------------------------------
        if($Name == $Lists[$i]){
          //--------------------------------------------------------------------
          $Name = $Name+($j++);
          //--------------------------------------------------------------------
          break;
        }
      }
      //------------------------------------------------------------------------
      $Result[$Name != 'UniqID'?$Name:UniqID('ID')] = $Child.ToObject($Lists);
    }
  }else{
    //--------------------------------------------------------------------------
    if(this.Attribs.type != undefined){
      //------------------------------------------------------------------------
      var $Type = this.Attribs.type;
      //------------------------------------------------------------------------
      switch($Type){
        case 'array':
          $Result = {};
        break;
        default:
         //---------------------------------------------------------------------
         alert(SPrintF('[Tag.ToObject]: неверный тип (%s)',$Type));
         //---------------------------------------------------------------------
         return false;
      }
    }else
      $Result = this.Text;
  }
  //----------------------------------------------------------------------------
  return $Result;
};
//------------------------------------------------------------------------------
Tag.prototype.ToXMLString = function(){
  //----------------------------------------------------------------------------
  var $Name = this.Name;
  //----------------------------------------------------------------------------
  var $Result = SPrintF('<%s',$Name);
  //----------------------------------------------------------------------------
  var $Attribs = this.Attribs;
  //----------------------------------------------------------------------------
  for(var $AttribID in $Attribs){
    //--------------------------------------------------------------------------
    var $Attrib = String($Attribs[$AttribID]);
    //--------------------------------------------------------------------------
    $Result += SPrintF(' %s="%s"',String($AttribID),$Attrib.XMLEscape());
  }
  //----------------------------------------------------------------------------
  var $Childs = this.Childs;
  //----------------------------------------------------------------------------
  if($Childs.length > 0){
    //--------------------------------------------------------------------------
    $Result += '>\n';
    //--------------------------------------------------------------------------
    for(var $ChildID in $Childs){
      //------------------------------------------------------------------------
      if(typeof($Childs[$ChildID]) != 'object')
        continue;
      //------------------------------------------------------------------------
      $Result += $Childs[$ChildID].ToXMLString();
    }
  }else{
    //--------------------------------------------------------------------------
    var $Text = ($Attribs['force-escape']?this.Text:this.Text.XMLEscape());
    //--------------------------------------------------------------------------
    var $IsShort = (($Text.length < 1) && !['TEXTAREA','BUTTON','TITLE','SCRIPT'].IsExists($Name));
    //--------------------------------------------------------------------------
    if(!$IsShort)
      $Result += SPrintF('>%s',$Text);
    else
      return SPrintF('%s />\n',$Result);
  }
  //----------------------------------------------------------------------------
  return SPrintF('%s</%s>\n',$Result,$Name);
}
//------------------------------------------------------------------------------
var Attrib = function(){
  //----------------------------------------------------------------------------
  // Имя
  this.Name = '';
  // Значение
  this.Value = '';
};
//------------------------------------------------------------------------------
function TagFromObject($Object){
  //----------------------------------------------------------------------------
  var $Result = new Tag($Object.Name);
  //----------------------------------------------------------------------------
  for(var i in $Object.Attribs)
    $Result.AddAttrib(i,String($Object.Attribs[i]));
  //----------------------------------------------------------------------------
  $Result.Text = $Object.Text;
  //----------------------------------------------------------------------------
  for(var i=0;i<$Object.Childs.length;i++)
    $Result.AddChild(TagFromObject($Object.Childs[i]));
  //----------------------------------------------------------------------------
  return $Result;
}
//------------------------------------------------------------------------------
var DOM = function($Object){
  //----------------------------------------------------------------------------
  // Хранилище дерева объектов
  this.Object = null;
  // Массив ссылок
  this.Links = {};
  //----------------------------------------------------------------------------
  if($Object){
    //--------------------------------------------------------------------------
    this.Object = TagFromObject($Object);
    //--------------------------------------------------------------------------
    this.Linking(); // Линковка объекта
  }
};
//------------------------------------------------------------------------------
DOM.prototype.Linking = function($Object){
  //----------------------------------------------------------------------------
  if(!$Object){
    //--------------------------------------------------------------------------
    var $Object = this.Object;
    //--------------------------------------------------------------------------
    this.Links = {};
  }
  //----------------------------------------------------------------------------
  var $Attribs = $Object.Attribs;
  //----------------------------------------------------------------------------
  if($Attribs.id)
    this.Links[$Attribs.id] = $Object;
  //----------------------------------------------------------------------------
  var $Childs = $Object.Childs;
  //----------------------------------------------------------------------------
  if($Childs.length > 0){
    //--------------------------------------------------------------------------
    for(var $ChildID in $Childs){
      //------------------------------------------------------------------------
      var $Child = $Childs[$ChildID];
      //------------------------------------------------------------------------
      if(typeof($Child) != 'object')
        continue;
      //------------------------------------------------------------------------
      this.Linking($Child);
    }
  }
}
//------------------------------------------------------------------------------