// magic.js
//--|
// Copyright © 2000-2001, Hodgson Myers Associates Ltd.
// All Rights Reserved
// Licences may be purchased separately or obtained as part of a training package.
// Licencees using this script may use it in as many pages and sites as they wish.
// Licencees may not otherwise distribute this script or the associated documentation.
// This copyright block must appear in its entirety.
//
// Enquiries to Rodney Myers, Director
// Hodgson Myers Associates Ltd   P O Box 397  Oxford OX1 4AF  United Kingdom
// Tel 01865 200025
// Fax 01865 726545
// email rodney@aflyingstart.net
// http://www.aflyingstart.net
//--|

// History after first release to December 2000 course participants
// Dec 16
// Radio buttons may be unchecked, and are verified
// First examples of function customAddData. form object passed. call to setProductData(pkey) moved up.
// Jan 15 2001
// debugged calls for pkey
// Jan 18
// experimental multi version begun
// Jan 22
// outsideSystemHandler variable introduced to lod364.js in 3.6.4C, boss.js and multiboss.js
// with respective values of 1,2,3 buy() and multibuy() functions check this value.
// March 13 amendments to multibuy1() to prevent additions to basket of items preceding items with omissions in form

// April 19 2001 Modified isForm() and added BrowserCheck().
// Both functions and the two lines calling them may be deleted
// April 20 2001 Modified multibuy1() to make calls to newchoice outside system with MULTIBOSS loaded
// May 16 Support for checkboxes with price additions in their value  using $caption
// August Support in multibuy forms for common inputs, names end _common  eg Fabric_common
// Sept 04 qlock_common supported in multibuy forms
// Sept 05 checkbox and radio button support for $ prefix extended with ; delimited values option
// Oct 02 Trailing zeroes bug fixed. See message of this date in afs_magic
// --|

var outsideSystemHandler=0;
var ProductName,ProductRef,Price,Weight,TaxCode,VARSLOT2;
var productData=new Array();

var message; // To display if form is not passed OK (Set in function InputOK)
// Quantity related variables
var Qty,Inc,Min,Max;
var pkey;
var tab="\t";
var newline="\n";
var CRLF=unescape("%0D%0A");
var OK,multiQtyFound,productErrors;
var Add2Price,Add2Ref,VARSLOT1;
var multibossOp=false;
// for column pricing
var colPbar="|";var colPsemi=";";

function setvars(){
if(window.reValue){reValue();} // uses cookie restoration if cookie script present.
}

function multibuy(form){
     if(top.INSASS || outsideSystemHandler >=3){multibuy1(form);}
else if(outsideSystemHandler==2){if(!http_mode()){alert("MISSING COMPONENT\n\nmultiboss.js is required to handle\nthis page outside Shop@ssistant system.");}else{nosass();}}
else if(outsideSystemHandler==1){nosass();}
else if(outsideSystemHandler==0){alert("No shopping system loaded");}
}

function multibuy1(form){
var qe;
var formErrors="";
var addchoice = new Array();
multiQtyFound=false; OK=true;
var cboxqty=false; // new July 31 2001
setProductArrayData();
for (var pkey in productData)
	{

	setQdefaults(form);
	Add2Price=0;Add2Ref="";
	if(form["qty_"+pkey])
		{
		qe=form["qty_"+pkey];
		// alert(pkey); //!!
		if(qe.type=="checkbox"){cboxqty=true;} // new July 31 2001
		if(qe.type=="text"){Qty=1*(0+qe.value);}
		else if(qe.type=="checkbox" && qe.checked){Qty=1;}
		else if(qe.type=="select-one"){Qty=lv(qe);}
		var QVAL;
			 if(eval("form.qlock_"+pkey))   {QVAL=-Qty;}
			 if(form.qlock_common)   {QVAL=-Qty;}
		else if(eval("form.noremove_"+pkey)){QVAL=noremove(Qty);}
		else                  {QVAL=top.revQfix(Qty,Inc,Min,Max);}

		if(Math.abs(Qty)>0)
			{
			multiQtyFound=true;
			VARSLOT1=getDataforPkey(form,pkey);
			VARSLOT1+=VARSLOT1.length>0?CRLF:"";
			VARSLOT1+=getDataforPkey(form,'common');
			VARSLOT1=stripTrailingCRLF(VARSLOT1);
			// end of new code
			if(OK)
				{
				multiSetProductData(pkey);
		    	if(typeof(Price)=="number") { Price+=Add2Price; }
				else if(typeof(Price)=="string" && Price.indexOf(colPbar)>-1){Price=fix_price_string(Price,Qty)}
				else if(typeof(Price)=="string" && Price.indexOf("[")>-1){/* do nothing */}
				else if (Add2Price>0){alert("Error : Cannot Add to Price")}
				addchoice[pkey]=new addObj(ProductName,ProductRef+Add2Ref,VARSLOT1,VARSLOT2,Price,QVAL,Weight,TaxCode)
				}
			else
				{
				productErrors=(productErrors.length>0) ? "\n"+productData[pkey].ProductName+productErrors+"\n" : "";
				formErrors += productErrors;
				}
			}
		}
	}

if(multiQtyFound && OK)
	{
	if (top.INSASS) { makeNewChoices(addchoice); top.reviewbasket(true); }
	else            { if(multBossStartUp){makeNewChoices(addchoice);multBossStartUp();}else{"MULTI-BOSS ADD-ON NEEDED TO USE OUTSIDE SYSTEM"}   }
	}
else if(!multiQtyFound)
	{
	var piqmsg=cboxqty?"Please check the box next to each item you wish buy.":"Please input a quantity for each item you wish buy.";
	alert(piqmsg); // new July 31 2001
	}
else if(!OK){alert("MISSING INPUTS\n"+formErrors);}
top.multiproduct_end();
}//

