// $Id: //placeware/dev/i18n/build/placeware.ccc/lib/ccc/button.js#8 $
// Copyright 1999-2002 PlaceWare, Inc.

/*
 * File: element.js
 * Include with: <SCRIPT SRC="element.js"></SCRIPT>
 *
 * This file defines the Element(DIV) class, which provides a portable API
 * to Dynamic HTML features.
 */
var elements 	    = new Object();

//#####################################################################
// This is the constructor function for Element objects.
// The arguments are the following:
//   window: The Window object in which the dynamic Element is to appear
//   id:     The HTML ID for the dynamic Element. Must be unique.
//   body:   HTML text that constitutes the body of the dynamic Element
//   left:   The optional initial X-coordinate of the Element
//   top:    The optional initial Y-coordinate of the Element
//   width:  The optional width of the Element
//   height: The optional height of the Element
//
// This constructor outputs a style sheet into the current document.
// This means that it can only be called from the <HEAD> of the document
// before any text has been output for display.
//#####################################################################
function Element(window, id, classId, body, left, top, width, height) {
    // Remember some arguments for later.
    this.window  = window;
    this.id      = id;
    this.classId = classId;
    this.body    = body;
    // left, top, width, height are set in ThemeAddDivStylers()
    this.left    = left;
    this.top     = top;
    this.width   = width;
    this.height  = height;

    this.write      = ElementWrite;
    this.setBody    = ElementSetBody;
    this.moveTo     = ElementMoveTo;
    this.moveBy     = ElementMoveBy;
    this.clipValue  = ElementClipValue;
    this.clipTo     = ElementClipTo;
    this.clipBy     = ElementClipBy;
    this.show       = ElementShow;
    this.hide       = ElementHide;
    this.setBgColor = ElementSetBgColor;
    this.setBgImage = ElementSetBgImage;
    this.setOrder   = ElementSetOrder;
    this.get	    = ElementGet;
    this.getX	    = ElementGetX;
    this.getY	    = ElementGetY;
    this.getWidth   = ElementGetWidth;
    this.getHeight  = ElementGetHeight;
    this.getOrder   = ElementGetOrder;
    this.isVisible  = ElementIsVisible;
    this.addEvtHandler    = ElementAddEventHandler;
    this.removeEvtHandler = ElementRemoveEventHandler;

    elements[id] = this;
}

function ElementWrite(body) {
    // body can overwrite this.body
    if (body) this.body = body;

    // Output the Element within a <DIV> tag.  Specify the element id.
    dw('<DIV ID="' + this.id + '"');
    if (this.classId) dw(' CLASS="' + this.classId + '"');
    dw('>');
    if (this.body) dw(this.body);
    dw('</DIV>\n');
    
    if (isNetscape4) {
       // save a reference to the Layer object created by this dynamic Element.
       this.layer = this.window.document[this.id];
    } else {
       // save references to the <DIV> element
       // we've created, and to its associated Style element.
       // These will be used throughout the methods that follow.
       this.element = this.window.document.all[this.id];
       this.style = this.element.style;
    }
}

function ElementGet() {
    if (isNetscape4)
	return this.layer;
    else
    	return this.element;
}

/*
 * This method allows us to dynamically change the contents of
 * the dynamic Element. The argument or arguments should be HTML
 * strings which become the new body of the Element.
 */
function ElementSetBody(body) {
    if (isNetscape4) {
       this.layer.document.open();
       this.layer.document.write(body);
       this.layer.document.close();
    } else {
       this.element.innerHTML = body;
    }

}

function ElementMoveTo(x,y) {
    if (isNetscape4) {
       this.layer.moveTo(x,y);
    } else {
       this.style.pixelLeft = x;
       this.style.pixelTop = y;
    }
}

function ElementMoveBy(x,y) {
    if (isNetscape4) {
       this.layer.moveBy(x,y);
    } else {
       this.style.pixelLeft += x;
       this.style.pixelTop += y;
    }
}

function ElementClipValue(which)
{
    if (isNetscape4) {
	if (which=="t") return this.layer.clip.top;
	if (which=="r") return this.layer.clip.right;
	if (which=="b") return this.layer.clip.bottom;
	if (which=="l") return this.layer.clip.left;
    }
    else {
	var clipv = this.style.clip.split("rect(")[1].split(")")[0].split("px");
	if (which=="t") return Number(clipv[0]);
	if (which=="r") return Number(clipv[1]);
	if (which=="b") return Number(clipv[2]);
	if (which=="l") return Number(clipv[3]);
    }
}

function ElementClipTo(t,r,b,l)
{
    if (isNetscape4) {
	this.layer.clip.top 	= t;
	this.layer.clip.right 	= r;
	this.layer.clip.bottom 	= b;
	this.layer.clip.left 	= l;
    }

    // In IE you have to obtain all the clip values and reset them
    // at the same time. e.g.:
    // divName.style.clip = "rect(0px 100px 50px 0px)"
    else  this.style.clip = "rect("+t+"px "+r+"px "+b+"px "+l+"px)";
}

