/* Por Aurélio A. Heckert - http://aurium.cjb.net - aurium@gmail.com
** Esse script apresenta os atributos e metodos de objetos JavaScript
** Direitos Autorais Reservados (C) 2004 Aurélio Adnauer Heckert
**
** Esse Script é Software Livre, licenciado pela GPL v2 ou superior
** http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
**
** Este programa é software livre; você pode redistribuí-lo e/ou modificá-lo
** sob os termos da Licença Pública Geral GNU conforme publicada pela Free
** Software Foundation; tanto a versão 2 da Licença, como (a seu critério)
** qualquer versão posterior.
**
** Este programa é distribuído na expectativa de que seja útil, porém, SEM
** NENHUMA GARANTIA; nem mesmo a garantia implícita de COMERCIABILIDADE OU
** ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. Consulte a Licença Pública Geral
** do GNU para mais detalhes.
**
** Você deve ter recebido uma cópia da Licença Pública Geral do GNU junto
** com este programa; se não, escreva para a Free Software Foundation, Inc.,
** no endereço 59 Temple Street, Suite 330, Boston, MA 02111-1307 USA.
** Caso você esteja vendo esse script através de uma página web, use os
** links já citados para ler a licença.
*/

window.debugObject = {

"getConstructor" : function M_GetConstructor(obj){
  if(typeof(obj.constructor)!="undefined"){
    objConstr = obj.constructor.toString();
    objConstr = objConstr.replace(/\n/g, "");
    objConstr = objConstr.replace(/\r/g, "");
    objConstr = objConstr.replace(/function ([^( ]*)\(.*/, "$1");
    objConstr = objConstr.replace(/.*\[([A-Za-z0-9_]*)\].*/, "$1");
  } else {
    objConstr = "[Indefinido]";
    if(obj === window){ objConstr = "Window"; }
    if(obj === document){ objConstr = "Document"; }
    //if(obj === ){ objConstr = ""; }
  }
  return objConstr;
},


"myTypeOf" : function M_MyTypeOf(variable){
  switch( typeof(variable) ){
    case "object":
      if(variable.constructor == Array){
        return 'array';
      } else {
        return 'object';
      }
      break;
    case "function":
      return 'function';
      break;
    default:
      return 'primitive';
  }
},


"view" : function M_View(obj){
  if( typeof(obj) == 'string' ){
    // "obj" é o id de um objeto, então precisamos pegar a referência:
    obj = document.getElementById(obj);
  }
  // Opções da Janela:
  var wOpts = "width=500,height=400";
  wOpts += ",directories=no,location=no,menubar=no,personalbar=no,toolbar=no";
  wOpts += ",resizable=yes,scrollbars=yes,titlebar=yes,status=yes";
  // Abrindo nova janela:
  var wDebug = window.open("", "_blank", wOpts);
  // A função "echo" escreverá na nova janela.
  function echo(Str){ wDebug.document.write(Str); }
  
  wDebug.document.open();
  // Escreve o cabeçalho:
  this.writeHeader(wDebug.document);
  
  var objConstr = this.getConstructor(obj);
  var arrayNum = 0;
  var funcNum = 0;
  var errorNum = 0;
  
  echo('<body>\n');
  echo('<h1>Objeto do Construtor "'+objConstr+'"</h1>\n');
  echo('<table>');
  for(var item in obj){
    echo('<tr title="'+item+'">\n');
    echo('<td>'+ item.substr(0,25) + ((item.length>25)?'...':'') +'</td>\n');
    /* * para não parar nos bugs dos navegadores: * * * * */
    var itCanBeListed = true;
    var listingError = { "name":"", "mess":"" };
    try{
      obj[item];
    }
    catch(error){
      itCanBeListed = false;
      if(typeof(error.message)!="undefined"){
        // Mozilla:
        listingError.name = error.name;
        listingError.mess = error.message;
      } else {
        // IE:
        listingError.name = "ERRO "+ error.number;
        listingError.mess = error.description;
      }
      listingError.mess = listingError.mess.replace(/&/g,"&amp;");
      listingError.mess = listingError.mess.replace(/</g,"&lt;");
    }
    /* * agora está tudo bem. * * * * * * * * * * * * * * */
    if( itCanBeListed ){
      if( obj[item] == null ){
        echo('<td class="Value"><span class="null">NULL</span></td>\n');
      }
      else{
        switch( this.myTypeOf(obj[item]) ){
          case "object":
            echo('<td class="ObjName"><a href="javascript:view(\''+item+'\');">');
            echo('Objeto de '+this.getConstructor(obj[item])+'</a></td>\n');
            break;
          case "array":
            arrayNum++;
            echo('<td class="ArrayName"><a href="javascript:openclose(\'array'+arrayNum+'\');">');
            echo('Array</a></td>\n');
            echo('</tr><tr id="array'+arrayNum+'" style="display:none">\n');
            echo('<td class="ArrayVal" colspan="2"><ul>\n');
            for(var iArr in obj[item]){
              var StrValue = obj[item][iArr].toString().replace(/&/g,"&amp;");
              StrValue = StrValue.replace(/</g,"&lt;");
              if(StrValue==""){ StrValue='<span class="null">vazio</span>'; }
              switch( this.myTypeOf(obj[item][iArr]) ){
              case "object":
                echo('<li class="ObjName"><a href="javascript:view(\''+item+'['+iArr+']\');">');
                echo('Objeto de '+this.getConstructor(obj[item][iArr])+'</a></li>\n');
                break;
              case "array":
                echo('<li class="ArrayName"><a href="javascript:view(\''+item+'['+iArr+']\');">');
                echo('Array</a> ( <pre>'+ StrValue +'</pre> )</li>\n');
                break;
              case "function":
                funcNum++;
                echo('<li class="FuncName"><a href="javascript:openclose(\'func'+funcNum+'\');">Função</a>\n');
                echo('<div id="func'+funcNum+'" style="display:none;"><pre>'+ StrValue +'</pre></div></li>\n');
                break;
              default:
                echo('<li class="Value"><pre>'+ StrValue +'</pre></li>\n');
                break;
              }
            }
            echo('<ul></td>\n');
            break;
          case "function":
            funcNum++;
            echo('<td class="FuncName"><a href="javascript:openclose(\'func'+funcNum+'\');">');
            echo('Função</a></td>\n');
            echo('</tr><tr id="func'+funcNum+'" style="display:none">\n');
            var StrFunc = obj[item].toString().replace(/&/g,"&amp;");
            StrFunc = StrFunc.replace(/</g,"&lt;");
            echo('<td class="FuncCode" colspan="2"><pre>'+StrFunc+'</pre></td>\n');
            break;
          default:
            var StrValue = obj[item].toString().replace(/&/g,"&amp;");
            StrValue = StrValue.replace(/</g,"&lt;");
            if(StrValue==""){ StrValue='<span class="null">vazio</span>'; }
            echo('<td class="Value"><pre>'+StrValue+'</pre></td>\n');
            break;
        }
      }
    }
    else { // itCanBeListed == false
      // Por algum motivo, o item não pode ser listado
      errorNum++;
      echo('<td class="ErrorName" nowrap="nowrap"><a href="javascript:openclose(\'error'+errorNum+'\');">');
      echo('Não Listavel - '+listingError.name+'</a></td>\n');
      echo('</tr><tr id="error'+errorNum+'" style="display:none">\n');
      echo('<td class="ErrorMess" colspan="2">ERRO:\n<pre>'+listingError.mess+'</pre></td>\n');
    }
    echo('</tr>');
  }
  echo('</table>\n');
  /// Rodapé ////////////////////////////////////
  echo('<div id="rodape">Desenvolvido por <a href="http://www.aurium.cjb.net" target="_blank">Aurium</a> - ');
  echo('Bugs, sugestões, comentáros : <a href="mailto:aurium@gmail.com">aurium@gmail.com</a></div>\n');
  echo('</body>\n</html>');
  /// Fim do Cabeçalho //////////////////////////
  wDebug.document.close();
  wDebug.debugingObj = obj;
}, // Fim do metodo view


"writeHeader" : function M_WriteHeader(doc){
  // Escreve o cabeçalho do documento de debug
  function echo(Str){ doc.write(Str); }
  echo('<html>\n<head>\n');
  echo('  <title>Debugando Objeto JavaScript</title>\n');
  echo('  <style>\n');
  echo('body{\n');
  echo('  margin: 0px;\n');
  echo('  font-family: sans-serif;\n');
  echo('  font-size: 12px;\n');
  echo('  background-color: #C0D0E0;');
  echo('  color: #505050;');
  echo('}\n');
  echo('h1{\n');
  echo('  text-align: center;');
  echo('  font-size: 150%;\n');
  echo('  color: #7090B0;');
  echo('  margin: 5px;');
  echo('}\n');
  echo('table{\n');
  echo('  width: 100%;\n');
  echo('  border-collapse: collapse;\n');
  echo('  border: none;\n');
  echo('  border-top: 2px solid #80A0B0;\n');
  echo('  border-bottom: 2px solid #80A0B0;\n');
  echo('  border-collapse: collapse;\n');
  echo('  background-color: #E0F0FF;');
  echo('}\n');
  echo('td{\n');
  echo('  border: none;\n');
  echo('  border-top: 1px solid #90B0C0;\n');
  echo('  padding: 2px 4px 2px 4px;\n');
  echo('  font-family: sans-serif;\n');
  echo('  font-size: 12px;\n');
  echo('}\n');
  echo('.null{\n');
  echo('  font-size: 80%;\n');
  echo('  color: #A0B0C0;\n');
  echo('}\n');
  echo('.ObjName a{\n');
  echo('  color: #8090A0;\n');
  echo('  font-weight: 600;\n');
  echo('  text-decoration: none;\n');
  echo('}\n');
  echo('.ArrayName a{\n');
  echo('  color: #0080A0;\n');
  echo('  text-decoration: none;\n');
  echo('}\n');
  echo('.ArrayVal{\n');
  echo('  background-color: #E8F4FF;\n');
  echo('}\n');
  echo('.ArrayVal li{\n');
  echo('  white-space: nowrap;\n');
  echo('}\n');
  echo('.FuncName a{\n');
  echo('  color: #508090;\n');
  echo('  text-decoration: none;\n');
  echo('}\n');
  echo('.FuncCode{\n');
  echo('  background-color: #E8F4FF;\n');
  echo('}\n');
  echo('.ErrorName{\n');
  echo('  color: #B07080;\n');
  echo('  text-decoration: none;\n');
  echo('}\n');
  echo('.ErrorMess{\n');
  echo('  background-color: #FFA0A0;\n');
  echo('}\n');
  echo('pre{\n');
  echo('  margin: 0px;\n');
  echo('  display: inline;\n');
  echo('}\n');
  echo('#rodape{\n');
  echo('  border: 1px solid #A0B0C0;\n');
  echo('  background-color: #C8D8E8;');
  echo('  margin: 2px;\n');
  echo('  font-size: 10px;\n');
  echo('  line-height: 20px;\n');
  echo('  text-align: right;\n');
  echo('  padding-right: 10px;\n');
  echo('  color: #7090B0;\n');
  echo('}\n');
  echo('#rodape a{\n');
  echo('  color: #7090B0;\n');
  echo('  text-decoration: none;\n');
  echo('}\n');
  echo('  </style>\n\n');
  echo('  <script type="text/javascript">\n');
  echo('function openclose(id){\n');
  echo('  var tr = document.getElementById(id).style;\n');
  echo('  if(tr.display == "none"){\n');
  echo('    if(window.navigator.appName.substr(0,5)=="Micro"){\n');
  echo('      tr.display = "block";\n');
  echo('    } else {\n');
  echo('      tr.display = "table-row";\n');
  echo('    }\n');
  echo('  } else {\n');
  echo('    tr.display = "none";\n');
  echo('  }\n');
  echo('}\n\n');
  echo('function view(obj){\n');
  echo('  if( parseInt(obj) == obj ){\n    // Eh um item de vetor\n');
  echo('    window.opener.debugObject.view( debugingObj[obj] );\n');
  echo('  } else {\n    // Eh um atributo de objeto\n');
  echo('    window.opener.debugObject.view( eval("debugingObj."+obj) );\n');
  echo('  }\n');
  echo('}\n');
  echo('  </script>\n\n');
  echo('</head>\n');
} // Fim do metodo writeHeader

}