function addObj(D,R,V1,V2,P,Q,W,T){
this.D=D; this.R=R; this.V1=V1; this.V2=V2; this.P=P; this.Q=Q; this.W=W; this.T=T;
this.addNewChoice=addNewChoice;
}//

function makeNewChoices(addchoice){
top.multiproduct_start();
for(var pkey in addchoice){addchoice[pkey].addNewChoice();}
top.multiproduct_end();
}//

function addNewChoice() { // method of addObj
top.newchoice(this.D,this.R,this.V1,this.V2,this.P,this.Q,this.W,this.T);
}


function getDataforPkey(form,pkey) {
var last=form.elements.length;
var ret="";
var e,str,caption;
productErrors="";
for(var i=0 ; i<last; i++)
 {
 e=form.elements[i];str="";
 multiCheckQfields(e,pkey);
 if(elementBelongs(e,pkey))
 	{
 	caption=fixCaptionMulti(e,pkey);
 	//!! alert(pkey+"\n"+caption);
	if(e.type=="select-one")
	 	{
	 	if(notOptional(e) && e.selectedIndex==0){OK=false;productErrors+="\n\t"+caption}
		if(e.name.charAt(0)=="$" || e.name.substring(0,2)=="_$")
			{Add2Price+=1*lv(e);}
		if(e.name.charAt(0)=="#" || e.name.substring(0,2)=="_#")
			{Add2Ref+=lv(e);}
		str = stripUnderscores(lt(e));
		} // could use top.listtext()

 	if(e.type=="text")
 		{
	 	if(notOptional(e) && e.value.length==0){OK=false;productErrors+="\n\t"+caption}
 		str=e.value;
 		}

 	if(e.type=="textarea")
 		{
	 	if(notOptional(e) && e.value.length==0){OK=false;productErrors+="\n\t"+caption}
 		str=(e.value.length>0)?CRLF+e.value:"";
 		}

	 if((e.type=="checkbox" ) && e.checked)
	 	{
	 	if(e.name.charAt(0)=="$"){Add2Price+=1*e.value;str="YES"}
	 	else{str=e.value;str=(str.length==0 || str=="checkbox")?"YES":str;}
	 	}
	 if((e.type=="radio") && e.checked){str=e.value;}


 if(str.length>0)
   {
	caption=fixCaption(caption);
    ret+=caption.bold() + " : " +str+CRLF;
   }

 	}
 }

return(ret);
}

function notOptional(e){return(e.name.charAt(0)!="_");}

function fixCaptionMulti(e,pkey){
ret=e.name.substring(0,e.name.lastIndexOf("_"+pkey));

return(fixCaption(ret));
}


function elementBelongs(e,pkey){
var n=e.name;
var ret=n.substr(0,3)!="qty";
if(ret)
	{
	p=n.lastIndexOf("_"+pkey);
	ret= (p==(n.length-pkey.length-1));
	}
return(ret);
}

function buy(form){

if(form.multibuy)
	{ multibuy(form); }
else
	{ onebuy(form); }
return(false); //!!??
}

