/*
	worksheet library

-	contents{}
-	dependencies{objects{}, libraries{}}
*/

/**
	from arc-form.js {
	Copyright (C) 2000-2001 Jay R. Smith Mfg Co.
	Distributed under the GNU Lesser General Public License.
**/
/*
	DomEventManager
	a class that manages events of a form element
	2001-02-22 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager}}
*/
Base = EventManager
DomEventManager = cDE = function (element, divWrapper, eventIds)
{if(arguments.length>0){
	var i, idCur, e
	var id = DomEventManager.refs.length

	if (is.dom||is.ie) e = element
	else if (is.ns) e = divWrapper.document

	DomEventManager.refs[id] = this
	this.lists = new Object()
	this.listeners = new Array()
	for (i = eventIds.length - 1; i >= 0; i--) {
		idCur = eventIds[i]
		this.lists[idCur] = new Array()
		eval('function DEM_dispatch'+ id +'(evt){ return DomEventManager.refs['+ id +'].invokeEvent("'+ idCur +'", evt)}')
		if (is.ns&&is.v<5) e.captureEvents( eval("Event."+ idCur.toUpperCase()) )
		eval("e.on"+ idCur +" = DEM_dispatch"+ id)
	}
};}
cDE.prototype = new Base()
cDE.refs = new Array()

/*
	CheckboxField
	2001-05-17 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager, DomEventManager}}
*/

Base = EventManager
CheckboxField = cCF = function (formCheckboxElement, formDiv, defaultChecked)
{if(arguments.length>0){
	this.CF_base(new Array("EMBlur", "EMChange"))

	this.e = formCheckboxElement
	this.e.checked = defaultChecked
	a = new Array("click")
	man = new DomEventManager(formCheckboxElement, formDiv, a)
	man.addEventListener( new EventMethodListener(a[0], this, a[0]) )
};}
cCF.prototype = new Base()
pCF = cCF.prototype
pCF.CF_base = Base

pCF.click = function (evt) {
	this.invokeEvent("EMChange")
}

pCF.getValue = function () {
	return this.e.checked
}

pCF.focus = function () {
	this.e.focus()
}

pCF.setValue = function (checked, quietFlag) {
	this.e.checked = checked
	if (! quietFlag) this.invokeEvent("EMChange")
}
/*
	RadioField
	2001-04-11 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager, DomEventManager}}
*/
Base = EventManager
RadioField = cRF = function (formRadioElements, formDivs, defaultIndex)
{if(arguments.length>0){
	var i, manCur, a

	this.selectedIndex = defaultIndex
	this.es = formRadioElements
	this.RF_base(new Array ("EMBlur", "EMChange"))
	a = new Array("click")
	for (i = formRadioElements.length - 1; i >= 0; i--) {
		if (formDivs != null) {
			manCur = new DomEventManager(formRadioElements[i], formDivs[i], a)
		} else {
			manCur = new DomEventManager(formRadioElements[i], null, a)
		}	
		manCur.addEventListener( new EventMethodListener(a[0], this, a[0], i) )
		formRadioElements[i].checked = false
	}
	formRadioElements[defaultIndex].checked = true
};}
cRF.prototype = new Base()
pRF = cRF.prototype
pRF.RF_base = Base

//* methods {
pRF.click = function (evt, eIndex) {
	this.setValue(eIndex, false)
}

pRF.setValue = function(itemIndex, quietFlag) {
	this.es[this.selectedIndex].checked = false
	this.es[itemIndex].checked = true
	this.selectedIndex = itemIndex
	if (! quietFlag) this.invokeEvent("EMChange")
}

pRF.getValue = function () {
	return this.es[this.selectedIndex].value
}

pRF.focus = function () {
	this.es[this.selectedIndex].focus()
}
//* methods }

/*
	FilteredField object
	a class that manages a field that fires validation events
	2001-10-03 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager, DomEventManager, EventMethodListener}, others{"the size attribute of the tag that creates the formInputElement should match the fieldWidthCharCount"}}
*/
Base = EventManager
FilteredField = cRJ = function (formInputElement, formDiv, valueDefault, 
			invalidCharErrStatusMsg)
{if(arguments.length>0){
	var man, a, i

	this.RJF_base(new Array ("EMChangeOnBlur", "EMChange", "EMFocus", "EMValidate",
				"EMValidateKeydown", "EMValidateKeyup", "EMBlur"))
	this.e = formInputElement
	this.statusErrMsg = invalidCharErrStatusMsg
	this.valueDefault = valueDefault
	this.value = valueDefault

	a = new Array("blur", "focus", "keydown", "keyup")
	man = new DomEventManager(formInputElement, formDiv, a)
	for (i = a.length -1; i >= 0; i--) {
		man.addEventListener( new EventMethodListener(a[i], this, a[i]) )
	}

	this.refresh(false)
};}
cRJ.prototype = new Base()
pRJ = cRJ.prototype
pRJ.RJF_base = Base

