//CHECKJS  D:\js\jmol\applet\mscalc\mscalc.js 4/19/2005 6:46:48 AM

jsversion="6:14 AM 4/26/2006"
codebase="../"
jmoldefaults="width=400 height=400 "
jmolscript="rotate y 20;set picking distance"
Isotopes=new Array()
Elements=new Array()  //requires fullmass.js
Structure=new Array()
min2nd=2 //minimum % relative abundance resulting in multiple MS peaks flag
jmoltarget="jm"+(Math.random()+"").split(".")[1]
AllMasses=0//new Array()
MASSMIN=20
function createmolstructure(smolinfo){
mw=0
mf=""
molname=""

	//read a MOL file and create a data structure from it
        var n=0
//	var d=document.getElementById("molfile")
//	d.innerHTML="<pre>"+smolinfo+"</pre>"
	var S=smolinfo.split("\n")
	Structure.header=S[0]+"\n"+S[1]+"\n"+S[2]+"\n"+S[3]+"\n"
	Structure.footer=S[S.length-1]
	var Sline=S[3].split(" ")
	Structure.info=smolinfo
	Structure.natoms=parseInt(Sline[1])
	Structure.nbonds=parseInt(Sline[2])
	Structure.Bonds=new Array()
	Structure.Atoms=new Array()
	for(var i=1;i<=Structure.natoms;i++){
		var pt=3+i
		Structure.Atoms[i]=new Array()
		Structure.Atoms[i].Bonds=new Array()
		Structure.Atoms[i].sym=S[pt].substring(31,33).split(" ")[0]
		Structure.Atoms[i].lineinfo=S[pt]
		Structure.Atoms[i].color="CPK"
	}
	for(var i=0;i<Structure.nbonds;i++){
		var pt=4+Structure.natoms+i
		var s=S[pt]
		var a1=parseInt(s.substring(0,3))
		var a2=parseInt(s.substring(3,6))
		var bo=parseInt(s.substring(6,9))
		Structure.Bonds[Structure.Bonds.length]=[a1,a2,bo,s]
		Structure.Atoms[a1].Bonds[Structure.Atoms[a1].Bonds.length]=a2
		Structure.Atoms[a2].Bonds[Structure.Atoms[a2].Bonds.length]=a1
	}
	for(var i=1;i<=Structure.natoms;i++){
	        n=0
  	        for(var j=0;j<Structure.Atoms[i].Bonds.length;j++){
                        if(Structure.Atoms[Structure.Atoms[i].Bonds[j]].sym!="H")n++
                }
                Structure.Atoms[i].ntype=n
	}
}

function doatom(mess){

	//user clicked on the first atom of a pair
	//reading "Atom #1: .... #[a1]


	for(var i=1;i<=Structure.natoms;i++)Structure.Atoms[i].color="CPK"
	var S=mess.split("#")
	var a1=parseInt(S[2])

	var scmd=showmass(a1,0)
	showmolfile()
	sendscript(scmd)
}

function dodistance(mess){

	//user clicked on the second atom
	//reading "Distance: ...#[a1]...#[a2]

	var S=mess.split("#")
	var a1=parseInt(S[1])
	var a2=parseInt(S[2])
	var scmd=""
	if (a1==0 && a2==0){
		mf=getformula("all")
		mw=getmass("all")
		scmd+=';set echo top center;echo '+title.replace(/MS of /,"")+" M="+mw+";"
	}

	scmd+=showmass(a1,a2)
	showmolfile()
	sendscript(scmd)
}

function getapplet(path,src){

	//create the applet tag -- crude but effective

	var S=(src+"~"+src).split("~")
	molname=S[1]
	jmolscript+=';set echo top center;echo '+molname
	var s='\n<form name=info><applet name="'+jmoltarget+'" id="'+jmoltarget+'" code="JmolApplet"'
	s+='\ncodebase="'+codebase+'"'
	s+='\narchive="JmolApplet.jar"'
	+'\n'+jmoldefaults+' mayscript="true" />'
	+'\n<param name="progressbar"   value="true" />'
	+'\n<param name="messagecallback"   value="mymsg" />'
	+'\n<param name="pickcallback"   value="mypick" />'
	+'\n<param name="script"    value="load '+path+S[0]+';'+jmolscript+';show file" />'
	+'\n</applet>'
	+"<br>* after mass indicates other isotopes have &gt;"+min2nd+"% relative abundance"
	+"<br><input type=text size=30 name=cmd value='background white'><input type=button value=\"execute Jmol command\" onclick=\"sendscript(document.info.cmd.value)\">"
	+"<input type=button value=\"rotate x\" onclick=\"sendscript('rotate x 30')\">"
	+"</form>"+jsversion
	return s//.replace(/\</g,"<br>&lt;")
}

