web应用中,用户交互性体验一直都是开发人员追求的。Ajax是个不错的选择。
本文介绍用javascript操作DOM元素,完成多段图决策问题。
先简要的介绍一下:
通过web视图,选择下一阶段是否是汇点,如不是汇点,则提示输入该阶段的节点数目;如是汇点,则提示各个阶段中每个节点到下一阶段每个节点的成本。当输入完成后可以点击查看决策结果。
本例采用MVC模式开发,这样在维护起来较为方便,可以随着应用增加新的功能。关于MVC 模式的优点可以参照<a href="http://blog.csdn.net/huankfy/archive/2007/05/06/1598481.aspx">
模型-视图-控制器
(MVC)模式在ajax中的应用 <a>中的相关介绍。
视图部分:
<html>
<head>
<title>test</title>
<script language="javascript" src=”mutiGraph.js”></script>
<script language=”javascript”>
window.οnlοad=createJieDuan;
</script>
<head>
<body>
<span id="sd">源点<br></span>
<input type="radio" id="source"><span id="s">1</span>
<div id="divborder"></div>
<input type="submit" οnclick="showResult()" id="sub" value="查看结果">
<div id="result"></div>
</body>
</html>
模型/控制部分:
mutiGraph.js的内容:
....................................................................................................................................................................
var counter=2; //阶段数目,初始值为2(源点/汇点)
var NodeNumber=1;//记录节点编号,初始值为源点的编号
var KNodeNum=new Array();//从数组的第2个开始,KNodeNum[0]不用
var cost=new Array();
var CResult=new Array();//各个节点到汇点的最小成本
var Designser=new Array();//二维数组,Designser[i][j]存储的是处于第j-1阶段节点i 在第j阶段的决策
function createJieDuan(){//创建阶段
var btn=document.getElementById("sub");
btn.style.display="none";
var rootDiv=document.getElementById("divborder");
var jieDuanEl=document.createElement("div");//创建阶段dom,用以显示该阶段所有的数据
jieDuanEl.setAttribute("id","jieDuan_"+counter);
var questionEl=document.createElement("div");;//创建问题的dom节点
questionEl.setAttribute("id","question_"+counter);
questionEl.innerHTML="下一阶段是汇点吗?<br>";
var checkboxEl=new Array();
var checkboxSpan=new Array();
var i=0;
while(i<2){
checkboxEl[i]=document.createElement("input");
checkboxEl[i].setAttribute("type","radio");
checkboxEl[i].setAttribute("title",counter);
checkboxEl[i].οnblur=radioClickEvent;
checkboxSpan[i]=document.createElement("span");
if(i==0){
checkboxEl[i].setAttribute("value","yes");
checkboxSpan[i].innerHTML="yes</br>";
}
else{
checkboxEl[i].setAttribute("value","no");
checkboxSpan[i].innerHTML="no</br>";
}
checkboxEl[i].setAttribute("name","choice_"+counter);
questionEl.appendChild(checkboxEl[i]);
questionEl.appendChild(checkboxSpan[i]);
i=i+1;
}
var answerDom=document.createElement("div");
answerDom.setAttribute("id","ans_"+counter);
questionEl.appendChild(answerDom);
jieDuanEl.appendChild(questionEl);
rootDiv.appendChild(jieDuanEl);
}
function radioClickEvent(){
var radioEltitle=this.title;
var ansDomEl=document.getElementById("ans_"+radioEltitle);
var questionDomEl=document.getElementById("question_"+radioEltitle);
var radioEl=questionDomEl.getElementsByTagName("input");
if(radioEl){
if(true){
if(radioEl[1].checked){ //选择不是汇点的时候
var spanDom=document.createElement("span");
spanDom.innerHTML="第"+counter+"阶段的节点数目:";
ansDomEl.appendChild(spanDom);
var textDom=document.createElement("input");
textDom.setAttribute("type","text");
textDom.setAttribute("id",radioEltitle);
textDom.οnblur=inputEvent;
ansDomEl.appendChild(textDom);
var jiedianDom=document.createElement("div");
jiedianDom.setAttribute("id","jiedian_"+radioEltitle);
ansDomEl.appendChild(jiedianDom);
counter=counter+1;
}
if(radioEl[0].checked){
var spanDom=document.createElement("span");
spanDom.innerHTML="汇点<br>";
ansDomEl.appendChild(spanDom);
var textDom=document.createElement("input");
textDom.setAttribute("type","radio");
textDom.setAttribute("id",radioEltitle);
ansDomEl.appendChild(textDom);
NodeNumber=NodeNumber+1;
var txt=document.createTextNode(NodeNumber);
ansDomEl.appendChild(txt);
var divDom=document.createElement("div");
divDom.setAttribute("id","huidian_"+counter);
ansDomEl.appendChild(divDom);
getInput();
}
}
}
}
function inputEvent(){
var i=this.id;
if(parseInt(this.value)!=NaN){
var num=parseInt(this.value);
var jiedianDiv=document.getElementById("jiedian_"+i);
var jiedianDom=new Array();
var tempcounter=1;
while(tempcounter<=num){
jiedianDom[tempcounter]=document.createElement("input");
jiedianDom[tempcounter].setAttribute("type","radio");
// jiedianDom[tempcounter].setAttribute("name","jiedian_"+i);
jiedianDiv.appendChild(jiedianDom[tempcounter]);
var lable=document.createElement("span");
lable.innerHTML=NodeNumber+tempcounter;
jiedianDiv.appendChild(lable);
tempcounter=tempcounter+1;
}
NodeNumber=parseInt(NodeNumber)+parseInt(num);
createJieDuan();
}
}
function getInput(){
var i=2;
var j=1;
var m=1;
var k=1;
var inputDomDivEl=document.getElementById("huidian_"+counter);
KNodeNum[0]=0;
KNodeNum[1]=1;
KNodeNum[counter]=1;
while(i<counter){
//取得每个阶段的节点数目
var temp=document.getElementById(i);
KNodeNum[i]=temp.value;
i=i+1;
}
initCost(); //初始化cost'二维数组'
var tempNodeNumber=0;
while(j<counter){
var txt=document.createElement("span");
txt.innerHTML="输入第"+j+"阶段到第"+(j+1)+"阶段节点间的成本:<br>"
inputDomDivEl.appendChild(txt);
while(k<=KNodeNum[j+1]){
while(m<=KNodeNum[j]){
var txti=document.createTextNode("节点"+(parseInt(tempNodeNumber)+parseInt(m))+"到节点"+(parseInt(tempNodeNumber)+parseInt(KNodeNum[j])+k)+"的距离:
");
inputDomDivEl.appendChild(txti);
var inputDomEl=document.createElement("input");
inputDomEl.setAttribute("type","text");
var tempNodeNumberm=parseInt(tempNodeNumber)+m;
var tempNjk=tempNodeNumber+parseInt(KNodeNum[j])+k;
// inputDomEl.setAttribute("id",tempNodeNumber+m+"|"+tempNodeNumber+parseInt(KNodeNum[j])+k);
inputDomEl.setAttribute("id",tempNodeNumberm+"|"+tempNjk);
inputDomEl.οnblur=stroeData;
inputDomDivEl.appendChild(inputDomEl);
var txteffict=document.createElement("span");
txteffict.innerHTML=" <br>";
inputDomDivEl.appendChild(txteffict);
m=m+1;
}
k=k+1;
m=1;
}
k=1;
tempNodeNumber=parseInt(tempNodeNumber)+parseInt(KNodeNum[j]);
j=j+1;
var txtspan=document.createElement("span");
txtspan.innerHTML="<br>";
inputDomDivEl.appendChild(txtspan);
}
var btn=document.getElementById("sub");
btn.style.display="block";
return 1;
}
function stroeData(){
var number=(this.id).split("|");
var i=parseInt(number[0]);
var j=parseInt(number[1]);
cost[i][j]=this.value;
}
function getResult(){ //计算结果
initDesignser();//初始化Designser'二维数组'
var tempi=counter-1;
var tempk=0;
var tempj=0;
var tempNodeNumber=NodeNumber;
var tempCOST=new Array();
CResult[NodeNumber]=0;
while(tempi>0){ //阶段
var dtemp=tempNodeNumber;
tempNodeNumber=tempNodeNumber-KNodeNum[tempi];
while(tempk<KNodeNum[tempi]){
var tmNK=parseInt(tempNodeNumber)+parseInt(tempk);
while(tempj<KNodeNum[tempi+1]){
var tmNKJ=dtemp;
tmNKJ=tmNKJ+parseInt(tempj);
tempCOST[tempj]=parseInt(cost[tmNK][tmNKJ])+parseInt(CResult[tmNKJ]);
// alert(tempCOST[tempj]);
tempj=tempj+1;
}
var tempr=miniValue(tempCOST);
CResult[tmNK]=tempr[0]; //tmNK节点到汇点的最小成本
// alert(tempr[0]);
Designser[tmNK][tempi+1]=parseInt(dtemp)+parseInt(tempr[1]);
tempk=tempk+1;
tempj=0;
}
tempi=tempi-1;
tempk=0;
}
}
function miniValue(temp){
var length=temp.length;
var result=new Array();
var i=0;
result[0]=temp[0];
result[1]=0;
if(length>1){
for(;i<length;i++){
if(result[0]>temp[i]){
result[0]=temp[i];
result[1]=i;
}
}
}
return result;
}
function initDesignser(){
var i=0;
while(i<counter){
Designser.push(new Array());
i=i+1;
}
}
function initCost(){
var i=0;
while(i<NodeNumber){
cost.push(new Array()); //模拟二维数组,空间会很浪费.............cost[i][j] 是编号为i的节点到编号为j的节点的成本.........希望有更好的办法
i=i+1;
}
}
function showResult(){
getResult();
var testDiv=document.getElementById("result");
testDiv.setAttribute("align","center");
testDiv.innerHTML="==========决策结果如下==========<br>";
var retxt="1->";
var ct=1;
var node=0;
while(ct<counter){
node=parseInt(node)+parseInt(KNodeNum[ct]);
retxt=retxt+Designser[node][ct+1];
if((ct+1)!=counter)
retxt=retxt+"->";
ct=ct+1;
}
var txtDomEl=document.createTextNode(retxt);
testDiv.appendChild(txtDomEl);
}