function onebuy(form){
     if(top.INSASS || outsideSystemHandler >=2){onebuy1(form);}
else if(outsideSystemHandler==1){nosass();}
else if(outsideSystemHandler==0){alert("No shopping system loaded");}
}

function onebuy1(form){
pkey=null;Add2Price=0;Add2Ref="";
var VARSLOT1;
message="";
var F_ok=InputOK(form);

if( F_ok )
	{
	VARSLOT1 = stripTrailingCRLF(getInputFrom(form));
	if(typeof setProductArrayData == "function"){setProductArrayData();multiSetProductData(pkey)}else{setProductData(pkey);}
    var QVAL;
         if(form.qlock)   {QVAL=-Qty;}
    else if(form.noremove){QVAL=noremove(Qty);}
    else                  {QVAL=top.revQfix(Qty,Inc,Min,Max);}
    if(typeof(Price)=="number"){Price+=Add2Price;}
	else if(typeof(Price)=="string" && Price.indexOf(colPbar)>-1){Price=fix_price_string(Price,Qty)}
	else if(typeof(Price)=="string" && Price.indexOf("[")>-1){/* do nothing */}
    else if (Add2Price>0){alert("Error : Cannot Add to Price\nPrice is not numeric")}
	top.newchoice(ProductName,ProductRef+Add2Ref,VARSLOT1,VARSLOT2,Price,QVAL,Weight,TaxCode)
	}
else
	{alert(message);}
}

function stripTrailingCRLF(str){
	while(str.length>2 && "!$%0D!$%0A".indexOf("!$"+escape(str.charAt(str.length-1)))>-1)
		{
		str=str.substring(0,str.length-1)
		}


return(str);
}

function noremove(V){return(""+-1*parseFloat(V))+"!";}

function setQdefaults(form){// Defaults for Quantity related variables
Qty=(form.multibuy)?0:1; Min=1; Max=999999; Inc=1; }

function checkQfields(e){
var ret=false
 		if(e.type=="hidden" && e.name.substring(0,4).toLowerCase()=="pkey"){pkey=e.value;ret=true;}
 else	if(hQfld(e,'increment')){Inc=e.value;ret=true;}
 else	if(hQfld(e,'minimum')  ){Min=e.value;ret=true;}
 else	if(hQfld(e,'maximum')  ){Max=e.value;ret=true;}
 else	if(e.type=="text" && e.name.substring(0,3).toLowerCase()=="qty"){Qty=e.value;ret=true;}
 else	if(e.type=="select-one" && e.name.substring(0,3).toLowerCase()=="qty"){Qty=lv(e);ret=true;}
 else	if(e.name.substring(0,2)=="__" ){ret=true;}
return(ret);
}

function hQfld(e,tag){return(e.type=="hidden" && e.name.toLowerCase()==tag);}


function multiQfix(qe){
var form=qe.form;var e;
var pkey = qe.name.substring(qe.name.lastIndexOf("_")+1);
setQdefaults(form);

for(var i=0 ; i<form.elements.length; i++)
 {
 e=form.elements[i];
 multiCheckQfields(e,pkey);
 }

top.qty_fix(qe,Inc,Min,Max);
}

function multiCheckQfields(e,pkey){
if(mhQfld(e,pkey,'increment')){Inc=e.value;}
if(mhQfld(e,pkey,'minimum')  ){Min=e.value;}
if(mhQfld(e,pkey,'maximum')  ){Max=e.value;}
}

function mhQfld(e,pkey,tag){return(e.type=="hidden" && e.name==tag+"_"+pkey);}


function magicQfix(qe){
var form=qe.form;var e;
setQdefaults(form);
for(var i=0 ; i<form.elements.length; i++)
 {
 e=form.elements[i];
 checkQfields(e);
 }
top.qty_fix(qe,Inc,Min,Max);
}

function show__Total(form){
var e,N;
Add2Price=0;
for(var i=0 ; i<form.elements.length; i++)
 {
 e=form.elements[i];
 checkQfields(e);
  if(e.type=="select-one")
  	{
	N=e.name;
	if(N.charAt(0)=="$" || N.charAt(1)=="$" )
		{Add2Price+=1*lv(e);}
	}
 }
setProductData(pkey);


if(form.__Total)
	{
    if(typeof(Price)=="number"){Price+=Add2Price}else{alert("ERROR : Price is not a number!")}
 	form.__Total.value=top.MC.MCPrice(top.adjust(Price));
	}
else
	{
	alert("Form needs a text type input named __Total\nAnd that's TWO leading underscores");
	}
}