function getconnected(a1,a2,Tagged){

	//generate array Tagged of connected atoms to a1 not including a2
        //returns 0 if connection forms a loop
        var s=""
	var slist=""
        var B=new Array()
	var b=0
	if(a1==a2)return
	if(a2==0){
		Tagged[a1]=1
		return 1
	}
	B[0]=a1
	//for(var i=0;i<Structure.Atoms[a1].Bonds.length;i++)B[B.length]=Structure.Atoms[a1].Bonds[i]
        slist=";"+a1+";"
        for (var i=0;i<B.length;i++){
		var a=B[i]
		if(a!=a2 &&!Tagged[a]){
			Tagged[a]=1
			for(var j=0;j<Structure.Atoms[a].Bonds.length;j++){
                                b=Structure.Atoms[a].Bonds[j]
                     		if(b==a2 && a!=a1)return 0
                                s=";"+b+";"
			        if(slist.indexOf(s)<0){
			                B[B.length]=b
			                slist+=s
			        }
			}
		}
	}
	return 1
}

function getconnectedscript(a1,a2,color){

	// generate Jmol script for atoms connected to a1 but not including a2

	var isInitial=(a1==0 && a2==0)
	var Tagged=new Array()
	if(!getconnected(a1,a2,Tagged))return ""
	var s=""
	for(var i=1;i<Tagged.length;i++){
		if(Tagged[i]){
			s+=" or atomno="+i
			Structure.Atoms[i].color=color
		}
	}
	var scmd="select "+s.substring(4,s.length)+";color "+color+";"
	return scmd
}

function getformula(color){

	//combined formula of specific atom color

	var S=new Array()
	S["C"]=0
	S["H"]=0
	S["N"]=0
	S["O"]=0
	var sout=""
	var a=""
	for(var i=1;i<=Structure.natoms;i++){
		if(color=="all" || Structure.Atoms[i].color==color){
			a=Structure.Atoms[i].sym
			if(!S[a])S[a]=0
			S[a]++
		}
	}
	for(var i in S){
		if(S[i])sout+=i+(S[i]>1?S[i]:"")
	}
	return sout
}

function getmass(color){

	//sum mass of specific atom color

	var m=0
	var hasmultiple=0
	for(var i=1;i<=Structure.natoms;i++){
		if(color=="all"||Structure.Atoms[i].color==color){
			m+=massof(Structure.Atoms[i].sym)
			if(Elements[Structure.Atoms[i].sym].hasmultiple && !hasmultiple)hasmultiple=1
		}
	}
	return m+(hasmultiple?"*":0)
}

function massof(sym){
	return Elements[sym].AtomWt
}

function mymsg(m,mess){

	//message callback function

	var s=mess+""

	if (s.indexOf("ript")>=0)return

//	if(s.indexOf("#")<0)return
	//document.info.cmd.value=s
	if(s.indexOf("Atom #1")==0)doatom(s)
	if(s.indexOf("Distance")==0)dodistance(s)
	if(s.length>1000 || s.indexOf("END")>=0){
		createmolstructure(s)
		//alert("OK, now point to pairs of connected atoms. ")
		dodistance("0#0#0")
	}
}

function newElem(XXn,sym,relabund,exactmass){

 	//for reading elements in fullmass.js, which follows this js file

	if(!Elements[sym])Elements[sym]=new Array()
	if(relabund==100)Elements[sym].AtomWt=exactmass
	if(!Elements[sym].Isotopes)Elements[sym].Isotopes=new Array()
	Elements[sym].Isotopes[Elements[sym].Isotopes.length]=[relabund,exactmass]
	if(relabund<100 && relabund>=min2nd)Elements[sym].hasmultiple=1
}

function sendscript(scmd,isnow){

	//send script to applet as setTimeout string -- critical for Opera

	if(isnow){
		scmd=unescape(scmd)
	}else{
		setTimeout("sendscript('"+escape(scmd)+"',1)",100)
		return
	}

	if(document[jmoltarget]){
		document[jmoltarget].script(scmd)
	}else if(document.getElementById(jmoltarget)){
		var d=document.getElementById(jmoltarget)
		d.script(scmd)
	}else if(document.info[jmoltarget]){
		document.info[jmoltarget].script(scmd)
	}else{
		alert("Can't find applet")
	}
}


