text: /*
   * XML Logger javascript routines
   *
   * Extracted from Peek example, chapter 4 of
   * 'XMPP Programming with Javascript and jQuery' by Jack Moffitt
   */
  var XmlLogger = {
      master_div: null,
  
      show_traffic: function (body, type) {
          if (body.childNodes.length > 0) {
              var console = $(XmlLogger.master_div).get(0);
              var at_bottom = console.scrollTop >= console.scrollHeight - 
                  console.clientHeight;;
  
              $.each(body.childNodes, function () {
                  $(XmlLogger.master_div).append(
                      "<div class='" + type + "'>" + XmlLogger.pretty_xml(this) + "</div>" );
              });
  
              if (at_bottom) {
                  console.scrollTop = console.scrollHeight;
              }
          }
      },
  
      pretty_xml: function (xml, level) {
          var i, j;
          var result = [];
          if (!level) { 
              level = 0;
          }
  
          result.push("<div class='xml_level" + level + "'>");
          result.push("<span class='xml_punc'>&lt;</span>");
          result.push("<span class='xml_tag'>");
          result.push(xml.tagName);
          result.push("</span>");
  
          // attributes
          var attrs = xml.attributes;
          var attr_lead = []
          for (i = 0; i < xml.tagName.length + 1; i++) {
              attr_lead.push("&nbsp;");
          }
          attr_lead = attr_lead.join("");
  
          for (i = 0; i < attrs.length; i++) {
              result.push(" <span class='xml_aname'>");
              result.push(attrs[i].nodeName);
              result.push("</span><span class='xml_punc'>='</span>");
              result.push("<span class='xml_avalue'>");
              result.push(attrs[i].nodeValue);
              result.push("</span><span class='xml_punc'>'</span>");
  
              if (i !== attrs.length - 1) {
                  result.push("</div><div class='xml_level" + level + "'>");
                  result.push(attr_lead);
              }
          }
  
          if (xml.childNodes.length === 0) {
              result.push("<span class='xml_punc'>/&gt;</span></div>");
          } else {
              result.push("<span class='xml_punc'>&gt;</span></div>");
  
              // children
              $.each(xml.childNodes, function () {
                  if (this.nodeType === 1) {
                      result.push(XmlLogger.pretty_xml(this, level + 1));
                  } else if (this.nodeType === 3) {
                      result.push("<div class='xml_text xml_level" + (level + 1) + "'>");
                      result.push(this.nodeValue);
                      result.push("</div>");
                  }
              });
              
              result.push("<div class='xml xml_level" + level + "'>");
              result.push("<span class='xml_punc'>&lt;/</span>");
              result.push("<span class='xml_tag'>");
              result.push(xml.tagName);
              result.push("</span>");
              result.push("<span class='xml_punc'>&gt;</span></div>");
          }
          
          return result.join("");
      }
  }
  