view public/viewer/revisionviewer.html @ 119:aa5daf38f3e9 draft

viewer.html
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Thu, 18 Apr 2013 06:19:26 +0900
parents 440b337b2182
children 9cfb52e94bd0
line wrap: on
line source

<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>R-Consensus</title>
<link rel='stylesheet' href="form.css">
<link rel="stylesheet" href="jquery-ui.css">
<script src='form.js'></script>
<script type="text/javascript" src="js/lib/jquery-1.8.1-min.js"></script>
<script type="text/javascript" src="js/lib/jquery-ui-1.8.23-min.js"></script>
<script type="text/javascript" src="js/lib/jquery.ui.touch-punch.min.js"></script>
<script type="text/javascript" src="js/lib/jsBezier-0.4-min.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-util-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-dom-adapter-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-defaults-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-svg-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-canvas-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-vml-1.3.15-RC1.js"></script>
<script type="text/javascript" src="js/1.3.15/jquery.jsPlumb-1.3.15-RC1.js"></script>
<script type="text/javascript" src='treeArrangement.js'></script>
<script type="text/javascript">
    var LOAD_INTERVAL=5;
var BASE_URL="";
if(!Array.prototype.filter){
    Array.prototype.filter=function(func){
	var arr=[];
	for(var i=0;i<this.length;i++)if(func(this[i]))arr.push(this[i]);
	return arr;
    }
}

var userName;
var treeInfo;
var userList=[];
var root_id;
function loadConsensus(id){
    function onload(json){
	document.title="R-Consensus:"+json.toulmin.title;
	$("#headertitle_main").text(json.toulmin.title)
	if(treeInfo){
	    updateToNew(json);
	}else{
	    console.log(JSON.parse(JSON.stringify(json)));
	    treeInfo=createJSONTreeInfo(json)
	    //userList=getUserListFromJSONTree(treeInfo.root);
	    showUserList([]);
	    updateNode(treeInfo.root);
	    updateTree();
	}
    }
    $.ajax({
	url:BASE_URL+"/consensus/browse/"+id,
	success:function(o){onload(o)},
	type:"GET",cache:false,
	error:function(o){console.log("ERROR",o)}
    });
}
function loadUserList(){
    $.ajax({
	url:BASE_URL+"/users/all",
	success:function(o){userList=o.sort();showUserList([]);},
	type:"GET",cache:false,
	error:function(o){console.log("ERROR",o)}
    });
}

function loadRevisionInfo(consensus_id) {
    $.ajax({
	url:BASE_URL+"/claims/get/revision/"+consensus_id,
	success:function(o){createOptionTag(consensus_id, o); console.log("revision = "+ o)},
	type:"GET",cache:false,
	error:function(o){console.log("ERROR",o)}
    });
}

function changeRevision(id) {
    root_id = id;
    loadConsensus(id);
}

function createOptionTag(consensus_id, revisionInfo) {
    var selectArray = new Array();
    selectArray.push('<select onchange="changeRevision(this.value)" >');
    for (var i=0; i<revisionInfo.length; i++) {
	var revision = revisionInfo.length - i;
	selectArray.push("<option value='"+revisionInfo[i]+"'>"+revision+"</option>");
    }
    selectArray.push("</select>");
    $('#revisionId')[0].innerHTML =  "revision:"+selectArray.join();
    //        $('#revisionId')[0].children[0].value = consensus_id;
}

$(function(){
    userName=localStorage.userName;
    if(userName)start();
    else $("#loginPopup").css("display","block");
})
function login(uname){
    userName=localStorage.userName=uname;
    start();
}
function start(){
    popupInit();
    jsPlumb.importDefaults({
	Connector : [ "Straight", { curviness:50 } ],
	PaintStyle : { strokeStyle:"gray", lineWidth:2 },
	EndpointStyle : {},
	Anchors: ["BottomCenter","TopCenter"]
    });
    var consensus_id=(location.search.match("[0-9]+")||[])[0];
    if(consensus_id){
	root_id=consensus_id;
	loadUserList();
	loadRevisionInfo(consensus_id);
	loadConsensus(consensus_id);
    }else{
	document.body.innerHTML="<div style='color:white;font-size:64px'>No ClaimID Specified.<br><a href='index.html' style='color:#88f'>back</a></div>";
    }
}

