Mercurial > hg > Members > nobuyasu > Consensus
changeset 87:a067d8d6458e draft
add revisionviewer.html
author | one |
---|---|
date | Mon, 11 Mar 2013 05:44:46 +0900 |
parents | 8aabc749f5d8 |
children | 75d45f808217 |
files | public/viewer/revisionviewer.html |
diffstat | 1 files changed, 585 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/viewer/revisionviewer.html Mon Mar 11 05:44:46 2013 +0900 @@ -0,0 +1,585 @@ +<meta http-equiv="content-type" content="text/html;charset=utf-8" /> +<title>R-Consensus</title> +<link rel='stylesheet' href="form.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(){ + userName=localStorage.userName; + if(userName)start(); + else $("#loginPopup").css("display","block"); +}) +function login(uname){ + userName=localStorage.userName=uname; + start(); +} +function start(){ + $.ajax({ + url:BASE_URL+"/users/create/"+userName, + success:function(o){/*console.log(o)*/}, + type:"PUT",cache:false, + error:function(o){console.log(o)} + }); + + 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() + loadConsensus(consensus_id); + setInterval(function(){loadUserList();loadConsensus(consensus_id)},LOAD_INTERVAL*1000); + }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 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); + 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> +div.claimNode{ + z-index:20; + position:absolute;width:92px;height:40px;font-size:12px;padding:4px;background:white; + border:2px solid silver; + overflow:hidden; + border-radius:5px; + cursor:pointer; +} +body{background-color:black;} + +div.userList{ + position:fixed; + z-index:30; + right:0;top:0; + width:160px; +} +div.header{ + position:absolute; + left:0;top:0; + z-index:5; + height:50px; + width:100%; + background:#223; + background:-moz-linear-gradient(top,#002,#223); + background:-webkit-gradient(linear,left top,left bottom,from(#002),to(#223)); + color:silver; + font-size:40px; +} +div.revision{ + position:absolute; + left:0;top:50px; + z-index:5; + height:25px; + width:100%; + color:silver; + font-size:20px; +} + +</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(); + } +} + +</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"> + revision: + <select id="revisionselect" name="revision" onchange="console.log(this.value)"> + <option>9</option> + <option>94</option> + </select> +</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>