function getInputFrom(form,last){
var last=form.elements.length;
var extra=" : extra cost included"; //
setQdefaults(form);
var ret="";
var e,str;
var caption;
for(var i=0 ; i<last; i++)
 {
 e=form.elements[i];str="";
 caption=e.name;
 // remove leading underscore if any
 caption=(caption.charAt(0)=="_") ? caption.substring(1):caption;
 if(checkQfields(e)){continue;}


 if(e.type=="text"){str=e.value;}
 if(e.type=="textarea"){str=(e.value.length>0)?CRLF+e.value:"";}
 if(e.type=="select-one")
 	{
	if(caption.charAt(0)=="$")
		{Add2Price+=1*lv(e);}
	if(caption.charAt(0)=="#")
		{Add2Ref+=lv(e);}
	str = stripUnderscores(lt(e));
	} //

 if(e.type=="radio" && e.checked)
 	{
	if(caption.charAt(0)=="$") //!! Sept 04
		{
		var bits=e.value.split(";")
		Add2Price+=1*bits[0];
		var priceAdded=(top.INSASS)?" @ "+top.MC.MCPrice(1*bits[0]):"";
		str=bits[1]
		str+=(1*bits[0]>0)?extra+priceAdded:"";
		}
	else{ str=e.value; }
 	}

 if(e.type=="checkbox" && e.checked)
 	{
	if(e.name.charAt(0)=="$")
		{
		if(e.value.indexOf(";")>-1)
			{
			var bits=e.value.split(";")
			Add2Price+=1*bits[0];
			str=bits[1];
			var priceAdded=(top.INSASS)?" @ "+top.MC.MCPrice(1*bits[0]):"";
			str+=(1*bits[0]>0)?extra+priceAdded:"";
			}
		else{Add2Price+=1*e.value;str="YES"+extra}
		}
	else{str=e.value;str=(str.length==0 || str=="checkbox")?"YES":str;}
 	}


 if(str.length>0)
   {
	  if(e.type=="select-one")
	  {
	    At_index=str.indexOf("@");
		ret+=str.substring(0,At_index) + CRLF;
	  }
	  else
	  {
		caption=fixCaption(caption);
		ret+=caption.bold() + " : " +str+CRLF;
	  }
   }
 }

if(window.customAddData){customAddData(form)}
return(ret);
}


function stripUnderscores(str){
while(str.charAt(0)=="_"){str=str.substring(1);}
return(str);
}


// function to be used for verifying form, if needed
function InputOK(form){
var last=form.elements.length;
var ret=true;
var e; var str="";var custom_str="";var rb,rbv; var previous_rbname="+++";
var caption;
var select_not_valid=false;
for(var i=0 ; i<last; i++)
 {
 e=form.elements[i];
 // Text fields having names STARTING with underscore need not be filled
 // SELECTS having names STARTING with underscore may rest on option zero
 if(e.name.charAt(0)=="_"){continue;}
 if(checkQfields(e)){continue;}
 if(e.name==previous_rbname){continue;}
 else  if( (e.type=="text" || e.type=="textarea")  && e.value.length==0)
 	{
	ret=false;
	caption=fixCaption(e.name);
	str+=tab+caption+newline
	}
 else  if( e.type=="select-one"   && e.selectedIndex==0)
 	{
	ret=false;
	caption=fixCaption(e.name);
	str+=tab+caption+newline
	select_not_valid=true;
	}
 else  if( e.type=="radio")
 	{
	rb=eval("form."+e.name);
	rbv=getRadioVal(rb);
	if(rbv.length==0)
		{
		ret=false;
		caption=fixCaption(e.name);
		str+=tab+caption+newline;
		previous_rbname=e.name
		}
	}
 }


if(window.customVerify){
	custom_str=customVerify(form);
	ret=(ret)?custom_str.length==0:ret;
// return value, if currently true, depends on length of custom_str
//               if false, it remains false
}
// custom message starting with newline overrides main message
// otherwise it just adds to the end

if(custom_str.length>0 && "%0A%0D".indexOf(escape(custom_str.charAt(0))) >-1)
	{
	message=custom_str;
	}
else
	{
	if(select_not_valid==true)
	{
		message="Please choose an item from the selection box";
	}
	else
	{
		message="Please attend to :\n"+str+custom_str;
	}
	}

return(ret);
}