function updateToNew(json){
    var t2=createJSONTreeInfo(json)
    updateJSONTreeDiff(treeInfo.root,t2.root);
    
    updateNode(treeInfo.root);
    treeInfo.newLayout=t2.layout;
    var cnt=0,time=500;
    var time0=new Date();
    var prevCnt=0;
    function tfunc(t){return 2*t-t*t}
    function animation(){
	var cnt=(new Date()-time0)/time;
	if(cnt<1){
	    if(prevCnt!=cnt){
		var pt=tfunc(prevCnt);
		var t=tfunc(cnt);
		animateTree((t-1)/(pt-t));
		prevCnt=cnt;
		
	    }
	    setTimeout(animation,10);
	}else{
	    animateTree(0);
	}
	updateNode(treeInfo.root);
	updateTree();
    }
    animation();
}

var ViewParam={
    offsetTop:100,
    offsetBottom:100,
    offsetLeft:100,
    offsetRight:100,
    nodeWidth:120,
    nodeHeight:60,
    intervalX:140,
    intervalY:120
};

function animateTree(t){
    function animateNodePosition(node,t){
	node.position.x=(node.position.x*t+node.newPosition.x)/(1+t);
	node.position.y=(node.position.y*t+node.newPosition.y)/(1+t);
	for(var i=0;i<node.mentions.length;i++){
	    animateNodePosition(node.mentions[i],t);
	}
	if(t==0){
	    if(node.newPosition.remove){
		jsPlumb.removeAllEndpoints(node.view);
		$(node.view).remove();
	    }
	    node.mentions=node.mentions.filter(function(n){return !n.newPosition.remove});
	}
    }
    animateNodePosition(treeInfo.root,t);
    treeInfo.layout.left=(treeInfo.layout.left*t+treeInfo.newLayout.left)/(1+t);
    treeInfo.layout.right=(treeInfo.layout.right*t+treeInfo.newLayout.right)/(1+t);
    treeInfo.layout.depth=(treeInfo.layout.depth*t+treeInfo.newLayout.depth)/(1+t);
}

function updateTree(){
    with(treeInfo.layout){
	$("#treeRoot").css({
	    left:ViewParam.offsetLeft+ViewParam.nodeWidth/2-ViewParam.intervalX*left,
	    top:ViewParam.offsetTop+ViewParam.nodeHeight/2});
	$("#treeMain").css({
	    width:ViewParam.intervalX*(right-left)+ViewParam.nodeWidth+ViewParam.offsetLeft+ViewParam.offsetRight,
	    height:ViewParam.intervalY*(depth-1)+ViewParam.nodeHeight+ViewParam.offsetTop+ViewParam.offsetBottom,
	    top:50});
    }
    jsPlumb.repaintEverything();
}


var relationJPMap={
    suggestion:"提案",
    refutation:"反論",
    question:"質問"
};
function updateNode(node){
    if(updateClaimElement(node)){
	var fc=$("#treeRoot")[0].firstChild;
	if(fc)$("#treeRoot")[0].insertBefore(node.view[0],fc);
	else $("#treeRoot").append(node.view);
    }
    node.view.css({
	left:node.position.x*ViewParam.intervalX-ViewParam.nodeWidth/2,
	top:node.position.y*ViewParam.intervalY-ViewParam.nodeHeight/2
    });	
    var childs=node.mentions;
    for(var i=0;i<childs.length;i++){
	var child=childs[i];
	var created=!child.view;
	updateNode(child);
	if(created){
	    var c=jsPlumb.connect({source:node.view[0],target:child.view[0]});
	    c.setLabel({label:"<span style='color:white'>"+(relationJPMap[child.relation]||child.relation)+"</span>",cssStyle:"color:white"});
	}
    }
}