//* methods {
pRJ.cleanupAfterValueEdit = function () {
	var i
	var valueNew = this.e.value
	var valueClean = ""
	var charCur
	var redisplayRequired = false
	var eventCur = new Object()

	eventCur.value = valueNew
	if ( this.invokeEvent("EMValidate", eventCur) ) {
		if (this.statusErrMsg != null) status = ""
		for (i = 0; i < valueNew.length; i++) {
			charCur = valueNew.charAt(i)
			if (charCur != " ") valueClean += charCur
		}
	} else {
		if (this.statusErrMsg != null) status = this.statusErrMsg
		valueClean = this.value
		redisplayRequired = true
	}

	if (valueClean == "") {
		redisplayRequired = true
		valueClean = this.valueDefault
	}

	this.value = valueClean

	if (redisplayRequired) this.refresh(true)
}

pRJ.refresh = function (select) {
	this.e.value = this.value
	if (select) this.select()
}

pRJ.select = function () {
	this.e.select()
}

pRJ.blur = function () {
	if (! ((is.ns) && (is.p=="mac") && (is.v<5)) ) {
		this.refresh(false)
		this.invokeEvent("EMChangeOnBlur")
	}
	this.invokeEvent("EMBlur")
}

pRJ.focus = function () {
	this.refresh(true)
	this.e.focus()
	this.invokeEvent("EMFocus")
}

pRJ.keydown = function (evt) {
	var keycode
	var allowKey
	var eventCur = new Object()

	if (is.ns) keycode = evt.which
	else if (is.ie) keycode = window.event.keyCode

	eventCur.character = String.fromCharCode(keycode)
	allowKey = this.invokeEvent("EMValidateKeydown", eventCur)

	if (this.statusErrMsg != null) {
		if (allowKey) status = ""
		else status = this.statusErrMsg
	}

	//* IE 5 for Mac garbles the keyCode if window.event.returnValue is modified
	if (is.ns) return allowKey
	else if (is.ie && (is.p != "mac")) window.event.returnValue = allowKey
}

pRJ.keyup = function (evt) {
	var keycode
	var eventCur = new Object()

	if (is.ns) keycode = evt.which
	else if (is.ie) keycode = window.event.keyCode

	eventCur.character = String.fromCharCode(keycode)
	if (this.invokeEvent("EMValidateKeyup", eventCur)) {
		switch (keycode) {
			case 13: // [enter]
				this.cleanupAfterValueEdit()
				this.refresh(true)
				this.invokeEvent("EMChange")
			break
			default:
				this.cleanupAfterValueEdit()
			break
		}
	}
}

pRJ.setValue = function (value, quietFlag) {
	if (value != this.value) {
		this.value = value
		this.refresh(false)
		if (! quietFlag) this.invokeEvent("EMChange")
	}
}

pRJ.getValue = function () {
	return this.value
}
//* methods }

/*
	ManagedButton
	2001-02-22 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager, DomEventManager, EventMethodListener}}
*/
Base = EventManager
ManagedButton = cMB = function (formButtonElement, formDiv)
{if(arguments.length>0){
	var man, a, i
	this.MB_base(new Array("EMBlur", "EMChange", "EMFocus"))

	this.e = formButtonElement

	a = new Array("blur", "focus", "click")
	man = new DomEventManager(formButtonElement, formDiv, a)
	for (i = a.length -1; i >= 0; i--) {
		man.addEventListener( new EventMethodListener(a[i], this, a[i]) )
	}
};}
cMB.prototype = new Base()
pMB = cMB.prototype
pMB.MB_base = Base

pMB.blur = function (evt) { this.invokeEvent("EMBlur", evt) }

pMB.focus = function (evt) {
	this.e.focus()
	return this.invokeEvent("EMFocus", evt)
}

pMB.click = function (evt) { this.invokeEvent("EMChange", evt) }


