// CoolLayr.js
//
// Title:	Useful JavaScript functions for Layer object.
// Author:	Pankaj Katoch
// Updated:	12 August 1997
// 		Reaz Hoque (converted to CSSP syntax)
//              Eric Krock (added some comments)
// Description: Utility JavaScript file used by Layer Experiments
//              example. Extends JavaScript Layer object by using
//              prototype objects.


// global variables: BL stands for "blinds." These are intended
// to support a locking mechanism on the blinds to keep the user
// from clicking on "Show" in the middle of the "Hide" operation
// and vice versa; this has not been fully implemented and is a
// hook for future development.

var lockBL = false;
var arrBL = new Array();
var numBL = 0;
var tidBL = 0;

// some utility functions
var ldbStr = "";
// var ldb = java.lang.System.out.println;
function ldb() {};


//
function addBL(num) {
for(i = 0, j = arrBL.length; i < num; i++, j++) {
arrBL[j] = new Layer(1024);
arrBL[j].bgColor = "#CCCCCC";
arrBL[j].hide();
}
}



// trueStr and callStr are both JavaScript code inside
// strings. If trueStr evaluates to true, we evaluate
// callStr. Otherwise, we set a recursive timeout of
// length ms milliseconds.
function callIfTrue(trueStr, ms, callStr) {
if(eval(trueStr)) {
eval(callStr);
}
else {
setTimeout( "callIfTrue(\"" + trueStr + "\"," + ms + ",'" + callStr + "')", ms);
}
}



//  This is called when the blind has completed the hide operation.
function endHideBlinds(lyr, h, num, ms, inc) {
var c = lyr.clip;
var funcStr = "";

lockBL = true;
lyr.hide();

funcStr = "layer_blindSetClip(0, " + h/2 + ", " + c.right + "," + h/2 + "," + ms + "," + 0 + "," + inc + "," + "'lockBL=false;')";
tidBL = setInterval(funcStr, ms);
}



//  This is called when the blind has completed the show operation.
function endShowBlinds(lyr, h, num, ms, inc) {
var c = lyr.clip;
var funcStr = "";

lockBL = true;
lyr.show();

funcStr = "layer_blindSetClip(0, " + h/2 + ", " + c.right + "," + h/2 + "," + ms + "," + 0 + "," + inc + "," + "'lockBL=false;')";
tidBL = setInterval(funcStr, ms);
}



// move the layer up by the specified number of pixels
// (default to 10 pixels, in case of missing argument)
//
// Note: does not affect viewable area (clip rectangle)
//	 of this layer
//
function layer_moveUp(inc) {
if(layer_moveUp.arguments.length == 0) {
inc = 10;
}
this.top = this.top - inc;
}



// move the layer down by the specified number of pixels
// (default to 10 pixels, in case of missing argument)
//
// Note: does not affect viewable area (clip rectangle)
//	 of this layer
//
function layer_moveDown(inc) {
if(layer_moveDown.arguments.length == 0) {
inc = 10;
}
this.top = this.top + inc;
}



// move the layer left by the specified number of pixels
// (default to 10 pixels, in case of missing argument)
//
// Note: does not affect viewable area (clip rectangle)
//	 of this layer
//
function layer_moveLeft(inc) {
if(layer_moveLeft.arguments.length == 0) {
inc = 10;
}
this.left = this.left - inc;
}



// move the layer right by the specified number of pixels
// (default to 10 pixels, in case of missing argument)
//
// Note: does not affect viewable area (clip rectangle)
//	 of this layer
//
function layer_moveRight(inc) {
if(layer_moveRight.arguments.length == 0) {
inc = 10;
}
this.left = this.left + inc;
}



// scroll the layer up, within the viewing rectangle (clip area)
// by the specified number of pixels (default to 10 pixels, in
// case of missing argument)
//
function layer_scrollUp(inc) {
if(layer_scrollUp.arguments.length == 0) {
inc = 10;
}
this.top = this.top + inc;
this.clip.top = this.clip.top - inc;
this.clip.bottom = this.clip.bottom - inc;
}



// scroll the layer down, within the viewing rectangle (clip area)
// by the specified number of pixels (default to 10 pixels, in
// case of missing argument)
//
function layer_scrollDown(inc) {
if(layer_scrollDown.arguments.length == 0) {
inc = 10;
}
this.top = this.top - inc;
this.clip.top = this.clip.top + inc;
this.clip.bottom = this.clip.bottom + inc;
}