var focusedUser=null;
function setFocusedShadowEverything(){
    function recFocusShadow(node){
	setFocusedShadow(node);
	for(var i=0;i<node.mentions.length;i++){
	    recFocusShadow(node.mentions[i]);
	}
    }
    recFocusShadow(treeInfo.root);
}
function setFocusedShadow(node){
    var name=focusedUser||userName;
    var color;
    //	console.log(node.info.author)
    if(node.info.author==name)color="#afa";
    else{
	var users=node.info.users,status;
	for(var i=0;i<users.length;i++){
	    var u=users[i];
	    if(u.id==name){status=u.status;break;}
	}
	color=({agreed:"#aaf",denied:"#faa",pend:"white",unknown:"white"})[status];
    }
    node.view.css("box-shadow",color?color+" 0 0 30px":"none");
}
function appendStatusElement(viewDiv, status){
    var statusView = $("<div class='nodeStatus'/>");
    statusView.text(status);
    statusView.css({
	left:0,
	top:-5
    });
    viewDiv[0].appendChild(statusView[0]);
}
function updateClaimElement(node){
    var created=false;
    if(!node.view){
	created=true
	node.view=$("<div class='claimNode'/>");
	node.view.click(function(){showClaim(node);});
	node.view.hover(
	    function(){div.css("box-shadow","white 0 0 50px");showUserList(node.info.users,node.info.author)},
	    function(){try{setFocusedShadow(node);}catch(e){/*console.log(e)*/;}showUserList([])}
	)
    }
    setFocusedShadow(node);
    var div=node.view;
    div.text(node.info.toulmin.title);
    appendStatusElement(node.view, node.info.status);
    var statusBackground={pass:"#aaf",unknown:"#fff",failed:"#faa",fail:"#faa"};
    var statusBorder={pass:"#66a",unknown:"#aaa",failed:"#a66",fail:"#a66"};
    div.css("background",statusBackground[node.info.status]||"white");
    div.css("border-color",statusBorder[node.info.status]||"white");
    return created;
}


