//'============================================================================
//'
//' Program:		XI_HtmlBuilder.js
//'
//'			
//' Created:		Mipela GIS Pty Ltd
//'
//' Date:		18-11-2004	Version:		3.0
//
//'
//'
//' COPYRIGHT NOTICE - Mipela (GIS) Pty Ltd 2003
//' The copyright in this work is vested in Mipela (GIS) Pty Ltd and is issued in
//' confidence for the purpose only for which it is supplied. It must not be
//' reproduced in whole or in part except under an agreement with, or with the
//' consent of, Mipela Pty Ltd and then only on the condition that this notice
//' appears in any such reproduction. No information as to the contents or 
//' subject matter of this code or any part thereof may be given orally or in
//' writing or communicated in any manner whatsoever to any third party without
//' prior consent in writing of Mipela (GIS) Pty Ltd.
//'
//'============================================================================

var htmlEscapes = new Array();

htmlEscapes["<"] = "&lt;";
htmlEscapes[">"] = "&gt;";
htmlEscapes["\""] = "&quot;";
htmlEscapes["&"] = "&amp;";

// This object encapsulates HTML element and attribute syntax from the caller.
// It allows HTML strings to be built more easily and more robustly
function HtmlBuilder()
{
  this.buffer = ""; // this is the frequent appends buffer.
  this.oBuffer = ""; // this is the final output buffer.
  this.bTagOpen = false; // indicates that a tag is open.
  
  this.attributeEscapes = /[&"<>]/; // include double quotes for attributes
  this.contentEscapes = /[&<>]/; // no double quotes for content
  
  this.tag = HtmlBuilderTag;
  this.attr = HtmlBuilderAttr;
  this.attrEx = HtmlBuilderAttrEx;
  this.text = HtmlBuilderText;
  this.raw = HtmlBuilderRawText
  this.endTag = HtmlBuilderEndTag;
  this.escapeWith = HtmlBuilderEscapeWith;
  this.doubleBuffer = HtmlBuilderDoubleBuffer;
  
  this.endTreeItem = HtmlBuilderEndTreeItem;
  this.beginTreeItem = HtmlBuilderBeginTreeItem;
  this.addCrumbCells = HtmlBuilderAddCrumbCells;
  this.selectedAttr = HtmlBuilderSelectedAttr;
}

function HtmlBuilderBeginTreeItem(treeItemType, treeItemId)
{
  this.tag("div").attr("id", treeItemType + treeItemId);
  this.tag("table").attr("border", "0").attr("cellspacing", "0").attr("cellpadding", "0").attr("width", "100%");
  return (this);
}

function HtmlBuilderEndTreeItem()
{
	this/*.tag("td").attr("width", "100%").endTag("td")*/.endTag("table").endTag("div");
}

function HtmlBuilderAddCrumbCells(sCrumbs)
{
	var index;

	for (index=0;index<sCrumbs.length;index++)
	{
		this.tag("td").attr("valign", "top").attr("align", "left").attr("width", "16");
		
		if (sCrumbs.charAt(index) == "1")
		  this.attr("background", "graphics/vertline.gif").tag("img").attr("src", "graphics/vertline.gif");
		else if (sCrumbs.charAt(index) == "0")
		  this.tag("img").attr("src", "graphics/blank.gif");

		this.attr("width", "16").attr("height", "22").attr("border", "0").endTag("img").endTag("td");
	}
}

function HtmlBuilderTag(tag)
{
  if (this.bTagOpen)
    this.buffer += '>';

  this.bTagOpen = true;
  this.buffer += '<';
  this.buffer += tag;
  return (this);
}

function HtmlBuilderAttr(name, val)
{
  if (this.bTagOpen)
  {
    this.buffer += ' ';
    this.buffer += name;

    if (val != null)
    {
      this.buffer += '="';
      this.escapeWith(val, this.attributeEscapes);
      this.buffer += '"';
    }
  }
  return (this);
}

function HtmlBuilderAttrEx(name, val)
{
  if (this.bTagOpen)
  {
    this.buffer += ' ';
    this.buffer += name;

    if (val != null)
    {
      var offset, match, estring, tmp = "";

      while ((matches = this.attributeEscapes.exec(val)) != null)
      {
        tmp += val.slice(0, offset = matches.index);

        if ((estring = htmlEscapes[match = matches[0]]) != null)
          tmp += estring;
        else
          tmp += match;

        val = val.substr(offset + match.length);
      }
      
      tmp += val;

      this.buffer += '="';
      this.buffer += tmp.replace(/(\r\n|\r|\n)/g, "&#10;");
      this.buffer += '"';
    }
  }
  return (this);
}

function HtmlBuilderSelectedAttr(name, val)
{
  if (name == val)
    this.attr("selected", null);

  return (this);
}

function HtmlBuilderRawText(val)
{
  if (this.bTagOpen)
  {
    this.buffer += '>';
    this.bTagOpen = false;
  }

  this.buffer += val;
  return (this);
}

function HtmlBuilderText(val)
{
  if (this.bTagOpen)
  {
    this.buffer += '>';
    this.bTagOpen = false;
  }

  this.escapeWith(val, this.contentEscapes);
  return (this);
}

function HtmlBuilderEndTag(tag)
{
  if (this.bTagOpen)
  {
    this.buffer += '>';
    this.bTagOpen = false;
  }

  this.buffer += '</';
  this.buffer += tag;
  this.buffer += '>';

  if (this.buffer.length > 1500)
    this.doubleBuffer();

  return (this);
}

function HtmlBuilderEscapeWith(val, reg)
{
  if (val != null)
  {
    var offset;
    var match;
    var estring;

    // if the regular expression stuff worked as
    // documented, this stuff would be a lot easier
    // than the way that we've done it here (and
    // subsequently considerably more efficient).

    while ((matches = reg.exec(val)) != null)
    {
      this.buffer += val.slice(0, offset = matches.index);

      if ((estring = htmlEscapes[match = matches[0]]) != null)
        this.buffer += estring;
      else
        this.buffer += match;

      val = val.substr(offset + match.length);
    }

    this.buffer += val;
  }
}

function HtmlBuilderDoubleBuffer()
{
  this.oBuffer += this.buffer;
  this.buffer = "";

  return (this);
}

function updateInnerHtml(obj, sText)
{
  var builder = new HtmlBuilder();
  builder.text(sText);
  obj.innerHTML = builder.buffer;
}