/*
	ManagedField
	2001-02-22 Joe Walp <walpj@usa.net>

-	dependencies{objects{is, EventManager, DomEventManager, EventMethodListener}}
*/
Base = EventManager
ManagedField = cMF = function (formInputElement, formDiv, valueDefault)
{if(arguments.length>0){
	var man, a, i

	this.MF_base(new Array ("EMBlur", "EMChange", "EMFocus", "EMValidateKeyup"))
	this.e = formInputElement

	a = new Array("blur", "focus", "keyup")
	man = new DomEventManager(formInputElement, formDiv, a)
	for (i = a.length -1; i >= 0; i--) {
		man.addEventListener( new EventMethodListener(a[i], this, a[i]) )
	}

	this.e.value = valueDefault
};}
cMF.prototype = new Base()
pMF = cMF.prototype
pMF.MF_base = Base

//* methods {
pMF.select = function () {
	this.e.select()
}

pMF.focus = function () {
	this.select()
	this.e.focus()
	this.invokeEvent("EMFocus")
}

pMF.keyup = function (evt) {
	var keycode
	var eventCur = new Object()

	if (is.ns) keycode = evt.which
	else if (is.ie) keycode = window.event.keyCode

	eventCur.character = String.fromCharCode(keycode)
	if (this.invokeEvent("EMValidateKeyup", eventCur)) {
		if (keycode == 13) { //* [enter]
			this.invokeEvent("EMChange")
		}
	}
}

pMF.setValue = function (value, quietFlag) {
	this.e.value = value
	if (! quietFlag) this.invokeEvent("EMChange")
}

pMF.getValue = function () {
	return this.e.value
}

pMF.blur = function () {
	if (! ((is.ns) && (is.p=="mac") && (is.v<5)) ) {
		this.invokeEvent("EMBlur")
	}
}
//* methods }
/**
	from arc-form.js }
**/

/**
	from arc-util.js {
	Distributed under GNU Lesser General Public License.
**/

/*
	Vector
	2001-02-16 Joe Walp <walpj@usa.net>
*/

Vector = cV = function () {
	this.refs = new Array()
}
pV = cV.prototype

//* methods {
pV.add = function (item) {
	this.addInsert(this.refs.length, item)
}

pV.addInsert = function (index, item) {
	this.refs = this.refs.slice(0, index).concat(new Array(item), this.refs.slice(index))
}

pV.indexOf = function (item) {
	var i
	for (i = this.refs.length - 1; i >= 0; i--) {
		if (this.refs[i] == item) return i
	}
}

pV.remove = function (index) {
	if (index == 0) this.refs = this.refs.slice(1)
	else this.refs = this.refs.slice(0,index).concat(this.refs.slice(index+1))
}

pV.get = function (index) {
	return this.refs[index]
}

pV.size = function () { return this.refs.length }
//* methods }


/*
	ElementFromArrayViewer object
	2001-08-04 Joe Walp <walpj@usa.net>
*/
ElementFromArrayViewer = cEA = function (elementArray)
{if(arguments.length>0){
	this.es = elementArray
	this.selectedIndex = null
};}
pEA = cEA.prototype

//* methods {
pEA.setValue = function (itemIndex) {
	if (this.selectedIndex != null) {
		this.setVis(this.es[this.selectedIndex], "hidden")
	}
	this.setVis(this.es[itemIndex], "visible")
	this.selectedIndex = itemIndex
}

pEA.setVis = function (e, state) {
	e.style.visibility = state
}

pEA.init = function (itemIndex) {
	var i

	for (i = this.es.length - 1; i >= 0; i--) {
		this.setVis(this.es[i], "hidden")
	}
	this.setValue(itemIndex)
}
//* methods }


/*
	VerticalAppendRemoveNode
	2001-10-04 Joe Walp <walpj@usa.net>
*/
VerticalAppendRemoveBlock = cAR = function (node, heightNode, initialHeight) {
	this.p = node // parent
	this.lp = heightNode // layout parent
	this.h = initialHeight
	this.lp.style.height = this.h +"px"
}
pAR = cAR.prototype

pAR.appendChild = function (e, hDelta) {
	this.h += hDelta
	this.lp.style.height = this.h +"px"
	this.p.appendChild(e)
}

pAR.removeChild = function (e, hDelta) {
	this.p.removeChild(e)
	this.h += hDelta
	this.lp.style.height = this.h +"px"
}