function showUserList(users,author){
    var statusMap={};
    var userListElement=$(".userList");
    userListElement.text('')
    if(author)statusMap['#'+author]='author';
    for(var i=0;i<users.length;i++){
	statusMap['#'+users[i].id]=users[i].status;
    }
    for(var i=0;i<userList.length;i++){
	var u=userList[i];
	var ue=createUserElement(u==userName?"あなた("+u+")":u,statusMap['#'+u]);
	if(u==userName){
	    ue.css({fontWeight:"bold"})
	}
	ue.appendTo(userListElement);
	with({name:u,element:ue}){
	    ue.hover(
		function(){
		    element.css("opacity",1);
		    focusedUser=name;setFocusedShadowEverything()
		},
		function(){
		    element.css("opacity",0.5);
		    focusedUser=userName;setFocusedShadowEverything()
		}
	    )
	}
	
    }
    $(".userList").css("opacity","1");
}
function hideUserList(){
    $(".userStatus").css("background","none");
    $(".userItem").css("opacity","1");
    $(".userList").css("opacity","0.2");
}
</script>
<style>
body{background-color:black;}
div.revisionSlider{
    position:absolute;
    left:0;top:70px;
    z-index:5;
    width:50%;
}
</style>
<script>
function resetMentionForm(){
      var keys=['title','contents','w','d','b','q','r'];
      for(var i=0;i<keys.length;i++)$("#mentionform_"+keys[i]).val("");
      $("#mention_option")[0].className="option";
}
var formClaim;
var claimUserMap,mentionUserMap;
function showClaim(claim){
	formClaim=claim;
	var info=claim.info;
      var keys=['title','contents','w','d','b','q','r'];
      for(var i=0;i<keys.length;i++)$("#claimform_"+keys[i]).val(info.toulmin[keys[i]]);
	
	var status="";
	for(var i=0;i<info.users.length;i++)if(info.users[i].id==userName)status=info.users[i].status;
	var op=({denied:1,pend:2,agreed:3})[status];
	
	$("#claim_status").text(info.status)
	$("#claim_status").css("color",({pass:"blue",failed:"red",fail:"red",unknown:"black"})[info.status]);
	$("#agree_option")[0].className="option"+(op?" option"+op:"");
	$("#agree_option").css("display",status?"block":"none");
	
	$("#claim_button").css("display",(userName==info.author)?"block":"none");
	$("#claimvote_option").css("display",status?"block":"none");
	
	$("#claimbody")[0].className="claim_contents";
	$("#mentionbody")[0].className="mention_contents";
	
	$("#claim_author").text(info.author);
	$("#mention_author").text(userName);
	$("#claimvote_option")[0].className="option option"+(claim.agreeType=="majority"?2:1);
	$("#mentionvote_option")[0].className="option option1";
	var stateMap={};
	for(var i=0;i<info.users.length;i++)stateMap['#'+info.users[i].id]=info.users[i].status;
	claimUserMap=new HashSet(info.users.map(function(u){return u.id}));
	mentionUserMap=new HashSet();
	$("#claim_users").text("");
	$("#mention_users").text("");
	if(userName!=info.author)mentionUserMap.add(info.author);
	for(var i=0;i<userList.length;i++){
		var name=userList[i];
		if(name!=info.author){
			var status=stateMap['#'+name];
			createUserSelectItem(name,status,claimUserMap).appendTo($("#claim_users"));
		}if(name!=userName){
			createUserSelectItem(name,name==info.author?"unknown":"",mentionUserMap).appendTo($("#mention_users"));
		}
	}
      resetMentionForm();
	popupShowMain()
}


function claimSave(){
	var claim=formClaim;
	var info=claim.info;
	var id=claim.id||root_id;
	var agreeType=[null,"unanimously","majority"][($('#claimvote_option')[0].className.match("[0-9]+")||"0")[0]];
	var title=$('#claimform_title').val();
	var contents=$('#claimform_contents').val();
	var d=$('#claimform_d').val();
	var w=$('#claimform_w').val();
	var b=$('#claimform_b').val();
	var q=$('#claimform_q').val();
	var r=$('#claimform_r').val();
	var users=claimUserMap.toArray();
	var errors=[];
	if(!title)errors.push("タイトル");
	if(!agreeType)errors.push("採決方法");
	if(users.length==0)errors.push("同意を取るユーザ");
	if(errors.length){
		alert("未入力項目:"+errors.join(", "));
	}else{
		$.ajax({
			url:BASE_URL+"/claims/edit/"+id,
			success:function(o){loadConsensus(root_id)},
			type:"POST",cache:false,
			contentType:"application/json",
			data:JSON.stringify({type:agreeType,toulmin:{title:title,contents:contents,q:q,d:d,w:w,b:b,r:r},author:userName,users:users}),
			error:function(o){console.log("ERROR",o)}
		});
		popupHideAll();
	}
}
function claimAgree(status){
	var claim=formClaim;
	var info=claim.info;
	var id=claim.id||root_id;
	$.ajax({
		url:BASE_URL+"/claims/answer/"+id+"/"+userName+"/"+status,
		success:function(o){loadConsensus(root_id)},
		type:"POST",cache:false,
		error:function(o){console.log("ERROR",o)}
	});
	popupHideAll();
}
function mentionSave(){
	var claim=formClaim;
	var info=claim.info;
	var id=claim.id||root_id;
	var mentionType=[null,"refutation","question","suggestion"][($('#mention_option')[0].className.match("[0-9]+")||"0")[0]];
	var agreeType=[null,"unanimously","majority"][($('#mentionvote_option')[0].className.match("[0-9]+")||"0")[0]];
	var title=$('#mentionform_title').val();
	var contents=$('#mentionform_contents').val();
	var d=$('#mentionform_d').val();
	var w=$('#mentionform_w').val();
	var b=$('#mentionform_b').val();
	var q=$('#mentionform_q').val();
	var r=$('#mentionform_r').val();
	var users=mentionUserMap.toArray();
	var author=userName;
	var errors=[];
	if(!title)errors.push("タイトル");
	if(!agreeType)errors.push("採決方法");
	if(!mentionType)errors.push("反論質問提案");
	if(users.length==0)errors.push("同意を取るユーザ");
	if(errors.length){
		alert("未入力項目:"+errors.join(", "));
	}else{
		$.ajax({
			url:BASE_URL+"/claims/"+mentionType+"/"+id+"/create",
			success:function(o){loadConsensus(root_id)},
			type:"POST",cache:false,contentType:"application/json",
			data:JSON.stringify({type:agreeType,toulmin:{title:title,contents:contents,q:q,d:d,w:w,b:b,r:r},author:author,users:users}),
			error:function(o){console.log("ERROR",o)}
		});
		popupHideAll();
	}
}

