Mercurial > hg > Members > nobuyasu > html > graphViewer
changeset 11:8c4171f77fcc draft
add show.html
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 20 Mar 2013 15:25:09 +0900 |
parents | 3fa1be92ab48 |
children | 549962a324ac |
files | show.html |
diffstat | 1 files changed, 635 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/show.html Wed Mar 20 15:25:09 2013 +0900 @@ -0,0 +1,635 @@ +#{extends 'main.html' /} +#{set title:messages.get('AAEvidenceSiftingModel.userdesktops.show.title') /} +<link rel='stylesheet' href="/aat/public/viewer/css/viewer_form.css"> +<script src="@{'/public/viewer/js/lib/jquery-1.8.1-min.js'}" type="text/javascript" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/lib/jquery-ui-1.8.23-min.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/lib/jquery.ui.touch-punch.min.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/lib/jsBezier-0.4-min.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-util-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-dom-adapter-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-defaults-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-renderers-svg-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-renderers-canvas-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jsPlumb-renderers-vml-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jquery.jsPlumb-1.3.15-RC1.js'}" charset="${_response_encoding}"></script> +<script type="text/javascript" src="@{'/public/viewer/js/1.3.15/jquery.jsPlumb-1.3.15-all-min.js'}" charset="${_response_encoding}"></script> + +<div id="page"> + <div class="title"> + &{'AAEvidenceSiftingModel.userdesktops.show.title'} [ ${desktop.project.name} ] + </div> + <ul > + <li>> <a href="@{AAEvidenceSiftingModel.UserHomes.index()}">&{'navigation.back'}</a></li> + <li>> <a href="@{AAEvidenceSiftingModel.Projects.show(desktop.id)}">&{'AAEvidenceSiftingModel.projects.show.title'}</a></li> + </ul> +</div> + + +<div id="traverseDisplay" style='position:fixed; width:250px; height:250px; border:solid 1px; border-radius:5px; opacity:1; z-index:10; visibility:visible;'> + <div style='position:absolute; left:0; top:0; width:100%; height:100%; background:black; opacity:0.7;'></div> + <div id="closeTraverseDisplay" style='position:absolute; right:5; top:-3; z-index:10; color:white;' onclick="$('#traverseDisplay').css('visibility','hidden');" onmouseover="$('#closeTraverseDisplay').css('color','yellow');" onmouseout="$('#closeTraverseDisplay').css('color','white')" >CLOSE</div> + <div style='position:absolute; width:90%; height:90%;'> + <div style='position:absolute; left:5%; top:5%; width:100%; height:100%; background:white;'> + <div id="traverseDisplayTitle" style='position:absolute; left:10px; top:5px; font-size:24px; width:100%; text-align:left;'> + Traverse + </div> + <div style='position:absolute; top:30px; width:100%; margin-left:10px;'> Direction: + <label style='position:relative;' ><input id="direction_in" type='checkbox' checked value='in'/>IN</label> + <label style='position:relative;'><input id="direction_out" type='checkbox' checked value='out'/>OUT</label> + </div> + <div id="traverseDisplayBody" style='position:absolute; left:20px; top:50px;'> + Please click any node. + </div> + </div> + </div> + <span class='button display' style='position:absolute; width:100; left:75; bottom:5; opacity:1;' onclick='traverseAction();'>traverse</span> +</div> + +<div id="miniDisplay" style='position:fixed; width:250px; height:250px; border:solid 1px; border-radius:5px; opacity:1; z-index:10; visibility:visible;'> + <div style='position:absolute; left:0; top:0; width:100%; height:100%; background:black; opacity:0.5;'></div> + <div id="closeMiniDisplay" style='position:absolute; right:5; top:-3; z-index:10; color:white;' onclick="$('#miniDisplay').css('visibility','hidden');" onmouseover="$('#closeMiniDisplay').css('color','yellow');" onmouseout="$('#closeMiniDisplay').css('color','white')" >CLOSE</div> + <div style='position:absolute; width:90%; height:90%;'> + <div style='position:absolute; left:5%; top:5%; width:100%; height:100%; background:white;'> + <div id="miniDisplayTitle" style='position:absolute; left:10px; top:5px; font-size:24px; width:100%; text-align:left;'> + </div> + <div id="miniDisplayBody" style='position:absolute; left:20px; top:40px;'> + Please click any node. + </div> + </div> + </div> +</div> + +<div class="graphMainCss" style="position:absolute; left:0; bottom:0; width:100%; height:75%;" id='graphMain'> + <div style="position:absolute; width:0; height:0;left:0;" id='graphRoot'> + </div> +</div> + + +<script type="text/javascript"> +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; + } +} + +function GraphData() { + var graphData = {}; + graphData.nodes = {}; + graphData.edges = {}; + return graphData; +} + + +function Edge(fromNode, toNode, relation) { + var obj = {from:fromNode, to:toNode, rel:relation }; + return obj; +} + +function beginScript() { + DragHandler.attach($('#miniDisplay')[0]); + DragHandler.attach($('#traverseDisplay')[0]); +} + +var DragHandler = { + _oElem : null, + _id : null, + attach : function(oElem) { + oElem.onmousedown = DragHandler._dragBegin; + return oElem; + }, + attach : function(oElem, id) { + oElem.onmousedown = DragHandler._dragBegin; + _id = id; + return oElem; + }, + _dragBegin : function(e) { + var oElem = DragHandler._oElem = this; + if (isNaN(parseInt(oElem.style.left))) { oElem.style.left = '0px'; } + if (isNaN(parseInt(oElem.style.top))) { oElem.style.top = '0px'; } + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + e = e ? e : window.event; + oElem.mouseX = e.clientX; + oElem.mouseY = e.clientY; + document.onmousemove = DragHandler._drag; + document.onmouseup = DragHandler._dragEnd; + return false; + }, + _drag : function(e) { + var oElem = DragHandler._oElem; + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + e = e ? e : window.event; + var nextX = x + (e.clientX - oElem.mouseX); + var nextY = y + (e.clientY - oElem.mouseY); + oElem.style.left = nextX + 'px'; + oElem.style.top = nextY + 'px'; + oElem.mouseX = e.clientX; + oElem.mouseY = e.clientY; + if (_id) { + var node = GRAPH_DATA.nodes[_id]; + node.position.x = nextX; + node.position.x = nextY; + } + return false; + }, + _dragEnd : function() { + var oElem = DragHandler._oElem; + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + document.onmousemove = null; + document.onmouseup = null; + DragHandler._oElem = null; + } + +}; + +function addLoadEvent(func) { + var oldonload = window.onload; + if (typeof window.onload != 'function') { + window.onload = func; + } else { + window.onload = function() { + if (oldonload) { + oldonload(); + } + func(); + } + } +} + +addLoadEvent(function() { + beginScript(); +}); + +function writeMiniDisplay(title,str) { + $('#miniDisplayBody')[0].innerHTML = str; + if(title) { + $('#miniDisplayTitle')[0].innerHTML = title; + } +} + +function writeJSONDataToMiniDisplay(jsonObj) { + var str = ""; + for (var key in jsonObj.property) { + if (key != 'edgeInfo' ) { + str = str + key + ": "+ jsonObj.property[key] + "<br>"; + } + } + writeMiniDisplay(jsonObj.property.title, str); +} + +function getTraverseDivTemplate(kind, inNum, outNum) { + return "<div><label id='traverseLabel'><input type='checkbox' checked value='"+kind+"'/>"+kind+"</label><br>in:"+inNum+" out:"+outNum+"</div>"; +} + +function createTraverseView(info) { + var viewHtml = ""; + for (var kind in info) { + var data = info[kind]; + var inNum = 0; + var outNum = 0; + if (data['in']) { + inNum = data['in']; + } + if (data['out']) { + outNum = data['out']; + } + viewHtml = viewHtml + getTraverseDivTemplate(kind, inNum, outNum); + } + return viewHtml; +} + +function createEdgeInfoView(node) { + var id = node.property.id; + var edgeInfo = node.property.edgeInfo; + var str = ""; + var info = {}; + for (var i=0; i<edgeInfo.length; i++) { + var kind = edgeInfo[i].kind; + var dir = edgeInfo[i].direction; + var num = edgeInfo[i].num; + info[kind] = {}; + info[kind][dir] = num; + } + var viewHTML = createTraverseView(info); + edgeInfo.viewHtml = viewHTML; + $('#traverseDisplayBody')[0].innerHTML = viewHTML; +} + +function init() { + jsPlumb.importDefaults({ + Connector : [ "Straight", { curviness:50 } ], + PaintStyle : { strokeStyle:"gray", lineWidth:2 }, + EndpointStyle : {}, + Anchors: ["BottomCenter","TopCenter"], + }); + var rootDiv = $('#graphMain'); + var rootLeft = rootDiv.offset().left; + var rootTop = rootDiv.offset().top; + $('#traverseDisplay').css( { + left: rootLeft, + top: rootTop + }); + var heightStr = $('#traverseDisplay').css('height').split('px')[0]; + var height = parseInt(heightStr); + $('#miniDisplay').css( { + left: rootLeft, + top: rootTop + height + 50 + }); +} + +function showMiniDisplay(node) { + $("#miniDisplay").css("visibility", "visible"); + writeJSONDataToMiniDisplay(node); +} + +function showTraverseDisplay(node) { + this.id = node.property.id; + if (!node.property.edgeInfo) { console.log("not found node.edgeInfo "); return; } + if (!node.property.edgeInfo.viewHtml) { + createEdgeInfoView(node); + } + $('#traverseDisplayBody')[0].innerHTML = node.property.edgeInfo.viewHtml; + $("#traverseDisplay").css("visibility", "visible"); +} + +var nodeNum = 0; +var OFFSET = 200; +var miniD = $('#miniDisplay')[0].style; +var offsetLeft = parseInt(miniD.width.split('px')[0]); +var offsetTop = parseInt(miniD.height.split('px')[0]); +function calcNewNodePosition() { + var position = {}; + position = {x: offsetLeft, y: nodeNum*OFFSET + offsetTop / 3}; + nodeNum++; + return position; +} + +/* + * + */ +function clickNodeDiv(id) { + var graphData = GRAPH_DATA; + var node = graphData.nodes[id]; + var rels = {evidence:1, + dependency:1, + derived:1, + version:1, + agreement:1}; + showRelationNodes(graphData, node, rels); +} + +function addEdgeInfo(id, kind, direction) { + var nodes = GRAPH_DATA.nodes; + var edges = GRAPH_DATA.edges; + +} + +function showEdgesAndNodes(graphData,jsonData) { + var nodes = graphData.nodes; + var jsonNodes = jsonData.nodes; + for (var i=0; i<jsonNodes.length; i++) { + var id = jsonNodes[i].id; + updateNode(nodes[id]); + } + var edges = graphData.edges; + var jsonEdges = jsonData.edges; + for (var i=0; i<edges.lenght; i++) { + var id = jsonEdges[i].id; + showEdge(graphData, edges[id]); + } + showAllEdge(graphData); +} + +function getEvidence(id, kind, direction) { + var u = "/aat/aaevidencesiftingmodel.userdesktops/get?id="+id+"&kind="+kind/*+"?direction="+direction;*/; + $.ajax({ + url:u, + success:function(o) { parseJSONGraphData(GRAPH_DATA, o); recursiveCalcPosition(GRAPH_DATA, GRAPH_DATA.nodes[id]); showEdgesAndNodes(GRAPH_DATA, o);}, + type:"GET", cache:true, + error:function(o) { console.log("getEvidence error : ", o); } + }); +} + +function traverseAction() { + var inDirChecked = $('#direction_in')[0].checked; + var outDirChecked = $('#direction_out')[0].checked; + var labelTags = $('[id=traverseLabel]'); + var kinds = []; + for (var i=0;i<labelTags.length; i++ ) { + var inputTag = labelTags[i].children[0]; + if (inputTag.checked) { + kinds.push(inputTag.value); + } + } + var id = this.id; + for (var i=0; i<kinds.length; i++) { + var kind = kinds[i]; + if (inDirChecked) getEvidence(id, kind, "in"); + if (outDirChecked) getEvidence(id, kind, "out"); + } + +} + +function createNodeDiv(node) { + node.view = $("<div class='graphNode'/>"); + node.view.click(function(){ clickNodeDiv(node.property.id) }); + if(!node.position) node.position = calcNewNodePosition(); + node.view.hover(); + var div = $("<div class='graphNodeContent' />")[0]; + div.innerHTML = node.property.title; + node.view[0].appendChild(div); + return node; +} + +function updateNodeElement(node) { + var created = false; + console.log("node = +",node); + if(!node.view) { + created = true; + createNodeDiv(node); + } + var div = node.view; + // div.text(node.property.title); + div.click(function(){showMiniDisplay(node); showTraverseDisplay(node);}); + DragHandler.attach($(node.view)[0], node.property.id); + var kindBackground = {agree:"#aaf", rejected:"#fff"}; + var kindBorder = {agree:"#66a", rejected:"#a66"}; + div.css("background", kindBackground[node.kind]||"white"); + div.css("border-color", kindBorder[node.kind] ||"#58f"); + div.css({ + left: node.position.x, + top: node.position.y + }); + return created; +} + + +function updateNode(node) { + if(updateNodeElement(node)) { + var fc = $('#graphRoot')[0].firstChild; + if(fc) { + $('#graphRoot')[0].insertBefore(node.view[0], fc); + } else { + $('#graphRoot').append(node.view); + } + } +} + +var ViewParam = { + offsetTop:100, + offsetBottom:100, + offsetLeft:100, + offsetRight:100, + nodeWidth:120, + nodeHeight:60, + intervalX:140, + intervalY:120 +}; + +var arrowConnector = { + connector:"StateMachine", + // paintStyle:{lineWidth:3,strokeStyle:"#056"}, + paintStyle:{lineWidth:2,strokeStyle:"#aaf"}, + hoverPaintStyle:{strokeStyle:"#dbe300"}, + endpoint:"Blank", + anchor:"Continuous", + overlays:[ ["PlainArrow", {location:1, width:20, length:12} ]] +}; + +var arrowBothConnector = { + connector:"StateMachine", + paintStyle:{lineWidth:2,strokeStyle:"#aaf"}, + hoverPaintStyle:{strokeStyle:"#dbe300"}, + endpoint:"Blank", +}; + +function parseJSONGraphData(memory ,jsonObj) { + var nodes = jsonObj.nodes; + for (var i=0; i<nodes.length; i++) { + var node = nodes[i]; + if (memory.nodes[node.id]) continue; + memory.nodes[node.id] = {}; + memory.nodes[node.id].in = []; + memory.nodes[node.id].out = []; + memory.nodes[node.id].both = []; + memory.nodes[node.id].property = node; + } + if (!jsonObj.edges) return memory; + var edges = jsonObj.edges; + for (var i=0; i<edges.length; i++) { + var edge = edges[i]; + var edgeId = edge.id; + if (memory.edges[edgeId]) continue; + memory.edges[edgeId] = {}; + memory.edges[edgeId].property = edge; + if (edge.kind == "both") { + memory.nodes[edge.from].both.push(edgeId); + memory.nodes[edge.to].both.push(edgeId); + } else { + memory.nodes[edge.from].out.push(edgeId); + memory.nodes[edge.to].in.push(edgeId); + } + } + return memory; +} + +function showEdge(graphData, edge) { + function connectEdge(fromNode, toNode, rel, type) { + var c; + if (type == 'both') { + c = jsPlumb.connect({source:fromNode.view[0], target:toNode.view[0]}, arrowBothConnector); + } else { + c = jsPlumb.connect({source:fromNode.view[0], target:toNode.view[0]}, arrowConnector); + } + // jsPlumb.select({source:fromNode.view[0]}).removeAllOverlays(); + c.setLabel({label:"<span style='color:#129; font-size:1.5em;'>"+rel+"</span>",cssStyle:""}); + return c; + } + if (edge.visible) return; + var fromNode = graphData.nodes[edge.property.from]; + var toNode = graphData.nodes[edge.property.to]; + if (!fromNode.view && !toNode.view) return; + var rel = edge.property.rel; + var type = edge.property.type; + connectEdge(fromNode, toNode, rel, type); + edge.visible = true; +} + +function createNodeFromEdge(graphData, edge, baseNode) { + if(edge.visible) return; + var fromNode = graphData.nodes[edge.property.from]; + if (!fromNode.view) { + updateNode(fromNode); + } + var toNode = graphData.nodes[edge.property.to]; + if (!toNode.view) { + updateNode(toNode); + } + showEdge(graphData, edge); +} + +function getRelationEdgeIds(node) { + var edgeIds = []; + for (var i=0; i<node.in.length; i++) edgeIds.push(node.in[i]); + for (var i=0; i<node.out.length; i++) edgeIds.push(node.out[i]); + for (var i=0; i<node.both.length; i++) edgeIds.push(node.both[i]); + return edgeIds; +} + +function getRelationNodeIds(graphData, node) { + var nodes = graphData.nodes; + var edges = graphData.edges; + var nodeIds = []; + for (var i=0; i<node.in.length; i++) { + var edgeId = node.in[i]; + nodeIds.push(edges[edgeId].property.from); + } + for (var i=0; i<node.out.length; i++) { + var edgeId = node.out[i]; + nodeIds.push(edges[edgeId].property.to); + } + for (var i=0; i<node.both.length; i++) { + var edgeId = node.both[i]; + var fromId = edges[edgeId].property.from; + var toId = edges[edgeId].property.to; + if (fromId == node.property.id) { + nodeIds.push(toId); + } else { + nodeIds.push(fromId); + } + } + return nodeIds; +} + +/* + * This function output all NODE that are related [node] + */ +function updateRelationNodes(graphData, node) { + var id = node.property.id; + var edges = graphData.edges; + var edgeIds = getRelationEdgeIds(node); + for (var i=0; i<edgeIds.length; i++ ) { + createNodeFromEdge(graphData, edges[edgeIds[i]]); + } + jsPlumb.removeAllEndpoints(); + jsPlumb.draggable($('.graphNode')); +} + +/* + * rels = {dependency:1, evidence:1}; + * showRelationNodes(graphData, node, rels); + */ +function showRelationNodes(graphData, node, rels) { + var id = node.property.id; + var edges = graphData.edges; + var edgeIds = getRelationEdgeIds(node); + for (var i=0; i<edgeIds.length; i++) { + var edge = edges[edgeIds[i]]; + if (rels[edge.property.rel]) { + createNodeFromEdge(graphData, edges[edgeIds[i]]); + } + } + jsPlumb.removeAllEndpoints(); + jsPlumb.draggable($('.graphNode')); +} + +var BASE_THETA = -30; +var BASE_ANGLE = 180; +var BASE_DISTANCE = 180; +function calcChildNodePosition(parent, num) { + var pX = parent.position.x; + var pY = parent.position.y; + var deg = BASE_ANGLE - num * BASE_THETA; + var theta = deg * (Math.PI / 180); + var cX = pX - (BASE_DISTANCE * Math.cos(theta)); + var cY = pY - (BASE_DISTANCE * Math.sin(theta)); + return {x:cX, y:cY}; +} + +function showAllEdge(graphData) { + var edges = graphData.edges; + for (var id in edges) { + showEdge(graphData, edges[id]); + } + jsPlumb.removeAllEndpoints(); + jsPlumb.draggable($('.graphNode')); +} + +var EDGE_LIST = { + evidence:'evidence', + dependency:'dependency', + version:'version', + derived:'derived', + agreement:'agreement' +}; + +function recursiveCalcPosition(graphData, parentNode) { + if (!parentNode.position) updateNode(parentNode); + childNodeIds = getRelationNodeIds(graphData, parentNode); + /* calcration of childNode position */ + var numCalcChild = 0; + var childArray = {}; + for (var i=0; i<childNodeIds.length; i++) { + var id = childNodeIds[i]; + var childNode = graphData.nodes[id]; + childArray[id] = childNode; + if (!childNode.position) { + childNode.position = calcChildNodePosition(parentNode, numCalcChild); + numCalcChild++; + } + } + /* calcration of grandchildNode position */ + for (var id in childArray) { + var childNode = childArray[id]; + var grandChildIds = getRelationNodeIds(graphData, childNode); + for (var i=0; i<grandChildIds.length; i++) { + var gId = grandChildIds[i]; + var grandChild = graphData.nodes[gId]; + if (!grandChild.position) { + recursiveCalcPosition(graphData, childNode); + } + } + } +} + +var GRAPH_DATA = new GraphData(); +function startUserDesktopUI() { + function showFirstEvidenceList(graphData) { + var nodes = graphData.nodes; + for (var id in nodes) { + updateNode(nodes[id]); + } + } + var gData = GRAPH_DATA; + showFirstEvidenceList(gData); +} + +function start() { + init(); + $.ajax({ + url:"/aat/aaevidencesiftingmodel.userdesktops/get", + success:function(o) { parseJSONGraphData(GRAPH_DATA, o); startUserDesktopUI();}, + type:"GET", cache:false, + error:function(o) { console.log("first get error : ",o); } + }); +} + +$(function() { + start(); +}) + + +</script> + + + + +