/*
	formatNumber function
	modified from code by Duncan Crombie: dcrombie@chirp.com.au
	2001-01-10  removed decoration support -- Joe Walp <walpj@usa.net>

-	dependencies{}
*/
function formatNumber(number, format) {
	var n = number
	var f = format
	var nl, nr, sl, sr, dec, slc, i, charCur
	if (n - 0 != n) return null
	n = "" + n; // convert number input to string

	// split number and format into LHS and RHS using decpoint as divider
	dec = n.indexOf(".") != -1;
	nl = (dec) ? n.substring(0, n.indexOf(".")) : n
	nr = (dec) ? n.substring(n.indexOf(".") + 1) : ""
	dec = f.indexOf(".") != -1;
	sl = (dec) ? f.substring(0, f.indexOf(".")) : f;
	sr = (dec) ? f.substring(f.indexOf(".") + 1) : "";

	// adjust decimal places by cropping or adding zeros to LHS of number
	if (sr.length < n.length) {
		charCur = nr.charAt(sr.length) - 0;
		nr = nr.substring(0, sr.length);
		if (charCur >= 5) nr = "" + ((nr - 0) + 1); // round up
		if (sr.length < nr.length) {
			nr = nr.substring(1);
			nl = (nl - 0) + 1;
		}
	} else {
		for (i=nr.length; sr.length > nr.length; i++) {
			if (sr.charAt(i) == "0") nr += "0"; // append zero to RHS of number
			else break;
		}
	}

	// remove hashes from LHS of format
	slc = ""
	for (i=0; i < sl.length; i++)
		if (sl.charAt(i) == "#")
			slc += input.charAt(i)

	// adjust leading zeros
	while (slc.length > nl.length)
		nl = "0" + nl

	return nl + ((nr != "") ? "." + nr : "")
}
/**
	from arc-util.js }
**/
/**
	Copyright (C) 2001 Jay R. Smith Mfg Co.
	All rights reserved.
**/

var numericFieldInvalidCharErrStatusMsg = "invalid character"

var numberCharFilterExpr = o = new Object()
o["ns"] = /^\r?[\b]?\t?\.? ?-?\d?$/
o["ie"] = /^\x08?\x09?\x0D?\x20?\x23?\x24?\x25?\x26?\x27?\x28?\x2E?\x30?\x31?\x32?\x33?\x34?\x35?\x36?\x37?\x38?\x39?\x60?\x61?\x62?\x63?\x64?\x65?\x66?\x67?\x68?\x69?\x6D?\x6E?\xBD?\xBE?$/
var numberValidationExprGood = /^ *\d*\.?\d*$/
var numberValidationExprBad = /^ *0+\d+/

var numberRoundingFactor = 10000
var numberFormat = "0.#"

var buttonHeight = 26
var buttonRecentDelay = 200
var fixtureListFocusIndexInitialOffset = 11
var miscListFocusIndexInitialOffset = 22
var fixtureDescriptionDefault = "Sink A"
var miscDescriptionDefault = ""
var fixtureDrainDownPeriodDefault = "2"
var suppDocs = new Object()

suppDocs["supplement A"] = o = new Object()
o.windowName = "supplementA"
o.rl = "ws-8970-size-supA.html"
o.flags = "toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no"
o.width = 450
o.height = 290
o.resizableNSCludge = false

suppDocs["measurement converter tool"] = o = new Object()
o.windowName = "tool"
o.rl = "../tools/convert-length.html"
o.flags = "toolbar=yes,location=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes"
o.width = 630
o.height = null
o.resizableNSCludge = true

suppDocs["PM0047"] = o = new Object()
o.windowName = "pdf"
o.rl = "../brochures/grease/remp1.pdf"
o.flags = "toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes"
o.width = 600
o.height = null
o.resizableNSCludge = true

suppDocs["PM0222"] = o = new Object()
o.windowName = "pdf"
o.rl = "../??"
o.flags = "toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes"
o.width = 600
o.height = null
o.resizableNSCludge = true

suppDocs["rep guide"] = o = new Object()
o.windowName = "jrsFrameset"
o.rl = "../reps.htm"
o.flags = "toolbar=yes,location=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes"
o.width = 630
o.height = null
o.resizableNSCludge = true

var p //* p == pathsNavCludge
var EFL = EventFunctionListener

var procedure
var focusList
var fixtureSubsequentNode
var miscSubsequentNode
var supplementAShown

var data
var flds
var elementNewId = 0

var buttonRecent

var listItemHeight = 30
var contentUnderField = '<u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u>'
var contentTimesSign = '&nbsp;&times;'


function validateNumericFieldValue(evt) {
	return ( numberValidationExprGood.test(evt.value) ) &&
				(! numberValidationExprBad.test(evt.value) )
}
function validateNumericFieldChar(evt) {
	return numberCharFilterExpr[is.b].test(evt.character)
}

function initNumericField(id, initialValue) {
	var f = new FilteredField(getElement(id), null, initialValue,
				numericFieldInvalidCharErrStatusMsg)
	f.addEventListener(new EFL("EMValidateKeyup", testKeyup))
	f.addEventListener(new EFL("EMValidateKeydown", validateNumericFieldChar))
	f.addEventListener(new EFL("EMValidate", validateNumericFieldValue))
	f.addEventListener(new EFL("EMChange", handleFieldExit, f))
	focusList.add(f)
	return f
}