$(function() {
    $('#slider').slider({ step:5,
			  slide: function(event, ui){ console.log(ui.value); },
			  stop: function(event, ui){ console.log(ui.value); }
			});

    $('#slider').slider();
});
</script>
<div class='header'>
<nobr id='header_title'><a href='index.html'>Home</a><span id='headertitle_main' style='margin-left:40px;'>loading</span></nobr>
</div>
<div class="revision" id="revisionId"></div>
<div class="revisionSlider" id="slider" style='left:10px;' ></div>

<div style="position:relative;left:0;top:0;" id='treeMain'>
<div style="position:absolute;width:0;height:0;left:100;" id='treeRoot'>
</div>
</div>

<div class='userList'></div>


<div id='popup_base' style='display:none;z-index:100'>
<div id='popup_background'></div>
<div class='popup_center'>
<div class='claiminfo' id='claiminfo'>
	<div class='claim_title'><input placeholder="title" id='claimform_title'></div>
	<div id='claimbody' class='claim_contents'>
		<div class='claim_menu'>
			<div class='menu_item menu_contents' onclick="$('#claimbody')[0].className='claim_contents'">Contents</div>
			<div class='menu_item menu_toulmin' onclick="$('#claimbody')[0].className='claim_toulmin'">Toulmin</div>
			<div class='menu_item menu_users'  onclick="$('#claimbody')[0].className='claim_users'">Users</div>
			<div id='claim_status'></div>
		</div>
		<div class='claim_main main_contents'>
			<textarea placeholder='contents' id='claimform_contents'></textarea>
		</div>
		<div class='claim_main main_toulmin'>
			<div class='item_toulmin'><span>データ</span><input id='claimform_d'></div>
			<div class='item_toulmin'><span>論拠 </span><input id='claimform_w'></div>
			<div class='item_toulmin'><span>裏付け</span><input id='claimform_b'></div>
			<div class='item_toulmin'><span>限定詞</span><input id='claimform_q'></div>
			<div class='item_toulmin'><span>反駁 </span><input id='claimform_r'></div>
		</div>
		<div class='claim_main main_users'>
			<span class='author_label'>作者:</span>
			<span class='author_name' id='claim_author'></span>
			<div class='option option1' id='claimvote_option'>
				<span class='option option1 vote1' onclick="$('#claimvote_option')[0].className='option option1'">全会一致</span>
				<span class='option option2 vote2' onclick="$('#claimvote_option')[0].className='option option2'">多数決</span>
			</div>
			<div id='claim_users'></div>
		</div>
	</div>
	<div class='claim_footer'>
		<span onclick='popupShowSubMain()' class='button mention_button'>mention</span>
		<div class='option' id='agree_option'>
			<span class='option option1 agree1' onclick="$('#agree_option')[0].className='option option1';claimAgree('denied');">否認</span>
			<span class='option option2 agree2' onclick="$('#agree_option')[0].className='option option2';claimAgree('pend');">保留</span>
			<span class='option option3 agree3' onclick="$('#agree_option')[0].className='option option3';claimAgree('agreed');">合意</span>
		</div>
		<div id='claim_button'>
		<span class='button cancel' onclick="popupHideAll()">cancel</span>
		<span class='button save' onclick="claimSave()">save</span>
		</div>
	</div>
	<div class='cover' id='claim_cover'></div>
