comparison public/viewer/viewer.html @ 51:a76259e2ca9f

add public/viewer
author one
date Thu, 04 Oct 2012 16:14:56 +0900
parents
children a405991e39d8
comparison
equal deleted inserted replaced
50:d6c623e92837 51:a76259e2ca9f
1 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
2 <link rel='stylesheet' href="form.css">
3 <script src='form.js'></script>
4 <script type="text/javascript" src="js/lib/jquery-1.8.1-min.js"></script>
5 <script type="text/javascript" src="js/lib/jquery-ui-1.8.23-min.js"></script>
6 <script type="text/javascript" src="js/lib/jquery.ui.touch-punch.min.js"></script>
7 <script type="text/javascript" src="js/lib/jsBezier-0.4-min.js"></script>
8 <script type="text/javascript" src="js/1.3.15/jsPlumb-util-1.3.15-RC1.js"></script>
9 <script type="text/javascript" src="js/1.3.15/jsPlumb-dom-adapter-1.3.15-RC1.js"></script>
10 <script type="text/javascript" src="js/1.3.15/jsPlumb-1.3.15-RC1.js"></script>
11 <script type="text/javascript" src="js/1.3.15/jsPlumb-defaults-1.3.15-RC1.js"></script>
12 <script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-svg-1.3.15-RC1.js"></script>
13 <script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-canvas-1.3.15-RC1.js"></script>
14 <script type="text/javascript" src="js/1.3.15/jsPlumb-renderers-vml-1.3.15-RC1.js"></script>
15 <script type="text/javascript" src="js/1.3.15/jquery.jsPlumb-1.3.15-RC1.js"></script>
16 <script type="text/javascript" src='treeArrangement.js'></script>
17 <script type="text/javascript">
18 var LOAD_INTERVAL=5;
19 var BASE_URL="";
20 if(!Array.prototype.filter){
21 Array.prototype.filter=function(func){
22 var arr=[];
23 for(var i=0;i<this.length;i++)if(func(this[i]))arr.push(this[i]);
24 return arr;
25 }
26 }
27
28 var userName=localStorage.userName;
29 var treeInfo;
30 var userList=[];
31 var root_id;
32 function loadConsensus(id){
33 function onload(json){
34 $("#header_title").text("R-Consensus : "+json.toulmin.title)
35 if(treeInfo){
36 updateToNew(json);
37 }else{
38 console.log(JSON.parse(JSON.stringify(json)));
39 treeInfo=createJSONTreeInfo(json)
40 //userList=getUserListFromJSONTree(treeInfo.root);
41 showUserList([]);
42 updateNode(treeInfo.root);
43 updateTree();
44 }
45 }
46 $.ajax({
47 url:BASE_URL+"/consensus/browse/"+id,
48 success:function(o){onload(o)},
49 type:"GET",cache:false,
50 error:function(o){console.log("ERROR",o)}
51 });
52 }
53 function loadUserList(){
54 $.ajax({
55 url:BASE_URL+"/users/all",
56 success:function(o){userList=o.sort()},
57 type:"GET",cache:false,
58 error:function(o){console.log("ERROR",o)}
59 });
60 }
61
62
63 $(function(){
64 popupInit();
65 jsPlumb.importDefaults({
66 Connector : [ "Straight", { curviness:50 } ],
67 PaintStyle : { strokeStyle:"gray", lineWidth:2 },
68 EndpointStyle : {},
69 Anchors: ["BottomCenter","TopCenter"]
70 });
71
72 var consensus_id=(location.search.match("[0-9]+")||[])[0];
73 if(consensus_id){
74 root_id=consensus_id;
75 loadUserList()
76 loadConsensus(consensus_id);
77 setInterval(function(){loadUserList();loadConsensus(consensus_id)},LOAD_INTERVAL*1000);
78 }else{
79 document.body.innerHTML="<div style='color:white;font-size:64px'>No ClaimID Specified.<br><a href='index.html' style='color:#88f'>back</a></div>";
80 }
81 })
82
83 function updateToNew(json){
84 var t2=createJSONTreeInfo(json)
85 updateJSONTreeDiff(treeInfo.root,t2.root);
86
87 updateNode(treeInfo.root);
88 treeInfo.newLayout=t2.layout;
89 var cnt=0,time=500;
90 var time0=new Date();
91 var prevCnt=0;
92 function tfunc(t){return 2*t-t*t}
93 function animation(){
94 var cnt=(new Date()-time0)/time;
95 if(cnt<1){
96 if(prevCnt!=cnt){
97 var pt=tfunc(prevCnt);
98 var t=tfunc(cnt);
99 animateTree((t-1)/(pt-t));
100 prevCnt=cnt;
101
102 }
103 setTimeout(animation,10);
104 }else{
105 animateTree(0);
106 }
107 updateNode(treeInfo.root);
108 updateTree();
109 }
110 animation();
111 }
112
113 var ViewParam={
114 offsetTop:100,
115 offsetBottom:100,
116 offsetLeft:100,
117 offsetRight:100,
118 nodeWidth:120,
119 nodeHeight:60,
120 intervalX:140,
121 intervalY:120
122 };
123
124 function animateTree(t){
125 function animateNodePosition(node,t){
126 node.position.x=(node.position.x*t+node.newPosition.x)/(1+t);
127 node.position.y=(node.position.y*t+node.newPosition.y)/(1+t);
128 for(var i=0;i<node.mentions.length;i++){
129 animateNodePosition(node.mentions[i],t);
130 }
131 if(t==0){
132 if(node.newPosition.remove){
133 jsPlumb.removeAllEndpoints(node.view);
134 $(node.view).remove();
135 }
136 node.mentions=node.mentions.filter(function(n){return !n.newPosition.remove});
137 }
138 }
139 animateNodePosition(treeInfo.root,t);
140 treeInfo.layout.left=(treeInfo.layout.left*t+treeInfo.newLayout.left)/(1+t);
141 treeInfo.layout.right=(treeInfo.layout.right*t+treeInfo.newLayout.right)/(1+t);
142 treeInfo.layout.depth=(treeInfo.layout.depth*t+treeInfo.newLayout.depth)/(1+t);
143 }
144
145 function updateTree(){
146 with(treeInfo.layout){
147 $("#treeRoot").css({
148 left:ViewParam.offsetLeft+ViewParam.nodeWidth/2-ViewParam.intervalX*left,
149 top:ViewParam.offsetTop+ViewParam.nodeHeight/2});
150 $("#treeMain").css({
151 width:ViewParam.intervalX*(right-left)+ViewParam.nodeWidth+ViewParam.offsetLeft+ViewParam.offsetRight,
152 height:ViewParam.intervalY*(depth-1)+ViewParam.nodeHeight+ViewParam.offsetTop+ViewParam.offsetBottom,
153 top:50});
154 }
155 jsPlumb.repaintEverything();
156 }
157
158
159 var relationJPMap={
160 suggestion:"提案",
161 refutation:"反論",
162 question:"質問"
163 };
164 function updateNode(node){
165 if(updateClaimElement(node)){
166 var fc=$("#treeRoot")[0].firstChild;
167 if(fc)$("#treeRoot")[0].insertBefore(node.view[0],fc);
168 else $("#treeRoot").append(node.view);
169 }
170 node.view.css({
171 left:node.position.x*ViewParam.intervalX-ViewParam.nodeWidth/2,
172 top:node.position.y*ViewParam.intervalY-ViewParam.nodeHeight/2
173 });
174 var childs=node.mentions;
175 for(var i=0;i<childs.length;i++){
176 var child=childs[i];
177 var created=!child.view;
178 updateNode(child);
179 if(created){
180 var c=jsPlumb.connect({source:node.view[0],target:child.view[0]});
181 c.setLabel({label:"<span style='color:white'>"+(relationJPMap[child.relation]||child.relation)+"</span>",cssStyle:"color:white"});
182 }
183 }
184 }
185
186 var focusedUser=null;
187 function setFocusedShadowEverything(){
188 function recFocusShadow(node){
189 setFocusedShadow(node);
190 for(var i=0;i<node.mentions.length;i++){
191 recFocusShadow(node.mentions[i]);
192 }
193 }
194 recFocusShadow(treeInfo.root);
195 }
196 function setFocusedShadow(node){
197 var name=focusedUser||userName;
198 var color;
199 console.log(node.info.author)
200 if(node.info.author==name)color="#afa";
201 else{
202 var users=node.info.users,status;
203 for(var i=0;i<users.length;i++){
204 var u=users[i];
205 if(u.id==name){status=u.status;break;}
206 }
207 color=({agreed:"#aaf",denied:"#faa",pend:"white",unknown:"white"})[status];
208 }
209 node.view.css("box-shadow",color?color+" 0 0 30px":"none");
210 }
211 function updateClaimElement(node){
212 var created=false;
213 if(!node.view){
214 created=true
215 node.view=$("<div class='claimNode'/>");
216 node.view.click(function(){showClaim(node);});
217 node.view.hover(
218 function(){div.css("box-shadow","white 0 0 50px");showUserList(node.info.users,node.info.author)},
219 function(){try{setFocusedShadow(node);}catch(e){console.log(e);}showUserList([])}
220 )
221 }
222 setFocusedShadow(node);
223 var div=node.view;
224 div.text(node.info.toulmin.title);
225 var statusBackground={pass:"#aaf",unknown:"#fff",failed:"#faa",fail:"#faa"};
226 var statusBorder={pass:"#66a",unknown:"#aaa",failed:"#a66",fail:"#a66"};
227 div.css("background",statusBackground[node.info.status]||"white");
228 div.css("border-color",statusBorder[node.info.status]||"white");
229 return created;
230 }
231
232
233 function showUserList(users,author){
234 var statusMap={};
235 var userListElement=$(".userList");
236 userListElement.text('')
237 if(author)statusMap['#'+author]='author';
238 for(var i=0;i<users.length;i++){
239 statusMap['#'+users[i].id]=users[i].status;
240 }
241 for(var i=0;i<userList.length;i++){
242 var u=userList[i];
243 var ue=createUserElement(u==userName?"あなた("+u+")":u,statusMap['#'+u]);
244 if(u==userName){
245 ue.css({fontWeight:"bold"})
246 }
247 ue.appendTo(userListElement);
248 with({name:u,element:ue}){
249 ue.hover(
250 function(){
251 element.css("opacity",1);
252 focusedUser=name;setFocusedShadowEverything()
253 },
254 function(){
255 element.css("opacity",0.5);
256 focusedUser=userName;setFocusedShadowEverything()
257 }
258 )
259 }
260
261 }
262 $(".userList").css("opacity","1");
263 }
264 function hideUserList(){
265 $(".userStatus").css("background","none");
266 $(".userItem").css("opacity","1");
267 $(".userList").css("opacity","0.2");
268 }
269 </script>
270 <style>
271 div.claimNode{
272 z-index:20;
273 position:absolute;width:92px;height:40px;font-size:12px;padding:4px;background:white;
274 border:2px solid silver;
275 overflow:hidden;
276 border-radius:5px;
277 cursor:pointer;
278 }
279 body{background-color:black;}
280
281 div.userList{
282 position:fixed;
283 z-index:30;
284 right:0;top:0;
285 width:160px;
286 }
287 div.header{
288 position:absolute;
289 left:0;top:0;
290 z-index:5;
291 height:50px;
292 width:100%;
293 background:#223;
294 background:-webkit-gradient(linear,left top,left bottom,from(#002),to(#223));
295 color:silver;
296 font-size:40px;
297 }
298
299
300 </style>
301 <script>
302 function resetMentionForm(){
303 var keys=['title','contents','w','d','b','q','r'];
304 for(var i=0;i<keys.length;i++)$("#mentionform_"+keys[i]).val("");
305 $("#mention_option")[0].className="option";
306 }
307 var formClaim;
308 var claimUserMap,mentionUserMap;
309 function showClaim(claim){
310 formClaim=claim;
311 var info=claim.info;
312 var keys=['title','contents','w','d','b','q','r'];
313 for(var i=0;i<keys.length;i++)$("#claimform_"+keys[i]).val(info.toulmin[keys[i]]);
314
315 var status="";
316 for(var i=0;i<info.users.length;i++)if(info.users[i].id==userName)status=info.users[i].status;
317 var op=({denied:1,pend:2,agreed:3})[status];
318
319 $("#claim_status").text(info.status)
320 $("#claim_status").css("color",({pass:"blue",failed:"red",fail:"red",unknown:"black"})[info.status]);
321 $("#agree_option")[0].className="option"+(op?" option"+op:"");
322 $("#agree_option").css("display",status?"block":"none");
323
324 $("#claim_button").css("display",(userName==info.author)?"block":"none");
325 $("#claimvote_option").css("display",status?"block":"none");
326
327 $("#claimbody")[0].className="claim_contents";
328 $("#mentionbody")[0].className="mention_contents";
329
330 $("#claim_author").text(info.author);
331 $("#mention_author").text(userName);
332 $("#claimvote_option")[0].className="option option"+(claim.agreeType=="majority"?2:1);
333 $("#mentionvote_option")[0].className="option option1";
334 var stateMap={};
335 for(var i=0;i<info.users.length;i++)stateMap['#'+info.users[i].id]=info.users[i].status;
336 claimUserMap=new HashSet(info.users.map(function(u){return u.id}));
337 mentionUserMap=new HashSet();
338 $("#claim_users").text("");
339 $("#mention_users").text("");
340 if(userName!=info.author)mentionUserMap.add(info.author);
341 for(var i=0;i<userList.length;i++){
342 var name=userList[i];
343 if(name!=info.author){
344 var status=stateMap['#'+name];
345 createUserSelectItem(name,status,claimUserMap).appendTo($("#claim_users"));
346 }if(name!=userName){
347 createUserSelectItem(name,name==info.author?"unknown":"",mentionUserMap).appendTo($("#mention_users"));
348 }
349 }
350 resetMentionForm();
351 popupShowMain()
352 }
353
354
355 function claimSave(){
356 var claim=formClaim;
357 var info=claim.info;
358 var id=claim.id||root_id;
359 var agreeType=[null,"unanimously","majority"][($('#claimvote_option')[0].className.match("[0-9]+")||"0")[0]];
360 var title=$('#claimform_title').val();
361 var contents=$('#claimform_contents').val();
362 var d=$('#claimform_d').val();
363 var w=$('#claimform_w').val();
364 var b=$('#claimform_b').val();
365 var q=$('#claimform_q').val();
366 var r=$('#claimform_r').val();
367 var users=claimUserMap.toArray();
368 var errors=[];
369 if(!title)errors.push("タイトル");
370 if(!agreeType)errors.push("採決方法");
371 if(users.length==0)errors.push("同意を取るユーザ");
372 if(errors.length){
373 alert("未入力項目:"+errors.join(", "));
374 }else{
375 $.ajax({
376 url:BASE_URL+"/claims/edit/"+id,
377 success:function(o){loadConsensus(root_id)},
378 type:"POST",cache:false,
379 contentType:"application/json",
380 data:JSON.stringify({type:agreeType,toulmin:{title:title,contents:contents,q:q,d:d,w:w,b:b,r:r},author:userName,users:users}),
381 error:function(o){console.log("ERROR",o)}
382 });
383 popupHideAll();
384 }
385 }
386 function claimAgree(status){
387 var claim=formClaim;
388 var info=claim.info;
389 var id=claim.id||root_id;
390 $.ajax({
391 url:BASE_URL+"/claims/answer/"+id+"/"+userName+"/"+status,
392 success:function(o){loadConsensus(root_id)},
393 type:"POST",cache:false,
394 error:function(o){console.log("ERROR",o)}
395 });
396 popupHideAll();
397 }
398 function mentionSave(){
399 var claim=formClaim;
400 var info=claim.info;
401 var id=claim.id||root_id;
402 var mentionType=[null,"refutation","question","suggestion"][($('#mention_option')[0].className.match("[0-9]+")||"0")[0]];
403 var agreeType=[null,"unanimously","majority"][($('#mentionvote_option')[0].className.match("[0-9]+")||"0")[0]];
404 var title=$('#mentionform_title').val();
405 var contents=$('#mentionform_contents').val();
406 var d=$('#mentionform_d').val();
407 var w=$('#mentionform_w').val();
408 var b=$('#mentionform_b').val();
409 var q=$('#mentionform_q').val();
410 var r=$('#mentionform_r').val();
411 var users=mentionUserMap.toArray();
412 var author=userName;
413 var errors=[];
414 if(!title)errors.push("タイトル");
415 if(!agreeType)errors.push("採決方法");
416 if(!mentionType)errors.push("反論質問提案");
417 if(users.length==0)errors.push("同意を取るユーザ");
418 if(errors.length){
419 alert("未入力項目:"+errors.join(", "));
420 }else{
421 $.ajax({
422 url:BASE_URL+"/claims/"+mentionType+"/"+id+"/create",
423 success:function(o){loadConsensus(root_id)},
424 type:"POST",cache:false,contentType:"application/json",
425 data:JSON.stringify({type:agreeType,toulmin:{title:title,contents:contents,q:q,d:d,w:w,b:b,r:r},author:author,users:users}),
426 error:function(o){console.log("ERROR",o)}
427 });
428 popupHideAll();
429 }
430 }
431
432 </script>
433 <div class='header'>
434 <nobr id='header_title'>R-Consensus : loading</nobr>
435 </div>
436
437 <div style="position:relative;left:0;top:0;" id='treeMain'>
438 <div style="position:absolute;width:0;height:0;left:100;" id='treeRoot'>
439 </div>
440 </div>
441
442 <div class='userList'></div>
443
444
445 <div id='popup_base' style='display:none;z-index:100'>
446 <div id='popup_background'></div>
447 <div class='popup_center'>
448 <div class='claiminfo' id='claiminfo'>
449 <div class='claim_title'><input placeholder="title" id='claimform_title'></div>
450 <div id='claimbody' class='claim_contents'>
451 <div class='claim_menu'>
452 <div class='menu_item menu_contents' onclick="$('#claimbody')[0].className='claim_contents'">Contents</div>
453 <div class='menu_item menu_toulmin' onclick="$('#claimbody')[0].className='claim_toulmin'">Toulmin</div>
454 <div class='menu_item menu_users' onclick="$('#claimbody')[0].className='claim_users'">Users</div>
455 <div id='claim_status'></div>
456 </div>
457 <div class='claim_main main_contents'>
458 <textarea placeholder='contents' id='claimform_contents'></textarea>
459 </div>
460 <div class='claim_main main_toulmin'>
461 <div class='item_toulmin'><span>データ</span><input id='claimform_d'></div>
462 <div class='item_toulmin'><span>論拠 </span><input id='claimform_w'></div>
463 <div class='item_toulmin'><span>裏付け</span><input id='claimform_b'></div>
464 <div class='item_toulmin'><span>限定詞</span><input id='claimform_q'></div>
465 <div class='item_toulmin'><span>反駁 </span><input id='claimform_r'></div>
466 </div>
467 <div class='claim_main main_users'>
468 <span class='author_label'>作者:</span>
469 <span class='author_name' id='claim_author'></span>
470 <div class='option option1' id='claimvote_option'>
471 <span class='option option1 vote1' onclick="$('#claimvote_option')[0].className='option option1'">全会一致</span>
472 <span class='option option2 vote2' onclick="$('#claimvote_option')[0].className='option option2'">多数決</span>
473 </div>
474 <div id='claim_users'></div>
475 </div>
476 </div>
477 <div class='claim_footer'>
478 <span onclick='popupShowSubMain()' class='button mention_button'>mention</span>
479 <div class='option' id='agree_option'>
480 <span class='option option1 agree1' onclick="$('#agree_option')[0].className='option option1';claimAgree('denied');">否認</span>
481 <span class='option option2 agree2' onclick="$('#agree_option')[0].className='option option2';claimAgree('pend');">保留</span>
482 <span class='option option3 agree3' onclick="$('#agree_option')[0].className='option option3';claimAgree('agreed');">合意</span>
483 </div>
484 <div id='claim_button'>
485 <span class='button cancel' onclick="popupHideAll()">cancel</span>
486 <span class='button save' onclick="claimSave()">save</span>
487 </div>
488 </div>
489 <div class='cover' id='claim_cover'></div>
490 </div>
491
492
493 <div class='mentioninfo' id='mentioninfo'>
494 <div class='claim_title'><input placeholder="title" id='mentionform_title'></div>
495 <div id='mentionbody' class='mention_contents'>
496 <div class='claim_menu'>
497 <div class='menu_item menu_contents' onclick="$('#mentionbody')[0].className='mention_contents'">Contents</div>
498 <div class='menu_item menu_toulmin' onclick="$('#mentionbody')[0].className='mention_toulmin'">Toulmin</div>
499 <div class='menu_item menu_users' onclick="$('#mentionbody')[0].className='mention_users'">Users</div>
500 </div>
501 <div class='mention_main main_contents'>
502 <textarea placeholder='contents' id='mentionform_contents'></textarea>
503 </div>
504 <div class='mention_main main_toulmin'>
505 <div class='item_toulmin'><span>データ</span><input id='mentionform_d'></div>
506 <div class='item_toulmin'><span>論拠 </span><input id='mentionform_w'></div>
507 <div class='item_toulmin'><span>裏付け</span><input id='mentionform_b'></div>
508 <div class='item_toulmin'><span>限定詞</span><input id='mentionform_q'></div>
509 <div class='item_toulmin'><span>反駁 </span><input id='mentionform_r'></div>
510 </div>
511 <div class='mention_main main_users'>
512 <span class='author_label'>作者:</span>
513 <span class='author_name' id='mention_author'></span>
514 <div class='option option1' id='mentionvote_option'>
515 <span class='option option1 vote1' onclick="$('#mentionvote_option')[0].className='option option1'">全会一致</span>
516 <span class='option option2 vote2' onclick="$('#mentionvote_option')[0].className='option option2'">多数決</span>
517 </div>
518 <div id='mention_users'></div>
519 </div>
520 </div>
521 <div class='claim_footer'>
522 <div class='option' id='mention_option'>
523 <span class='option option1 mention1' onclick="$('#mention_option')[0].className='option option1'">反論</span>
524 <span class='option option2 mention2' onclick="$('#mention_option')[0].className='option option2'">質問</span>
525 <span class='option option3 mention3' onclick="$('#mention_option')[0].className='option option3'">提案</span>
526 </div>
527 <span class='button cancel' onclick="popupShowMain()">cancel</span>
528 <span class='button save' onclick="mentionSave()">save</span>
529 </div>
530 <div class='cover' id='mention_cover'></div>
531 </div>
532 </div>
533 </div>