var PATHNUM = 0;
var MAXDEPTH = 0;
var TREESPACE = 0;
var NODEHEIGHT = 0;
var DRAWHEIGHT = 0;
var MOUSEMOVED = 0;
var endpoint = "";
var startclass= "";
var endclass = "";
var defendpoint = "";
var defstartclass= "";
var defendclass = "";
var jsontext = "";
var pathobj = "";
var pathlimit = 10;
// ページ読み込みが完了次第実行
$(function(){
// ページのパーツ部分を追加
initparts();
getParameter();
if(defendpoint != "" && defstartclass != "" && defendclass != ""){
openSPARQLBuilder();
}
});
function initparts(){
var sbdiv = $('div#SPARQLBUILDER');
if(sbdiv.find('div').length == 0){
var sbtop = '
';
sbdiv.html(sbtop);
$('body').append(sbmodal);
}
$('.SBModalView').click(function(){
$(this).fadeOut(700);
});
$('.SBModalContents').click(function(){
event.stopPropagation();
});
loadEndPointList();
$(".SBEndPointSelect").change(function() {
changeEndPoint();
});
$(".SBStartClassSelect").change(function() {
startClass = $(".SBStartClassSelect").val();
loadPathList();
});
$(".SBEndClassSelect").change(function() {
endClass = $(".SBEndClassSelect").val();
loadPathList();
});
}
function getParameter()
{
if( 1 < window.location.search.length )
{
var query = window.location.search.substring( 1 );
var parameters = query.split( '&' );
for( var i = 0; i < parameters.length; i++ )
{
var element = parameters[ i ].split( '=' );
if(decodeURIComponent( element[ 0 ] ) == "ep"){
defendpoint = decodeURIComponent( element[ 1 ] )
}else if(decodeURIComponent( element[ 0 ] ) == "st"){
defstartclass = decodeURIComponent( element[ 1 ] )
}else if(decodeURIComponent( element[ 0 ] ) == "en"){
defendclass = decodeURIComponent( element[ 1 ] )
}
}
}
}
function openSPARQLBuilder(){
$('.SBModalView').css('top', $(window).scrollTop()).css('height', window.innerHeight).fadeIn();
var mvw = $('.SBModalContents').width();
var mvh = $('.SBModalContents').height();
$('.SBModalContents .SBSelects').css('width', (mvw - 201) + 'px').css('height', 30 + 'px');
$('.SBModalContents .SBMessage').css('width', 200 + 'px').css('height', 30 + 'px');
$('.SBModalContents .SBGraph').css('width', (mvw - 201) + 'px').css('height', (mvh - 31) + 'px');
$('.SBModalContents .SBSelectedPath').css('width', 180 + 'px').css('height', (mvh - 51 - 26) + 'px');
$('.SBModalContents .SBModalButtons').css('width', 200 + 'px').css('height', '26px');
$(".SBEndPointSelect").select2();
$(".SBStartClassSelect").select2();
$(".SBEndClassSelect").select2();
if(defendpoint != "" && defstartclass != "" && defendclass != ""){
$('.SBStartClassSelect').on('lccomplete', function(){
$('.SBStartClassSelect').val(defstartclass);
defstartclass = "";
$('.SBEndClassSelect').val(defendclass);
defendclass = "";
$(".SBEndPointSelect").select2();
$(".SBStartClassSelect").select2();
$(".SBEndClassSelect").select2();
$('.SBStartClassSelect').unbind('lccomplete');
});
loadPathList();
var eplist = $('.SBEndPointSelect option');
if(eplist.length == 0){
$('.SBEndPointSelect').on('epcomplete', function(){
$('.SBEndPointSelect').val(defendpoint);
defendpoint = "";
loadClassList();
$('.SBEndPointSelect').unbind('epcomplete');
});
}else{
$('.SBEndPointSelect').val(defendpoint);
defendpoint = "";
loadClassList();
}
}
d3.select('.SBModalView').on("mousewheel", function(){
event.preventDefault();
});
}
function openSample(ep, st, en){
defendpoint = ep;
defstartclass = st;
defendclass = en;
openSPARQLBuilder();
}
function openPermalink(){
var baseurl = location.href;
var spliturl = baseurl.split('?');
var url = spliturl[0] + "?ep=" + encodeURIComponent(endpoint) + "&st=" + encodeURIComponent(startclass) + "&en=" + encodeURIComponent(endclass);
window.open(url);
}
function closeSPARQLBuilder(){
$('.SBModalView').fadeOut();
}
function switchLoadIcon(mode) {
if(mode == "view"){
$('.SBAjaxLoad').show();
}else{
$('.SBAjaxLoad').hide();
}
};
function loadEndPointList(){
$('.SBSaveESE').attr('disabled', true);
var url = 'http://www.sparqlbuilder.org/api/eplist';
$.ajax({
url: url,
success: function(data) {
var list = eval(data);
$(".SBEndPointSelect").empty();
$(".SBEndPointSelect").append('
');
for (var i = 0; i < list.length; ++i) {
$(".SBEndPointSelect").append('
');
switchLoadIcon("hide");
if($('.SBModalView').attr('display') == 'block'){
$(".SBEndPointSelect").select2();
$(".SBStartClassSelect").select2();
$(".SBEndClassSelect").select2();
}
}
$(".SBEndPointSelect").trigger(new $.Event('epcomplete'));
},
});
}
changeEndPoint = function() {
endpoint = $(".SBEndPointSelect").val();
if(endpoint != "SBDefault"){
loadClassList();
}
};
loadClassList = function() {
$('.SBSaveESE').attr('disabled', true);
var url = "http://www.sparqlbuilder.org/api/clist?ep=" + encodeURIComponent(endpoint);
$.ajax({
type : "GET",
url : url,
async : false,
success : function(data) {
var list = eval(data);
$(".SBStartClassSelect").empty();
$(".SBEndClassSelect").empty();
$(".SBStartClassSelect").append('
');
$(".SBEndClassSelect").append('
');
for (var i = 0; i < list.length; ++i) {
$(".SBStartClassSelect").append('
');
$(".SBEndClassSelect").append('
');
}
$(".SBStartClassSelect").select2();
$(".SBEndClassSelect").select2();
$(".SBStartClassSelect").trigger(new $.Event('lccomplete'));
}
});
};
loadPathList = function() {
startclass = $(".SBStartClassSelect").val();
endclass = $(".SBEndClassSelect").val();
if(defendpoint != "" && defstartclass != "" && defendclass != ""){
endpoint = defendpoint;
startclass = defstartclass;
endclass = defendclass;
}
$('.SBSaveESE').attr('disabled', true);
if (startclass == null || endclass == null || startclass == "SBDefault" || endclass == "SBDefault"){
return;
}
pathlimit = 10;
$('.SBResult').hide();
$('.SBViewAll').hide();
$('.SBSelectedPath').html('
Please select a leaf node and push button to generate a SPARQL
');
var url = "http://www.sparqlbuilder.org/api/plist?ep=" + encodeURIComponent(endpoint)
+ "&startclass=" + encodeURIComponent(startclass)
+ "&endclass=" + encodeURIComponent(endclass);
//var self = this;
switchLoadIcon("view");
setTimeout(function(){
$.ajax({
type : "GET",
url : url,
//async : false,
timeout : 1000000,
success : function(data) {
jsontext = data;
view_map();
switchLoadIcon("hide");
$('.SBSaveESE').attr('disabled', false);
},
error: function(data){
switchLoadIcon("hide");
alert("error: ", data);
}
});
}, 100);
};
function viewAll(){
pathlimit = 0;
view_map();
}
generateSPARQL = function() {
var path = JSON.stringify(pathobj);
var url = 'http://www.sparqlbuilder.org/api/sparql?path=' + encodeURIComponent(path);
$.ajax({
type: "GET",
url : url,
dataType: 'text',
async: false,
success : function(data) {
$(".SBSparqlArea").val(data);
closeSPARQLBuilder();
}
});
};
function sendSPARQL(){
var sendep = $(".SBEndPointSelect").val();
var query = $(".SBSparqlArea").val();
if(sendep == "SBDefault" || query == ""){
return;
}
query = encodeURIComponent(query);
openpage = sendep + "?format=text%2Fhtml&query=" + query;
window.open(openpage);
}
function downloadResult(){
var sendep = $(".SBEndPointSelect").val();
var query = $(".SBSparqlArea").val();
if(sendep == "SBDefault" || query == ""){
return;
}
qr = sendQuery(sendep,query);
qr.fail(
function (xhr, textStatus, thrownError) {
alert("Error: A '" + textStatus+ "' occurred.");
}
);
qr.done(
function (d) {
downloadCSV(d.results.bindings);
}
);
}
function downloadCSV(data){
if (data instanceof Array) {
var result_txt ="";
var i=0;
for ( var key in data[0]) {
if(i>0){result_txt +=",";}
result_txt += key;
i++;
}
result_txt += "\n";
for (var d = 0; d < data.length; d++) {
var i = 0;
for ( var key in data[d]) {
if(i>0){result_txt +=",";}
result_txt += data[d][key].value;
i++;
}
result_txt += '\n';
}
var blob = new Blob( [result_txt], {type: 'text/plain'} )
var link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'result' + '.csv'
document.body.appendChild(link) // for Firefox
link.click()
document.body.removeChild(link) // for Firefox
}
};
view_map = function(){
// make_dataメソッドの結果を取得
var json = make_data(0);
if(json['nodes'].length != 0){
// 出来上がった結果を渡してマップ上のロケーションをセット
set_map_location(0, json['nodes'], json['links']);
// SVGの幅と高さを設定(幅:画面いっぱい 高さ:パスの数に応じ設定)
var width = $('.SBGraph').width();
var height = $('.SBGraph').height();
var graphheight = ((NODEHEIGHT * 1.5) * PATHNUM) + (NODEHEIGHT / 2);
var scoreleftmargin = NODEHEIGHT * 1.5;
// SVGの削除
d3.select(".SBGraph svg").remove();
// 画面サイズに合わせSVGの追加
var svg = d3.select(".SBGraph").append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", "0 0 " + width + " " + height)
.on("mousewheel", function(){
var vb = svg.attr("viewBox");
var spvb = vb.split(" ");
var vby = (parseInt(spvb[1]) - event.wheelDelta);
if(vby < 0){
vby = 0;
}else if(vby > (graphheight - height)){
vby = (graphheight - height);
if(vby < 0){
vby = 0;
}
}else{
event.preventDefault();
}
svg.attr("viewBox", "0 " + vby + " " + width + " " + height);
});
// 背景の追加
var bg = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", function(){
if(graphheight < height){
return height;
}else{
return graphheight;
}
})
.attr("fill", "#fafafa");
// links配列を渡しリンクの作成
var link = svg.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke", "#999")
.style("stroke-opacity", 0.6)
.style("stroke-width", function(d) { return Math.sqrt(d.value);});
// nodes配列を渡しノードの作成
var node = svg.selectAll(".node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", (NODEHEIGHT / 2))
.attr("cx", function(d) { return d.x;} )
.attr("cy", function(d) { return d.y; })
.style("stroke", function(d) { return '#fafafa'; })
.style("stroke-width", function(d) { return '1.5px'; })
.style("fill", function(d) { return d.nodecolor; })
.style("cursor", function(d) { return 'pointer'; });
// nodes配列を渡しノードテキストの作成
var tnode = svg.selectAll("text.node")
.data(json.nodes)
.enter().append("svg:text")
.attr("class", "tnode")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.text(function(d) { return d.name; })
.style("fill", function(d) { return '#000000'; })
.style("text-anchor", function(d) { return 'middle'; })
.style("pointer-events", "none");
// リンクテキストの作成
var tlink = svg.selectAll("text.link")
.data(json.links)
.enter().append("svg:text")
.attr("class", "tlink")
.attr("x", function(d) { return (json.nodes[d.source].x + json.nodes[d.target].x) / 2; })
.attr("y", function(d) { return (json.nodes[d.source].y + json.nodes[d.target].y) / 2; })
.style("fill", function(d) { return '#000000'; })
.style("text-anchor", function(d) { return 'middle'; });
// nodes配列を渡しノードテキストの作成
var tscore = svg.selectAll("text.score")
.data(json.nodes)
.enter().append("svg:text")
.attr("class", "tscore")
.attr("x", function(d) { return (d.x + scoreleftmargin); })
.attr("y", function(d) { return d.y; })
.text(function(d) { return d.score;
})
.style("fill", function(d) { return '#FF0000'; })
.style("text-anchor", function(d) { return 'middle'; })
.style("pointer-events", "none");
// マウスの動きカウントをルートに持たせる
MOUSEMOVED = 0;
// ノードへのオンマウスでパス探索、パス中のリンク文字を表示
node.on("mouseover", function(d){
// マウスの動きカウントをリセット
node.data()[0].mousemoved = 0;
// 表示するパス保存用配列
var path = [];
// ツールチップへの名前表示用配列
var pathname = [];
// ルートノード以外なら
if(d.nodeid != 0){
// まずオンマウスされたノードのidと名前をそれぞれ追加
path.push(d.nodeid);
pathname.push(d.name);
// パス探索
do{
// リンクの数だけ繰り返し
for(var i = 0; i < link.data().length; i++){
// 現在の最後尾に繋がるリンクがあれば
if(path[(path.length-1)] == link.data()[i].target){
// そのリンクのソース側ノードのidを追加
path.push(link.data()[i].source);
// そのリンクの名前とソース側ノードの名前を追加
pathname.push(link.data()[i].property);
pathname.push(node.data()[link.data()[i].source].name);
}
}
// ルートノードに辿り着くまで繰り返す
}while(path[(path.length-1)] != 0);
// 末端ノードでないなら
if(d.path == "notend"){
// ツールチップを非表示に
$('.SBSelectedPath').html('
Please select a leaf node and push button to generate a SPARQL
');
}else{
// 末端ノードならツールチップの情報を更新
var resultText = "";
// パスの名前配列分後ろから繰り返しながら
for (var i = pathname.length;i > 0; i--){
// 奇数番目(ノードの名前)は太字に
if(i % 2 == 1){
if(i == 1){
resultText = resultText + "
" + pathname[i - 1] + "
";
}else if(i == pathname.length){
resultText = resultText + "
" + pathname[i - 1] + "
";
}else{
resultText = resultText + "
" + pathname[i - 1] + "
";
}
// 偶数番目(リンクの名前)はそのままで表示
}else{
resultText = resultText + "
" + pathname[i - 1] + "
";
}
}
resultText = resultText + '
';
// ツールチップの内容を書き換え
$('.SBSelectedPath').html(resultText);
if(svg.attr("width") == width){
$('.SBTooltip').show();
}
// サーブレットに送り返すパスオブジェクトを保存
pathobj = d.path;
}
}
// オンマウスされたノードの高さに親を合わせるために合わせる高さを保存
var movey = d.y;
// 各ノードに対し
node
// 輪郭線の色を設定
.style("stroke", function(d){
// まずは背景色(デフォルト)を指定
var strokecolor = "#fafafa";
// パス判定の前処理
// 表示フラグがnow(前回オンマウスで動いていたノード)なら
if(d.view == "now"){
// ノードの表示フラグをnoに
d.view = "no";
}
// 表示フラグがmoved(クリックされ固定済みだが前回動いていたノード)なら
if(d.view == "moved"){
// 表示フラグをclickedに戻す
d.view = "clicked";
}
// 表示フラグがnoのものから確認
if(d.view == "no"){
// パスのノード数だけ繰り返しながら
for(var n = 0; n < path.length; n++){
// パス内に含まれるノードだったら
if(path[n] == d.nodeid){
// 輪郭線を赤に
strokecolor = "#ffaaaa";
// 表示フラグをnow(今回動いたノード)に
d.view = "now";
}
}
// 固定済みノードだったら
}else if(d.view == "clicked"){
// まずは輪郭線を赤に
strokecolor = "#ffaaaa";
// パス内に含まれるノードかチェック
for(var n = 0; n < path.length; n++){
if(path[n] == d.nodeid){
// 含まれていたなら今回動かすためフラグをmovedに
d.view = "moved";
}
}
}
// ここまでで得られた輪郭線の色を返す
return strokecolor;
})
// 高さの値
.attr("cy", function(d){
// ノードが今回オンマウスされた・または固定済みだが移動フラグをつけられていれば
if(d.view == "now" || d.view == "moved"){
// 現在の高さを取得
var curty = d.y;
// d.yに子ノードの高さをセット
d.y = movey;
// 現在の高さを返す(この時点では現在位置に描画され、redraw関数でd.yにアニメーションされる)
return curty;
// 移動対象でないなら
}else{
// 現在位置をそのまま返す
return d.y;
}
});
// 各リンクテキストに対し
tlink
// テキスト表示判定
.text(function(d) {
// デフォルトで空をセット
var linktext = "";
// 表示フラグがnow(前回表示されていたリンク)なら
if(d.view == "now"){
// 表示フラグを解除
d.view = "no";
}
// 表示フラグがnoなら
if(d.view == "no"){
// パスのノード数分繰り返し
for(var t = 0; t < path.length; t++){
// 自身がそのノードへ接続しているリンク(かつそのノードが折りたたまれていなければ)
if(path[t] == d.target && node.data()[d.target].view != "hide"){
// リンクテキストにプロパティの値をセット
linktext = d.property
// 表示フラグにnowをセット
d.view = "now";
}
}
// 表示フラグがfix(クリックされたパスのリンク)ならば(かつ繋がる先のノードが折りたたまれていなければ)
}else if(d.view == "fix" && node.data()[d.target].view != "hide"){
// リンクテキストにプロパティの値をセット
linktext = d.property
}
// ここまででできたリンクテキストを返す
return linktext;
});
// 各リンクに対し
link
// 線の色判定
.style("stroke", function(d){
// 表示フラグがnoならば
if(d.view == "no"){
// 色をデフォルトに
return "#999";
// それ以外(固定やオンマウスされたパスに含まれる)なら
}else{
// 色を赤に
return "#ffaaaa";
}
});
// ここまでの設定を元に再描画
redraw();
// ノードへのクリックで選択固定化(及び折り畳み処理)
}).on("click", function(d){
// 各ノードに対し
node
// 輪郭線の判定
.style("stroke", function(d) {
// デフォルトの色をセット
var strokecolor = "#fafafa"
// 表示フラグがオンマウス中・固定中・移動中(選択されているノード)ならば
if(d.view == "now" || d.view == "clicked" || d.view == "moved"){
// 色を赤に
strokecolor = "#ffaaaa"
// 表示フラグを固定中に
d.view = "clicked";
}
// ここまででできた色を返す
return strokecolor;
});
// 各リンクに対し
tlink
// テキスト表示判定
.text(function(d) {
// デフォルトで空に
var linktext = "";
// 表示フラグが現在表示中または固定化済みならば(かつ折り畳み中でなければ)
if((d.view == "now" || d.view == "fix") && (node.data()[d.target].view != "hide")){
// リンクテキストにプロパティの値をセット
linktext = d.property
// 表示フラグを固定中に
d.view = "fix";
}
// テキストを返す
return linktext;
});
// ここまでの処理結果を元に再描画
redraw();
});
// 再描画関数
var redraw = function (duration){
// かける時間が未指定ならば
if(duration == undefined){
// 0.5秒かけてアニメーション
duration = 500;
}
// 各リンクについて設定された位置に再描画
link
.transition()
.duration(duration)
.attr("x1", function(d) {return node.data()[d.source].x;})
.attr("y1", function(d) {return node.data()[d.source].y;})
.attr("x2", function(d) {return node.data()[d.target].x;})
.attr("y2", function(d) {return node.data()[d.target].y;});
// 各ノードについて設定された位置に再描画(かつ折りたたまれ中の場合の描画分岐処理)
node
.transition()
.duration(duration)
.attr("cx", function(d) {return d.x;})
.attr("cy", function(d) {return d.y;});
// 各ノードテキストについて設定された位置に再描画、テキスト描画位置を上下に振る(かつ折りたたまれ中の場合の描画分岐処理)
tnode
.transition()
.duration(duration)
.attr("x", function(d) {return d.x;})
.attr("y", function(d) {
// デフォルトで少し下げる
var updown = (self.NODEHEIGHT * 0.4);
// 奇数番目の深さなら少し上げる
if(d.group % 2 == 1){
updown = -(self.NODEHEIGHT * 0.2);
}
// その値を高さに返すことでテキスト描画位置が互い違いになる
return d.y + updown;
});
// 各リンクテキストについて設定された位置に再描画
tlink
.transition()
.duration(duration)
.attr("x", function(d) {return (node.data()[d.source].x + node.data()[d.target].x) / 2;})
.attr("y", function(d) {return ((node.data()[d.source].y + node.data()[d.target].y) / 2) + 5;});
};
// 背景部分がクリックされたら表示の固定化を解除
bg.on("click", function() {
// ツールチップを非表示
$('.SBTooltip').hide();
d3.selectAll(".node").style("stroke-width", function(d) { return '1.5px'; });
d3.selectAll(".node").style("stroke", function(d) { return '#ffffff'; });
// 各ノードの輪郭線の色をデフォルトに
node
.style("stroke", function(d){
if(d.view != "hide"){
d.view = "no";
}
return "#fafafa";
});
// リンクテキストを全て空に
tlink
.text(function(d) {
d.view = "no";
return "";
});
// リンクの色を全てデフォルトに
link
.style("stroke", function(d){
return "#999";
});
/*
if(svg.attr("width") == width){
svg.attr("width", (width / 5))
.attr("height", (width * 9 / 16 / 5))
.attr("viewBox", "0 0 " + width + " " + (width * 9 / 16));
}else{
svg.attr("width", width)
.attr("height", height)
.attr("viewBox", "0 0 " + width + " " + height);
}
*/
});
// 背景上でマウスが動くごとに
bg.on("mousemove", function(){
// MOUSEMOVEDを追加(ノードにオンマウスされる度にカウントリセット)
MOUSEMOVED++;
// 30を超えたら
if(MOUSEMOVED > 30){
// ツールチップを非表示にしてカウントリセット
$('.SBTooltip').hide();
MOUSEMOVED = 0;
}
});
// 初回のみdurationを0と指定し再描画(アニメーションなし)
redraw(0);
}else{
// SVGの削除
d3.select(".SBGraph svg").remove();
}
};
make_data = function(tdepth, ret, parent, depth){
// retが未定義ならば定義して代入
if (ret == undefined){
ret = new Object();
ret['nodes'] = new Array();
ret['links'] = new Array();
}
PATHNUM = 0;
MAXDEPTH = 0;
TREESPACE = 0;
NODEHEIGHT = 50;
DRAWHEIGHT = NODEHEIGHT;
var viewnum;
var obj = jsontext;
$('.SBResult').css('color', 'black').css('font-weight', 'normal');
$('.SBPlural').text('s');
if(obj.length == 0){
$('.SBResult').css('color', 'red').css('font-weight', 'bold');
$('.SBPlural').text('');
}else if(obj.length == 1){
$('.SBPlural').text('');
}
if(obj.length <= 10){
viewnum = obj.length;
$('.SBViewall').hide();
}else if(pathlimit == 10){
viewnum = 10;
$('.SBViewall').show();
}else{
viewnum = obj.length;
$('.SBViewall').hide();
}
$('.SBPathnum').text(obj.length);
$('.SBResult').show();
// objトップ階層の数だけ繰り返しながら
for(var i = 0; i < viewnum; i++){
if(i == 0){
// 初回だけルートノードをプッシュ
ret['nodes'].push({'name': obj[0]['label'], 'uri': obj[0]['startClass'], 'group': 0, 'x':50, 'y':50, 'nodeid':ret['nodes'].length, 'view' : 'no', 'path': 'notend', 'nodecolor': 'hsl(40, 50%, 75%)'});
}
// 先にsourceに0(ルート)を代入
var source = 0;
// 共通ルート判定をtrueに
var isCommon = true;
var score = obj[i]['score'];
// classLinksの数だけ繰り返しながら
for(var j = 0;j < obj[i]['classLinks'].length; j++){
// リンクの名前をURL末尾から取得
var propertytext = obj[i]['classLinks'][j]['predicate'];
var propertysplit1 = propertytext.split("/");
var propertysplit2 = propertysplit1[propertysplit1.length - 1];
var propertysplit3 = propertysplit2.split("#");
propertytext = propertysplit3[propertysplit3.length - 1];
if(MAXDEPTH < j+1){
MAXDEPTH = j+1;
}
// ここまで共通ルートなら
if(isCommon){
// 今回も共通か確認するためのフラグ
var isCommonNow = false;
// nodes配列に同じlinkedClassが既にあるか確認
var targets = [];
for(var k = 0; k < ret['nodes'].length; k++){
// 同階層かつ同じ名前のものがあったらtargets配列に番号を追加
if(ret['nodes'][k]['group'] == (j+1) && obj[i]['classLinks'][j]['linkedClass'] == ret['nodes'][k]['uri']){
targets.push(k);
}
}
// 既にあった場合はlinks配列に同じlinkが存在するか確認
if(targets.length != 0){
// 先ほど見つけたtargetsの数だけ繰り返しながら
for(var l = 0; l