function showmass(a1,a2){

	//return script for showing click action
	//DO NOT RUN .script() immediately, or next line of JS after this call will not run.

	for(var i=1;i<=Structure.natoms;i++)Structure.Atoms[i].color="CPK"
	var scmd="select *;color cpk;"
	if(a1!=a2)scmd+=getconnectedscript(a1,a2,"violet")
	if(scmd=="") return "set echo bottom left;color echo red; echo \" select two adjacent atoms\";select *;color atoms cpk;"
	var m=getmass("violet")

	scmd+="set echo top left;color echo violet;echo \" "+getformula("violet")+" "+(m?"mass="+m:"")+"\";"
	if(a2==0||a1==a2){
                scmd+="set echo bottom left;color echo white;echo \" now select an adjacent atom\""//white;echo \""+getformula("CPK")+" mass="+getmass("CPK")+"\";draw plane1 delete;"
		return scmd
	}
	scmd+=getconnectedscript(a2,a1,"grey")
        removeAllHighlights();
   	addHighlight(m);
	scmd+="set echo bottom left;color echo grey; echo \" "+getformula("grey")+" mass="+getmass("grey")+"\";draw plane1 PLANE 300 PERP (atomno="+a1+") (atomno="+a2+");color $plane1 translucent "
	return scmd
}

function getredmass(a1,a2,ib){
	for(var i=1;i<=Structure.natoms;i++)Structure.Atoms[i].color="CPK"
        var scmd=(Structure.Atoms[a1].sym!="C"||Structure.Atoms[a2].sym=="H"?"":getconnectedscript(a1,a2,"violet"))
        if(scmd=="")return [0,0,0,0,0]
        var mexact=getmass("violet")
        if(isNaN(mexact))mexact=parseFloat(mexact)
        var m=Math.floor(mexact)
        return [a1,a2,m,mexact,Structure.Atoms[a1].ntype]
}

function getbondmass(ib,isfirst){
        var B=Structure.Bonds[ib]
        return(isfirst?getredmass(B[0],B[1],ib):getredmass(B[1],B[0],ib))
}

function getallpossiblemasses(){
        var S=new Array()
        var A=new Array()
        for(var i=0;i<Structure.Bonds.length;i++){
                if(Structure.Bonds[i][2]==1){
                        A=getbondmass(i,1)
                        if(A[2]>=MASSMIN)S.push(A)
                        A=getbondmass(i,0)
                        if(A[2]>=MASSMIN)S.push(A)
                }
        }
        S=S.sort(msort)
        return S
}

function msort(a,b){
        return (a[2]>b[2]?1:a[2]<b[2]?-1:a[4]<b[4]?1:a[4]>b[4]?-1:0)
}

function showallpossiblemasses(isall){
        var s=""
        var m=0
        var m0=0
        if(!AllMasses)AllMasses=getallpossiblemasses()
        for(var i=0;i<AllMasses.length;i++){
                m=AllMasses[i][2]
                if(m && (isall || m!=m0)){
                        s+="<a href=javascript:showcut("+i+")>"+AllMasses[i][2]+"</a> "
                        addHighlight(m)
                }
                m0=m
        }
	var d=document.getElementById("molfile")
	d.innerHTML=s
}

function addHighlight(m){
        m=parseFloat(m+"")
        var d=document.getElementById("JSVApplet")
        if(d)d.addHighlight(m-0.5,m+0.5,241,111,171,200)
}

function showcut(i){
        document.title=AllMasses[i]
      	var scmd=showmass(AllMasses[i][0],AllMasses[i][1])
        addHighlight(AllMasses[i][2])
	sendscript(scmd)
}

function showMostProbable(intmass){
	//callback from JSpecView
	var scmd="select *; color cpk; draw plane1 delete; echo top center;echo \" \";echo bottom center;echo \" \""
	if(Math.abs(intmass - mw) < 0.5){
		sendscript(scmd)
		setTimeout('alert("This is the M peak ('+intmass+') for '+mf+'")',50)
		return
	}
	if(Math.abs(intmass - (mw-1)) < 0.5){
		sendscript(scmd)
		setTimeout('alert("This is the M-1 peak ('+intmass+') for '+mf+' with M = ' + mw+'")',50)
		return
	}
        var s=""
        var m=0
        var m0=0
        if(!AllMasses)AllMasses=getallpossiblemasses()
        for(var i=0;i<AllMasses.length;i++){
                m=AllMasses[i][2]
                if(m==intmass){
                        showcut(i)
                        return
                }
        }
	sendscript(scmd)
	setTimeout('alert("Couldn\'t identify a mass fragment with mass '+intmass+'")',50)
}

function showmolfile(){
         return

	//display molfile contents with highlights in right-hand table cell

	var s=Structure.header
	for(var i=1;i<=Structure.natoms;i++){
		s+="<font color="+Structure.Atoms[i].color+">"
		s+=Structure.Atoms[i].lineinfo+"</font>\n"
	}
	for(var i=0;i<Structure.nbonds;i++){
		s+=Structure.Bonds[i][2]+"\n"
	}
	s+=Structure.footer
	var d=document.getElementById("molfile")
	d.innerHTML="<pre>"+s+"</pre>"
}