function initRadioField(ids, initialValue) {
	var fes = new Array()
	var i, f

	for (i = ids.length -1; i >= 0; i--) {
		fes[i] = getElement(ids[i])
	}
	f = new RadioField(fes, null, initialValue)
	f.addEventListener(new EFL("EMChange", handleFieldExit, f))
	focusList.add(f)
	return f
}

function initManagedField(id, initialValue) {
	var f = new ManagedField(getElement(id), null, initialValue)
	f.addEventListener(new EFL("EMValidateKeyup", testKeyup))
	f.addEventListener(new EFL("EMChange", handleFieldExit, f))
	focusList.add(f)
	return f
}

function initCheckboxField(id, initialValue) {
	var f = new CheckboxField(getElement(id), null, initialValue)
	f.addEventListener(new EFL("EMChange", handleFieldExit, f))
	focusList.add(f)
	return f
}

function initViewerField(id) {
	return getElement(id, p)
}

function initButton(id, focusIndex) {
	var b = new ManagedButton(getElement(id), null)
	b.addEventListener(new EFL("EMChange", handleFieldExit, b))
	b.addEventListener(new EFL("EMChange", setButtonRecent))
	focusList.addInsert(focusIndex, b)
	return b
}

function getRecommendElements() {
	var i
	var suf = new Array("A", "B", "C", "D", "E", "F")
	var a = new Array()
	for (i = suf.length - 1; i >= 0; i--) {
		a[i] = getElement("step8Field2"+ suf[i], p)
	}
	return a
}

function setButtonRecent() {
	buttonRecent = true
	setTimeout(clearButtonRecent, buttonRecentDelay)
	return true
}
function clearButtonRecent() {
	buttonRecent = false
}

function handleFieldExit(evt, arg) {
	var focusNextId = focusList.indexOf(arg) + 1
	switch (arg) {
		case flds.fixtureAdd:
			flds.s2f1.focus()
		break
		case flds.s4f0: case flds.s3f0:
			switch (flds.s4f0.selectedIndex) {
				case 0: flds.s4f1.focus(); break
				case 1: flds.s4f2.focus(); break
				case 2: flds.s4f3.focus(); break
			}
		break
		case flds.s4f1: case flds.s4f2: case flds.s4f4:
			flds.miscDescription.focus()
		break
		case flds.miscAdd:
			flds.s7f0.focus()
		break
		default:
			if (focusNextId < focusList.size()) {
				focusList.get(focusNextId).focus()
			} else if (is.ns && is.v<5) {
				focusList.get(0).focus()
			}
		break
	}
	return true
}

function testKeyup(evt) {
	return !((evt.character == String.fromCharCode(13)) && buttonRecent)
}

function getBlock(cssClassId, content) {
	return '<div class="'+ cssClassId +'">'+ content +'</div>'
}

function prepNumber(n) {
	var str
	str = formatNumber( Math.round( numberRoundingFactor *
				n ) / numberRoundingFactor, numberFormat )
	return (str == "0")? "" : str
}

function addMisc() {
	var e, pv, me, remId
	var miscs = data.miscs
	var m = new Object()
	var str = ""
	var d0
	
	with (flds) {
		m.description = miscDescription.getValue()
		m.qty = parseFloat(miscQty.getValue())
		m.rate = parseFloat(miscRate.getValue())
	}
	m.contrib = m.rate * m.qty
	data.contribMisc += m.contrib
	data.contrib += m.contrib

	remId = "miscRem"+ elementNewId++

	str += getBlock("miscBlk0", contentUnderField + contentUnderField)
	str += getBlock("miscBlk0", m.description)
	str += getBlock("miscBlk1", "<u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u>")
	str += getBlock("miscBlk1", m.qty)
	str += getBlock("miscBlk1A", contentTimesSign)
	str += getBlock("miscBlk2", contentUnderField)
	if (m.rate > 0) str += getBlock("miscBlk2", m.rate)
	str += getBlock("miscBlk3", contentUnderField)
	str += getBlock("miscBlk3", prepNumber(m.contrib))
	str += getBlock("miscBlk3A", "GPM")
	str += '<div class="miscBlk4"><input id="'+ remId
				+'" type="button" class="buttonStyle" value="Remove" /></div>'

	e = window.document.createElement("DIV")
	e.innerHTML = str
	
	if (is.ie && (is.p == "mac") && (is.v < 5.5)) {
		// This cludge causes IE 5 for Mac to shift elements.
		d0 = window.document.createElement("DIV")
		d0.innerHTML = ""
		e.className = "miscItemNSCludge"
		flds.miscListNode.appendChild(e, listItemHeight)
		flds.miscListNode.appendChild(d0, 0)
	
	} else if (is.ns && (is.v <= 5) ) {
		e.className = "miscItemNSCludge"
		flds.miscListNode.appendChild(e, listItemHeight)
	
	} else {
		e.className = "miscItem"
		flds.miscListNode.insertBefore(e, miscSubsequentNode)
	}
	
	m.e = e
	miscs.add(m)
	m.button = initButton(remId, miscListFocusIndexInitialOffset + data.fixtures.size() + miscs.size())
	m.button.addEventListener( new EFL("EMChange", removeMisc, m) )

	scheduleRefresh()
	return true
}