// scroll the layer left, within the viewing rectangle (clip area)
// by the specified number of pixels (default to 10 pixels, in
// case of missing argument)
//
function layer_scrollLeft(inc) {
if(layer_scrollLeft.arguments.length == 0) {
inc = 10;
}
this.left = this.left + inc;
this.clip.left = this.clip.left - inc;
this.clip.right = this.clip.right - inc;
}



// scroll the layer right, within the viewing rectangle (clip area)
// by the specified number of pixels (default to 10 pixels, in
// case of missing argument)
//
function layer_scrollRight(inc) {
if(layer_scrollRight.arguments.length == 0) {
inc = 10;
}
this.left = this.left - inc;
this.clip.left = this.clip.left + inc;
this.clip.right = this.clip.right + inc;
}



// move the top edge of the clip rectangle by (+ve or -ve)
// pixel increment
//
function layer_moveTopEdge(inc) {
if(layer_moveTopEdge.arguments.length == 0) {
inc = 10;
}
this.clip.top = this.clip.top + inc;
}



// move the bottom edge of the clip rectangle by (+ve or -ve)
// pixel increment
//
function layer_moveBottomEdge(inc) {
if(layer_moveBottomEdge.arguments.length == 0) {
inc = 10;
}
this.clip.bottom = this.clip.bottom + inc;
}



// move the left edge of the clip rectangle by (+ve or -ve)
// pixel increment
//
function layer_moveLeftEdge(inc) {
if(layer_moveLeftEdge.arguments.length == 0) {
inc = 10;
}
this.clip.left = this.clip.left + inc;
}



// move the right edge of the clip rectangle by (+ve or -ve)
// pixel increment
//
function layer_moveRightEdge(inc) {
if(layer_moveRightEdge.arguments.length == 0) {
inc = 10;
}
this.clip.right = this.clip.right + inc;
}



// Returns true if the "visibility" property of this layer is
// not set to "hide", (other values are "show" & "inherit")
//
function layer_isVisible() {
return this.visibility.toLowerCase() != "hide";
}



// set the layer's "visibility" property to "show"
//
// Note: the layer may still be not seen on the page, if there
//	 there are other "visible" Opaque layers on top of it
//
function layer_show() {
this.visibility = "show";
}



// set the layer's "visibility" property to "hide"
//
function layer_hide() {
this.visibility = "hide";
}



// specify a new clip rectangle for the layer
// this behaves the save way as the <CLIP> tag in HTML;
// this is, if only two arguments are passed then the left
// corner defaults to (0, 0)
//
function layer_setClip(x1, y1, x2, y2) {
if(layer_setClip.arguments.length == 4) {
this.clip.left = x1;
this.clip.top = y1;
this.clip.right = x2;
this.clip.bottom = y2;
}
else {
if(layer_setClip.arguments.length == 2) {
this.clip.left = 0;
this.clip.top = 0;
this.clip.right = x1;
this.clip.bottom = y1;
}
}
}



//
//
function layer_timedSetClip(x1, y1, x2, y2, ms, xinc, yinc, evalStr) {
if((layer_timedSetClip.arguments.length != 8) && (layer_timedSetClip.arguments.length != 7)) {
alert("timedSetClip() called with invalid number of arguments");
return;
}
if(layer_timedSetClip.arguments.length == 7)
evalStr = "";

// check for infinite loop
if((xinc == 0) && (yinc == 0))
alert("Error in timedSetClip() called for layer:" + this.name + ". (xinc = yinc = 0)");

var c = this.clip;
var more = false;

if((c.left != x1) && (xinc != 0)) {
if(c.left < x1) {
if((c.left + xinc) > x1)
c.left = x1;
else {
c.left = c.left + xinc;
more = true;
}
}
else {
if((c.left - xinc) < x1)
c.left = x1;
else {
c.left = c.left - xinc;
more = true;
}
}
}

if((c.top != y1) && (yinc != 0)) {
if(c.top < y1) {
if((c.top + yinc) > y1)
c.top = y1;
else {
c.top = c.top + yinc;
more = true;
}
}
else {
if((c.top - yinc) < y1)
c.top = y1;
else {
c.top = c.top - yinc;
more = true;
}
}
}

if((c.right != x2) && (xinc != 0)) {
if(c.right < x2) {
if((c.right + xinc) > x2)
c.right = x2;
else {
c.right = c.right + xinc;
more = true;
}
}
else {
if((c.right - xinc) < x2)
c.right = x2;
else {
c.right = c.right - xinc;
more = true;
}
}
}

if((c.bottom != y2) && (yinc != 0)) {
if(c.bottom < y2) {
if((c.bottom + yinc) > y2)
c.bottom = y2;
else {
c.bottom = c.bottom + yinc;
more = true;
}
}
else {
if((c.bottom - yinc) < y2)
c.bottom = y2;
else {
c.bottom = c.bottom - yinc;
more = true;
}
}
}

if(more) {
setTimeout( "document.layers[\""+ this.name + "\"].timedSetClip(" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + ms + "," + xinc + "," + yinc + "," + evalStr + ")", ms);
}
else {
eval(evalStr);
}
}