</div>


<div class='mentioninfo' id='mentioninfo'>
	<div class='claim_title'><input placeholder="title" id='mentionform_title'></div>
	<div id='mentionbody' class='mention_contents'>
		<div class='claim_menu'>
			<div class='menu_item menu_contents' onclick="$('#mentionbody')[0].className='mention_contents'">Contents</div>
			<div class='menu_item menu_toulmin' onclick="$('#mentionbody')[0].className='mention_toulmin'">Toulmin</div>
			<div class='menu_item menu_users'  onclick="$('#mentionbody')[0].className='mention_users'">Users</div>
		</div>
		<div class='mention_main main_contents'>
			<textarea placeholder='contents' id='mentionform_contents'></textarea>
		</div>
		<div class='mention_main main_toulmin'>
			<div class='item_toulmin'><span>データ</span><input id='mentionform_d'></div>
			<div class='item_toulmin'><span>論拠 </span><input id='mentionform_w'></div>
			<div class='item_toulmin'><span>裏付け</span><input id='mentionform_b'></div>
			<div class='item_toulmin'><span>限定詞</span><input id='mentionform_q'></div>
			<div class='item_toulmin'><span>反駁 </span><input id='mentionform_r'></div>
		</div>
		<div class='mention_main main_users'>
			<span class='author_label'>作者:</span>
			<span class='author_name' id='mention_author'></span>
			<div class='option option1' id='mentionvote_option'>
				<span class='option option1 vote1' onclick="$('#mentionvote_option')[0].className='option option1'">全会一致</span>
				<span class='option option2 vote2' onclick="$('#mentionvote_option')[0].className='option option2'">多数決</span>
			</div>
			<div id='mention_users'></div>
		</div>
	</div>	
	<div class='claim_footer'>
		<div class='option' id='mention_option'>
			<span class='option option1 mention1' onclick="$('#mention_option')[0].className='option option1'">反論</span>
			<span class='option option2 mention2' onclick="$('#mention_option')[0].className='option option2'">質問</span>
			<span class='option option3 mention3' onclick="$('#mention_option')[0].className='option option3'">提案</span>
		</div>
		<span class='button cancel' onclick="popupShowMain()">cancel</span>
		<span class='button save' onclick="mentionSave()">save</span>
	</div>
	<div class='cover' id='mention_cover'></div>
</div>
</div>
</div>




<div id="loginPopup" style='position:fixed;left:0;top:0;width:100%;height:100%;z-index:10;display:none;'>
<div style='position:absolute;left:0;top:0;width:100%;height:100%;background:black;opacity:0.5'></div>
<div style='position:absolute;left:50%;top:50%;'>
<div style='position:absolute;left:-160px;top:-80px;width:320px;height:120px;background:white'>
<form onsubmit="try{a=$('#loginUserName');if(a.val()){login(a.val());$('#loginPopup').remove();}}catch(e){console.log(e)}return false">
<div style='position:absolute;left:20px;top:15px;font-size:24px;width:280;text-align:center;'>
	R-Consensus Login
</div>
<input type=text placeholder='username' style='position:absolute;left:20px;top:70px;width:180px;font-size:16px;height:24px;' id='loginUserName'>
<span style='position:absolute;left:220px;top:70px;width:80px;font-size:16px;height:24px;line-height:24px;' class='button' value='login' onclick="try{a=$('#loginUserName');if(a.val()){login(a.val());$('#loginPopup').remove();}}catch(e){console.log(e)}return false">login</span>
</form>
</div>
</div>
</div>