function removeMisc(evt, arg) {
	var m = arg
	var miscs = data.miscs

	if ( (is.ns && (is.v <= 5)) || (is.ie && (is.p == "mac") && (is.v < 5.5)) ) {
		flds.miscListNode.removeChild(m.e, -listItemHeight)
	} else {
		flds.miscListNode.removeChild(m.e)
	}
	data.contribMisc -= m.contrib
	data.contrib -= m.contrib
	miscs.remove(miscs.indexOf(m))
	focusList.remove(focusList.indexOf(m.button))

	scheduleRefresh()
	return true
}

function addFixture() {
	var e, remId
	var fixtures = data.fixtures
	var f = new Object()
	var str = ""
	var d0

	with (flds) {
		f.description = fixtureDescription.getValue()
		f.qty = parseFloat(fixtureQty.getValue())
		f.width = parseFloat(fixtureWidth.getValue())
		f.length = parseFloat(fixtureLength.getValue())
		f.depth = parseFloat(fixtureDepth.getValue())
	}

	//* calculate contribution of the fixture
	f.volume = (f.width * f.length * f.depth)
	if (f.volume < 0) f.volume = 0
	f.capacity = f.qty * f.volume / 231
	if (f.capacity < 0) f.capacity = 0

	data.fixtureCapacity += f.capacity

	remId = "fixtureRem"+ elementNewId++
	str += getBlock("fixtureBlk0", contentUnderField + contentUnderField)
	str += getBlock("fixtureBlk0", f.description)
	str += getBlock("fixtureBlk1", "<u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u>")
	str += getBlock("fixtureBlk1", f.qty)
	str += getBlock("fixtureBlk2", contentUnderField)
	if (f.width > 0) str += getBlock("fixtureBlk2", f.width)
	str += getBlock("fixtureBlk2A", contentTimesSign)
	str += getBlock("fixtureBlk3", contentUnderField)
	if (f.length > 0) str += getBlock("fixtureBlk3", f.length)
	str += getBlock("fixtureBlk3A", contentTimesSign)
	str += getBlock("fixtureBlk4", contentUnderField)
	if (f.depth >0 ) str += getBlock("fixtureBlk4", f.depth)
	str += getBlock("fixtureBlk4A", "=")
	str += getBlock("fixtureBlk5", contentUnderField)
	str += getBlock("fixtureBlk5", prepNumber(f.volume))
	str += getBlock("fixtureBlk5A", 'in<span class="sup">3</span> &times; Qty &divide; 231')
	str += getBlock("fixtureBlk6", contentUnderField)
	str += getBlock("fixtureBlk6", prepNumber(f.capacity))
	str += getBlock("fixtureBlk6A", "gal")
	str += '<div class="fixtureBlk7"><input id="'+ remId +
				'" type="button" class="buttonStyle" value="Remove" /></div>'

	e = window.document.createElement("DIV")
	e.innerHTML = str
	
	if (is.ie && (is.p == "mac") && (is.v < 5.5)) {
		// This cludge causes IE 5 for Mac to shift elements.
		d0 = window.document.createElement("DIV")
		d0.innerHTML = ""
		e.className = "fixtureItemNSCludge"
		flds.fixtureListNode.appendChild(e, listItemHeight)
		flds.fixtureListNode.appendChild(d0, 0)
	
	} else if ( is.ns && (is.v <= 5) ) {
		e.className = "fixtureItemNSCludge"
		flds.fixtureListNode.appendChild(e, listItemHeight)
		
	} else {
		e.className = "fixtureItem"
		flds.fixtureListNode.insertBefore(e, fixtureSubsequentNode)
	}
	
	f.e = e
	fixtures.add(f)
	f.button = initButton(remId, fixtureListFocusIndexInitialOffset + fixtures.size())
	f.button.addEventListener( new EFL("EMChange", removeFixture, f) )

	scheduleRefresh()
	return true
}