//
//
function layer_animateClip(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, ms, xinc, yinc) {
if(layer_animateClip.arguments.length != 11) {
return;
}
this.setClip(sx1, sy1, sx2, sy2);
this.timedSetClip(dx1, dy1, dx2, dy2, ms, xinc, yinc, "");
}



//
//
function layer_blindSetClip(x1, y1, x2, y2, ms, xinc, yinc, evalStr) {
if(layer_blindSetClip.arguments.length != 8) {
alert("layer_blindSetClip() called with invalid number of arguments (=" + layer_blindSetClip.arguments.length + ")");
return;
}

// check for infinite loop
if((xinc == 0) && (yinc == 0))
alert("Error in layer_blindSetClip() called for layer:" + this.name + ". (xinc = yinc = 0)");

var c = arrBL[0].clip;
var more = false;

if((c.left != x1) && (xinc != 0)) {
if(c.left < x1) {
if((c.left + xinc) > x1)
c.left = x1;
else {
c.left = c.left + xinc;
more = true;
}
}
else {
if((c.left - xinc) < x1)
c.left = x1;
else {
c.left = c.left - xinc;
more = true;
}
}
}

if((c.top != y1) && (yinc != 0)) {
if(c.top < y1) {
if((c.top + yinc) > y1)
c.top = y1;
else {
c.top = c.top + yinc;
more = true;
}
}
else {
if((c.top - yinc) < y1)
c.top = y1;
else {
c.top = c.top - yinc;
more = true;
}
}
}

if((c.right != x2) && (xinc != 0)) {
if(c.right < x2) {
if((c.right + xinc) > x2)
c.right = x2;
else {
c.right = c.right + xinc;
more = true;
}
}
else {
if((c.right - xinc) < x2)
c.right = x2;
else {
c.right = c.right - xinc;
more = true;
}
}
}

if((c.bottom != y2) && (yinc != 0)) {
if(c.bottom < y2) {
if((c.bottom + yinc) > y2)
c.bottom = y2;
else {
c.bottom = c.bottom + yinc;
more = true;
}
}
else {
if((c.bottom - yinc) < y2)
c.bottom = y2;
else {
c.bottom = c.bottom - yinc;
more = true;
}
}
}

for(i = 0; i < numBL; i++) {
arrBL[i].clip.left = c.left;
arrBL[i].clip.top = c.top;
arrBL[i].clip.right = c.right;
arrBL[i].clip.bottom = c.bottom;
}

if(!more) {
eval(evalStr);
clearInterval(tidBL);
}
}



//
//
// arguments -
//      h: Height of each "Blind" in pixels
//      ms: delay in miliseconds, for animation
//      inc: delta of "Blinds" animation in pixels
//      bgc: color of the "Blind"
//
function layer_hideUsingBlinds(h, ms, inc, bgc) {
var c = this.clip;
var funcStr = "";

// should check if not already locked by somebody
lockBL = true;

// calculate the number of "blinds" layers based on the
// clip height of target layer, and the requested height
// of "blinds"
numBL = (c.height - c.height%h)/h;
if((c.height)%h != 0)
numBL++;

// make sure that there are enough layers in the Blinds Array
if(arrBL.length < numBL)
addBL(numBL - arrBL.length);

flagBL = 0;
for(i = 0; i < numBL; i++) {
arrBL[i].zIndex = this.zIndex + 1;
arrBL[i].bgColor = bgc;
arrBL[i].moveTo(this.pageX + c.left, this.pageY + c.top + (i*h));
arrBL[i].setClip(0, h/2, c.right, h/2);
arrBL[i].show();
}

funcStr = "layer_blindSetClip(0, 0, " + c.right + "," + h + "," + ms + "," + 0 + "," + inc + "," + "'lockBL=false;')";
tidBL = setInterval(funcStr, ms);

// wait for the blinds to reach their full height, then make the layer
// and the blinds disappear
setTimeout("callIfTrue(\"(lockBL==false)\"," + ms + ",'endHideBlinds(document.layers[\"" + this.name + "\"]," + h + "," + numBL + "," + ms + "," + inc + ")')", ms*(h/inc));

}