function ElementClipBy(t,r,b,l)
{
    if (isNetscape4) {
	this.layer.clip.top 	= this.clipValue('t') + t;
	this.layer.clip.right 	= this.clipValue('r') + r;
	this.layer.clip.bottom 	= this.clipValue('b') + b;
	this.layer.clip.left 	= this.clipValue('l') + l;
    }
    else this.style.clip = "rect("+(this.clipValue('t')+t)+"px "
			        +(this.clipValue('r')+r)+"px "
			        +(this.clipValue('b')+b)+"px "
			        +(this.clipValue('l')+l)+"px)";
}

function ElementShow() {
    if (isNetscape4) {
       this.layer.visibility = "show";
    } else {
       this.style.visibility = "visible";
    }
}

function ElementHide() {
    if (isNetscape4) {
      this.layer.visibility = "hide";
    } else {
      this.style.visibility = "hidden";
    }
}

function ElementSetBgColor(color) {
    if (isNetscape4) {
      this.layer.bgColor = color;
    } else {
      this.style.backgroundColor = color;
    }
}

function ElementSetBgImage(image) {
    if (isNetscape4) {
      this.layer.background.src = image;
    } else {
      this.style.backgroundImage = image;
    }
}

function ElementSetOrder(z) {
    if (isNetscape4) {
      this.layer.zIndex = z;
    } else {
      this.style.zIndex = z;
    }
}

function ElementGetX() {
    if (isNetscape4) {
      return this.layer.left;
    } else {
      return this.style.pixelLeft;
    }
}

function ElementGetY() {
    if (isNetscape4) {
      return this.layer.top;
    } else {
      return this.style.pixelRight;
    }

}

function ElementGetWidth() {
    if (isNetscape4) {
      return this.layer.width;
    } else {
      return this.style.width;
    }

}

function ElementGetHeight() {
    if (isNetscape4) {
      return this.layer.height;
    } else {
      return this.style.height;
    }

}

function ElementGetOrder() {
    if (isNetscape4) {
      return this.layer.zIndex;
    } else {
      return this.style.zIndex;
    }
}

function ElementIsVisible() {
    if (isNetscape4) {
      return this.layer.visibility == "show";
    } else {
      return this.style.visibility == "visible";
    }
}

/*
 * This method registers a handler for the named event on the
 * element. The event name argument should be the name of an
 * event handler property, such as "onmousedown" or "onkeypress".
 * The handler is a function that takes whatever action is necessary.
 * Because Navigator and IE do not have compatible Event objects,
 * all event details are passed as arguments to the handler function.
 * When invoked, the handler will be passed the following nine arguments:
 *   1) A reference to the Element object
 *   2) A string containing the event type
 *   3) The X-coordinate of the mouse, relative to the Element
 *   4) The Y-coordinate of the mouse.
 *   5) The mouse button that was clicked (if any)
 *   6) The Unicode code of the key that was pressed (if any)
 *   7) A boolean specifying whether the Shift key was down
 *   8) A boolean specifying whether the Control key was down
 *   9) A boolean specifying whether the Alt key was down
 * Event handlers that are not interested in all these arguments do
 * not have to declare them all in their argument lists, of course.
 */
function ElementAddEventHandler(eventname, handler) {
    var dynel = this;  // Current Element for use in the nested function.
    if (isNetscape4) {
        // Arrange to capture events on this layer.
        this.layer.captureEvents(Element._eventmasks[eventname]);

        // Define an event handler that will invoke the specified handler,
        // and pass it the nine arguments specified above.
        this.layer[eventname] = function(event) {
            return handler(dynel, event.type, event.x, event.y,
                       event.which, event.which,
                       ((event.modifiers & Event.SHIFT_MASK) != 0),
                       ((event.modifiers & Event.CTRL_MASK) != 0),
                       ((event.modifiers & Event.ALT_MASK) != 0));
        }
    } else {

        // Set an IE4 event handler that invokes the specified handler
        // with the appropriate nine arguments.
        this.element[eventname] = function() {
           var e = dynel.window.event;
           e.cancelBubble = true;
           return handler(dynel, e.type, e.x, e.y, e.button, e.keyCode,
                              e.shiftKey, e.ctrlKey, e.altKey);
        }
    }

}


/*
 * This method unregisters the named event handler. It should be
 * called with a single string argument such as "onmouseover".
 */
 function ElementRemoveEventHandler(eventname) {
     if (Netscape) {
        this.layer.releaseEvents(Element._eventmasks[eventname]);
        delete this.layer[eventname];
     } else {
     	delete this.element[eventname];
     }
 }

if (isNetscape4) {
 /*
  * This array is used internally by the two methods above to map
  * from event name to event type.
  */
 Element._eventmasks = {
      onabort:Event.ABORT, onblur:Event.BLUR, onchange:Event.CHANGE,
      onclick:Event.CLICK, ondblclick:Event.DBLCLICK,
      ondragdrop:Event.DRAGDROP, onerror:Event.ERROR,
      onfocus:Event.FOCUS, onkeydown:Event.KEYDOWN,
      onkeypress:Event.KEYPRESS, onkeyup:Event.KEYUP, onload:Event.LOAD,
      onmousedown:Event.MOUSEDOWN, onmousemove:Event.MOUSEMOVE,
      onmouseout:Event.MOUSEOUT, onmouseover:Event.MOUSEOVER,
      onmouseup:Event.MOUSEUP, onmove:Event.MOVE, onreset:Event.RESET,
      onresize:Event.RESIZE, onselect:Event.SELECT, onsubmit:Event.SUBMIT,
      onunload:Event.UNLOAD
 };

}