function fixCaption(ret){
   // Remove trailing digits
   while("0123456789".indexOf(ret.charAt(ret.length-1))>-1){ret=ret.substring(0,ret.length-1);}
   // Strip trailing hash that protects required numbering
   if(ret.charAt(ret.length-1)=="#"){ret=ret.substring(0,ret.length-1);}

   // remove leading underscore if any
   ret=(ret.charAt(0)=="_") ? ret.substring(1):ret;

   // remove leading Dollar if any
   ret=(ret.charAt(0)=="$") ? ret.substring(1):ret;
   // remove leading hash if any
   ret=(ret.charAt(0)=="#") ? ret.substring(1):ret;

   // convert $ to slash
   ret=swapstring(ret,"$","/");
   // convert underscore to space
   ret=swapstring(ret,"_"," ");
return(ret);
}

function getRadioVal(rb){
var L=rb.length;var ret="";
for (var i = 0 ; i< L ; i++)
 { if(rb[i].checked) { ret=rb[i].value; break; } }
return(ret);
}


function swapstring(T,X,Y){T=""+T; var mark="É_É";var ret=""; if(Y.indexOf(X)>-1) { ret=swaps(T,X,mark); ret=swaps(ret,mark,Y); } else{ret=swaps(T,X,Y);} return(ret); }
function swaps(T,X,Y){ var P,n,l;l=X.length; while (T.indexOf(X)>-1){n=T.indexOf(X);P=T.substring(0,n)+Y+T.substring(n+l,T.length);T=P;} return(T);}
function setCk(){} // Stub - overwritten by function in cookie script if used.
function http_mode(){return("http"==(""+window.location).substring(0,4));}
function lv(L){return(L.options[L.selectedIndex].value);}
function lt(L){return(L.options[L.selectedIndex].text);}


// for Quantity inputs
function qty_fix(elem,Increment,qMin,qMax) {
var ev=elem.value;
ev=Math.abs(ev);
if(ev=="NaN"){ev=qMin;}
else if(ev<qMin){ev=qMin;}
else if(ev>qMax){ev=qMax;}
else if( (ev-qMin)/Increment != Math.ceil((ev-qMin)/Increment)){ev=1*qMin+Math.ceil((ev-qMin)/Increment)*Increment;}
elem.value=ev;
}//


function pObject(ProductName,ProductRef,Price,Weight,TaxCode,VARSLOT2){
this.ProductName = ProductName;
this.ProductRef = ProductRef;
this.Price = Price;
this.Weight = Weight;
this.TaxCode = TaxCode;
this.VARSLOT2 = VARSLOT2;
return(this);
}//

function multiSetProductData(pkey){
ProductName	= productData[pkey].ProductName;
ProductRef	= productData[pkey].ProductRef;
Price		= productData[pkey].Price;
Weight		= productData[pkey].Weight;
TaxCode		= productData[pkey].TaxCode;
VARSLOT2	= productData[pkey].VARSLOT2;
}//

// for column price support
function fix_price_string(Pstring,Q){
//Pstring breaks to break_mins|prices  break_mins & prices are xxx;yyy;zzz
if(Pstring.indexOf(colPbar)>-1){
var tmp=top.parser(Pstring,colPbar);var min=top.parser(tmp[1],colPsemi);
var prc=top.parser(tmp[2],colPsemi);
var n;for(n=min[0];n>0;n--){if(Q>=1*min[n]){break;}}
return(""+prc[n]+colPbar+tmp[1]+colPbar+tmp[2]);
}}


//// the remainder of this file may be deleted if not required

function isForm(){}


// BrowserCheck Object
function BrowserCheck() {
	var b = navigator.appName
	if (b.indexOf("Netscape")>-1){ this.b = "ns";}
	else if (b=="Microsoft Internet Explorer") this.b = "ie"
	else this.b = b
	this.version = navigator.appVersion
	this.v = parseInt(this.version)
	this.ns = (this.b=="ns" && this.v>=4)
	this.ns4 = (this.b=="ns" && this.v==4)
	this.ns5 = (this.b=="ns" && this.v==5)
	this.ie = (this.b=="ie" && this.v>=4)
	this.ie4 = (this.version.indexOf('MSIE 4')>0)
	this.ie5 = (this.version.indexOf('MSIE 5')>0)
	this.min = (this.ns||this.ie)
}
var is = new BrowserCheck();


//setTimeout("isForm()",4000);