//
//
// arguments -
//      h: Height of each "Blind" in pixels
//      ms: delay in miliseconds, for animation
//      inc: delta of "Blinds" animation in pixels
//      bgc: color of the "Blind"
//
function layer_showUsingBlinds(h, ms, inc, bgc) {
var c = this.clip;
var funcStr = "";

// should check if not already locked by somebody
lockBL = true;

// calculate the number of "blinds" layers based on the
// clip height of target layer, and the requested height
// of "blinds"
numBL = (c.height - c.height%h)/h;
if((c.height)%h != 0)
numBL++;

// make sure that there are enough layers in the Blinds Array
if(arrBL.length < numBL)
addBL(numBL - arrBL.length);

flagBL = 0;
for(i = 0; i < numBL; i++) {
arrBL[i].zIndex = this.zIndex + 1;
arrBL[i].bgColor = bgc;
arrBL[i].moveTo(this.pageX + c.left, this.pageY + c.top + (i*h));
arrBL[i].setClip(0, h/2, c.right, h/2);
arrBL[i].show();
}

funcStr = "layer_blindSetClip(0, 0, " + c.right + "," + h + "," + ms + "," + 0 + "," + inc + "," + "'lockBL=false;')";
tidBL = setInterval(funcStr, ms);

// wait for the blinds to reach their full height, then make the layer
// and the blinds disappear
setTimeout("callIfTrue(\"(lockBL==false)\"," + ms + ",'endShowBlinds(document.layers[\"" + this.name + "\"]," + h + "," + numBL + "," + ms + "," + inc + ")')", ms*(h/inc));

}



// Add these as prototype object methods, so that they are
// available to any Layer Object as a "Class" method.
//
// When you add a method to an object's prototype, all
// instances of that kind of object gain the method.  This
// is how we do object oriented programming and inheritance
// in JavaScript without using classes.
//
// For more information about object prototype, see:
//     _JavaScript: The Definitive Guide: Second Edition_
//     by David Flanagan. "Object Prototypes." pp. 106-110.
//     Publisher: O'Reilly & Associates.

Layer.prototype.moveUp = layer_moveUp;
Layer.prototype.moveDown = layer_moveDown;
Layer.prototype.moveLeft = layer_moveLeft;
Layer.prototype.moveRight = layer_moveRight;

Layer.prototype.scrollUp = layer_scrollUp;
Layer.prototype.scrollDown = layer_scrollDown;
Layer.prototype.scrollLeft = layer_scrollLeft;
Layer.prototype.scrollRight = layer_scrollRight;

Layer.prototype.moveTopEdge = layer_moveTopEdge;
Layer.prototype.moveBottomEdge = layer_moveBottomEdge;
Layer.prototype.moveLeftEdge = layer_moveLeftEdge;
Layer.prototype.moveRightEdge = layer_moveRightEdge;

Layer.prototype.isVisible = layer_isVisible;
Layer.prototype.show = layer_show;
Layer.prototype.hide = layer_hide;

Layer.prototype.setClip = layer_setClip;
Layer.prototype.timedSetClip = layer_timedSetClip;
Layer.prototype.blindSetClip = layer_blindSetClip;
Layer.prototype.animateClip = layer_animateClip;

Layer.prototype.hideUsingBlinds = layer_hideUsingBlinds;
Layer.prototype.showUsingBlinds = layer_showUsingBlinds;



// other functions, not related to Layer Object
function initCoolLayers() {
// for(i = 0; i < document.layers.length; i++) {
// save useful parameters for future reference
// document.layers[i].cl_savetop = document.layers[i].top;
// document.layers[i].cl_savebottom = document.layers[i].bottom;
// }
addBL(10);
}

initCoolLayers();