function removeFixture(evt, arg) {
	var f = arg
	var fixtures = data.fixtures
	
	if ( (is.ns && (is.v <= 5)) || (is.ie && (is.p == "mac") && (is.v < 5.5)) ) {
		flds.fixtureListNode.removeChild(f.e, -listItemHeight)
	} else {
		flds.fixtureListNode.removeChild(f.e)
	}
	data.fixtureCapacity -= f.capacity
	fixtures.remove(fixtures.indexOf(f))
	focusList.remove(focusList.indexOf(f.button))

	scheduleRefresh()
	return true
}

function scheduleRefresh() {
	setTimeout("refresh()", 0)  // The quoted syntax is required to satisfy IE 5 for Mac.
	return true
}

function refresh() {
	with (flds) {
		s8f2.setValue(0)
		s1Af0.innerHTML = prepNumber(data.fixtureCapacity)
		s2f0.innerHTML = prepNumber(data.fixtureCapacity)
		data.fixtureDrainDownPeriod = parseFloat(s2f1.getValue())
		data.contribFixture = data.fixtureCapacity * .75 / data.fixtureDrainDownPeriod
		data.contrib = data.contribFixture
		s2f2.innerHTML = prepNumber(data.contrib)
		data.contribFloorSink = parseFloat(s3f0.getValue()) * 4.0
		data.contrib += data.contribFloorSink
		s3f1.innerHTML = prepNumber(data.contribFloorSink)
		data.dishwasherMode = s4f0.selectedIndex
		switch (data.dishwasherMode) {
			case 0:
				data.contribDishwasher = parseFloat(s4f1.getValue())
				s4f2.setValue("0", true)
				s4f3.setValue("0", true)
				s4f4.setValue("0", true)
			break
			case 1:
				data.contribDishwasher = parseFloat(s4f2.getValue()) / 60
				s4f1.setValue("0", true)
				s4f3.setValue("0", true)
				s4f4.setValue("0", true)
			break
			case 2:
				data.contribDishwasher = parseFloat(s4f3.getValue()) * parseFloat(s4f4.getValue()) / 60
				s4f1.setValue("0", true)
				s4f2.setValue("0", true)
			break
		}
		data.contrib += data.contribDishwasher
		s4f5.innerHTML = prepNumber(data.contribDishwasher)

		data.contrib += data.contribMisc
		s6f0.innerHTML = prepNumber(data.contrib)

		data.contribEquipment = data.contrib
		
		if (s7f0.getValue()) {
			data.contribMenu = data.contrib * .25
			s7f1.innerHTML = prepNumber(data.contrib)
		} else {
			data.contribMenu = 0
			s7f1.innerHTML = ""
		}
		s7f2.innerHTML = prepNumber(data.contribMenu)

		if (s7f3.getValue()) {
			data.contribHours = data.contrib * .25
			s7f4.innerHTML = prepNumber(data.contrib)
		} else {
			data.contribHours = 0
			s7f4.innerHTML = ""
		}
		s7f5.innerHTML = prepNumber(data.contribHours)

		data.contrib += (data.contribMenu + data.contribHours)
		s8f0.innerHTML = prepNumber(data.contrib)
	}

	if (data.contrib > 75) {
		if (!supplementAShown) {
			supplementAShown = true
			openDocument("supplement A")
		}
	} else {
		supplementAShown = false
	}
	
	return true
}

function recommend() {
	var v = data.contrib
	var ret = true
	var idx, ret
	if (v <= 0) idx = 0
	else if (v <= 20) idx = 1
	else if (v <= 35) idx = 2
	else if (v <= 50) idx = 3
	else if (v <= 75) idx = 4
	else {
		supplementAShown = true
		openDocument("supplement A")
		idx = 5
		ret = false
	}
	flds.s8f2.setValue(idx)
	data.recommend = idx
	return ret
}

function openDocument(id) {
	var doc = suppDocs[id]
	var flags = doc.flags
	
	if (is.ns && (is.v <= 5)) {
		if (doc.resizableNSCludge) {
			window.open(doc.rl, doc.windowName)
		} else {
			window.open(doc.rl, doc.windowName, flags +",width="+ 
						doc.width +",height="+ doc.height)
		}
	} else {
		if (doc.width != null) flags += ",width="+ doc.width
		if (doc.height != null) flags += ",height="+ doc.height
		window.open(doc.rl, doc.windowName, flags)
	}
	
}

function init() {
	var o, e
	
	focusList = new Vector()
	data = new Object()
	flds = new Object()
	
	supplementAShown = false
	
	data.fixtures = new Vector()
	data.miscs = new Vector()
	data.fixtureCapacity = 0
	data.contribFloorSink = 0
	data.contribDishwasher = 0
	data.contribMisc = 0
	data.contribMenu = 0
	data.contribHours = 0
	data.contrib = 0

	flds.jobName = initManagedField("headJobName", "")
	flds.jobRep = initManagedField("headJobRep", "")
	flds.preparerName = initManagedField("headPreparerName", "")
	flds.preparerEmployer = initManagedField("headPreparerEmployer", "")
	flds.preparerPhone = initManagedField("headPreparerPhone", "")
	flds.preparerEmail = initManagedField("headPreparerEmail", "")

	flds.fixtureDescription = initManagedField("fixtureDescription", fixtureDescriptionDefault)
	flds.fixtureQty = initNumericField("fixtureQty", "1")
	flds.fixtureWidth = initNumericField("fixtureWidth", "0")
	flds.fixtureLength = initNumericField("fixtureLength", "0")
	flds.fixtureDepth = initNumericField("fixtureDepth", "0")
	flds.fixtureAdd = o = initButton("fixtureAdd", focusList.size())
	o.addEventListener(new EFL("EMChange", addFixture))
	if ( (is.ns && (is.v <= 5)) || (is.ie && (is.p == "mac") && (is.v < 5.5)) ) {
		e = getElement("fixtureListNSCludge")
		flds.fixtureListNode = new VerticalAppendRemoveBlock(e, e, 0)
	} else {
		fixtureSubsequentNode = getElement("step1A")
		flds.fixtureListNode = getElement("worksheet")
	}

	flds.s1Af0 = initViewerField("step1AField0")

	flds.s2f0 = initViewerField("step2Field0")
	flds.s2f1 = o = initNumericField("step2Field1", fixtureDrainDownPeriodDefault)
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s2f2 = initViewerField("step2Field2")

	flds.s3f0 = o = initNumericField("step3Field0", "0")
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s3f1 = initViewerField("step3Field1")

	flds.s4f0 = o = initRadioField(new Array("step4Field0A", "step4Field0B", "step4Field0C"), 0)
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	flds.s4f1 = o = initNumericField("step4Field1", "0")
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s4f2 = o = initNumericField("step4Field2", "0")
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s4f3 = o = initNumericField("step4Field3", "0")
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s4f4 = o = initNumericField("step4Field4", "0")
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	o.addEventListener(new EFL("EMChangeOnBlur", scheduleRefresh))
	flds.s4f5 = initViewerField("step4Field5")

	flds.miscDescription = initManagedField("miscDescription", miscDescriptionDefault)
	flds.miscQty = initNumericField("miscQty", "1")
	flds.miscRate = initNumericField("miscRate", "0")
	flds.miscAdd = o = initButton("miscAdd", focusList.size())
	o.addEventListener(new EFL("EMChange", addMisc))
	if ( (is.ns && (is.v <= 5)) || (is.ie && (is.p == "mac") && (is.v < 5.5)) ) {
		e = getElement("miscListNSCludge")
		flds.miscListNode = new VerticalAppendRemoveBlock(e, e, 0)
	} else {
		miscSubsequentNode = getElement("step6")
		flds.miscListNode = getElement("worksheet")
	}

	flds.s6f0 = initViewerField("step6Field0", "step6Blk0")

	flds.s7f0 = o = initCheckboxField("step7Field0", false)
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	flds.s7f1 = initViewerField("step7Field1")
	flds.s7f2 = initViewerField("step7Field2")
	flds.s7f3 = o = initCheckboxField("step7Field3", false)
	o.addEventListener(new EFL("EMChange", scheduleRefresh))
	flds.s7f4 = initViewerField("step7Field4")
	flds.s7f5 = initViewerField("step7Field5")

	flds.s8f0 = initViewerField("step8Field0")
	flds.s8f1 = o = initButton("step8Field1", focusList.size())
	o.addEventListener(new EFL("EMChange", recommend))
	flds.s8f2 = new ElementFromArrayViewer(getRecommendElements())
	flds.s8f2.setValue(0)
	
	flds.s9f0 = o = initButton("step9Field0", focusList.size())
	o.addEventListener(new EventMethodListener("EMChange", window, "print"))
	
	getElement("wait").style.visibility = "hidden"
	getElement("worksheet").style.visibility = "visible"
	focusList.get(0).focus()
}

/**
	"page logic" }
**/

