MediaWiki:Lipoquality.js: Difference between revisions
Jcblmaster (talk | contribs) No edit summary |
Jcblmaster (talk | contribs) No edit summary |
||
| Line 4: | Line 4: | ||
// external script ////////////////////////////////////////////////////////////////////////////////////////////// | // external script ////////////////////////////////////////////////////////////////////////////////////////////// | ||
mw.loader.load(' | mw.loader.load( ['jquery.ui.sortable'] ); | ||
mw.loader.load('https://code.highcharts.com/stock/highstock.js', "text/javascript"); | mw.loader.load('https://code.highcharts.com/stock/highstock.js', "text/javascript"); | ||
| Line 10: | Line 10: | ||
addOnloadHook(init); | addOnloadHook(init); | ||
// 初期化 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function init() | function init() | ||
{ | { | ||
| Line 29: | Line 30: | ||
showButton.onclick = function(){showChart()}; | showButton.onclick = function(){showChart()}; | ||
document.getElementById("show").appendChild(showButton); | document.getElementById("show").appendChild(showButton); | ||
// insert "Reset zoom" button | |||
var resetZoomButton = document.createElement("input"); | |||
resetZoomButton.setAttribute("type", "button"); | |||
resetZoomButton.value = "Reset zoom"; | |||
resetZoomButton.id = "resetZoomButton"; | |||
resetZoomButton.style = "visibility: hidden"; | |||
resetZoomButton.onclick = unzoomBarCharts; | |||
document.getElementById("resetZoom").appendChild(resetZoomButton); | |||
setCombobox('Classification'); | setCombobox('Classification'); | ||
setCombobox('Sample'); | setCombobox('Sample'); | ||
setCombobox('Type'); | setCombobox('Type'); | ||
$(window).resize(function() { | |||
resizeHeatmap(); | |||
}); | |||
} | } | ||
// ウィンドウサイズが変更されたとき、ヒートマップの幅も修正する /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function resizeHeatmap() | |||
{ | |||
var height = 400; | |||
var width = $(window).width() - $("#sortableList").width() - $("#mw-panel").width(); | |||
if(chart == undefined || chart.length == 0 || chart[0].options.chart.type != "heatmap") | |||
return; | |||
for(var i = 0; i < chart.length; i ++) | |||
$("#container" + i).highcharts().setSize(width, height); | |||
} | |||
// 検索ボックスの初期化 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function setCombobox(name) | function setCombobox(name) | ||
{ | { | ||
| Line 70: | Line 97: | ||
xmlHttpRequest.send(null); | xmlHttpRequest.send(null); | ||
} | } | ||
// XSS対策用 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function escape(text) | function escape(text) | ||
{ | { | ||
| Line 88: | Line 116: | ||
return text.replace(/[^A-Z0-9-]/g, ""); | return text.replace(/[^A-Z0-9-]/g, ""); | ||
} | } | ||
// 検索 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function search() | function search() | ||
{ | { | ||
| Line 97: | Line 126: | ||
var type = document.getElementById("type").value; | var type = document.getElementById("type").value; | ||
var url = 'https://script.google.com/macros/s/ | var url = 'https://script.google.com/macros/s/AKfycbwnSskrJWOPYksPyPqL5zHhGQxqeRpHhxt6ZzfaH-OCoMbG_w51/exec?classification=' + classification + '&sample=' + sample + '&type=' + type + '&q=search&callback=hasSearched'; | ||
// var url = '/lipo/json.txt' | // var url = '/lipo/json.txt' | ||
| Line 119: | Line 148: | ||
//var result = JSON.parse(escape(jsonp)); | //var result = JSON.parse(escape(jsonp)); | ||
document.getElementById('hit').innerHTML = 'result. ' + escape(result.length) + ' hit(s).'; | document.getElementById('hit').innerHTML = 'result. ' + escape(result.length) + ' hit(s).'; | ||
// 最長文字数を調べる | |||
var lenmax = 0; | |||
for(var i = 0; i < result.length; i ++){ | for(var i = 0; i < result.length; i ++){ | ||
if(result[i].title.length > lenmax) | |||
lenmax = result[i].title.length; | |||
} | |||
lenmax /= 2; | |||
for(var i = 0; i < result.length; i ++){ | |||
var span = document.createElement('span'); | |||
span.style = "display: inline-block; width: " + lenmax + "em"; | |||
var check = document.createElement('input'); | var check = document.createElement('input'); | ||
check.type = 'checkbox'; | check.type = 'checkbox'; | ||
check.id = attrEscape(result[i]); | check.id = attrEscape(result[i].title); | ||
check.value = attrEscape(result[i]); | check.value = attrEscape(result[i].title); | ||
check.name = 'target'; | check.name = 'target'; | ||
span.appendChild(check); | |||
var title = document.createElement('label'); | var title = document.createElement('label'); | ||
title.setAttribute('for', attrEscape(result[i])); | title.setAttribute('for', attrEscape(result[i].title)); | ||
title.innerHTML = escape(result[i]); | title.innerHTML = escape(result[i].title); | ||
span.appendChild(title); | |||
root.appendChild( | |||
root.appendChild(span); | |||
} | } | ||
document.getElementById("searchButton").disabled = false; | document.getElementById("searchButton").disabled = false; | ||
} | } | ||
// チャート表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function showChart() | function showChart() | ||
{ | { | ||
| Line 148: | Line 188: | ||
} | } | ||
targets = targets.substring(1); | targets = targets.substring(1); | ||
document.getElementById("resetZoomButton").style = "visibility: hidden"; | |||
document.getElementById("showButton").disabled = true; | document.getElementById("showButton").disabled = true; | ||
document.getElementById("bar") .disabled = true; | |||
document.getElementById("heatmap") .disabled = true; | |||
document.getElementById("sortableList").style.display = "none"; | |||
var sortableList = document.getElementById("sortableList"); | |||
for(var i = sortableList.childNodes.length-1; i >= 0; i --) | |||
sortableList.removeChild(sortableList.childNodes[i]); | |||
var chartType; | var chartType; | ||
if(document.getElementById('bar').checked) | if(document.getElementById('bar').checked) | ||
| Line 155: | Line 204: | ||
else | else | ||
chartType = 'heatmap'; | chartType = 'heatmap'; | ||
var url = 'https://script.google.com/macros/s/ | |||
retrieveChartData(targets, chartType); | |||
} | |||
// データ取得 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function retrieveChartData(targets, chartType) | |||
{ | |||
var url = 'https://script.google.com/macros/s/AKfycbwnSskrJWOPYksPyPqL5zHhGQxqeRpHhxt6ZzfaH-OCoMbG_w51/exec?id=' + targets + '&type=' + chartType + '&q=data&callback=hasRetrieved'; | |||
//var url = '/lipo/data.php?id=' + targets + '&type=' + chartType + '&q=data'; | //var url = '/lipo/data.php?id=' + targets + '&type=' + chartType + '&q=data'; | ||
// jsonpを使った取得 | // jsonpを使った取得 | ||
var ignore0 = document.getElementById("ignore0"); | |||
for(var i = ignore0.childNodes.length-1; i >= 0; i --) | |||
ignore0.removeChild(ignore0.childNodes[i]); | |||
var pieRoot = document.getElementById('pieContainer'); | |||
for(var i = pieRoot.childNodes.length-1; i >= 0; i --) | |||
pieRoot.removeChild(pieRoot.childNodes[i]); | |||
var root = document.getElementById('container'); | var root = document.getElementById('container'); | ||
for(var i = root.childNodes.length-1; i >= 0; i --) | |||
root.removeChild(root.childNodes[i]); | |||
root.textContent = 'Retrieving...'; | root.textContent = 'Retrieving...'; | ||
var jsonp = document.createElement('script'); | var jsonp = document.createElement('script'); | ||
| Line 166: | Line 229: | ||
} | } | ||
// コールバック関数(jsonp) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function hasRetrieved(jsonp) | function hasRetrieved(jsonp) | ||
{ | { | ||
| Line 171: | Line 235: | ||
// remove old elements | // remove old elements | ||
root.textContent = ''; | root.textContent = ''; | ||
// for(var i = root.childNodes.length-1; i >= 0; i --) | |||
// root.removeChild(root.childNodes[i]); | |||
var chartType; | var chartType; | ||
| Line 179: | Line 243: | ||
else | else | ||
chartType = 'heatmap'; | chartType = 'heatmap'; | ||
var ignore0 = document.getElementById("ignore0"); | |||
var cbox0ignore = document.createElement("input"); | |||
cbox0ignore.id = "ignore0box"; | |||
cbox0ignore.setAttribute("type","checkbox"); | |||
ignore0.appendChild(cbox0ignore); | |||
var ignoreLabel = document.createElement("label"); | |||
ignoreLabel.innerHTML = "ignore 0-intensity column(s)"; | |||
ignoreLabel.setAttribute("for", "ignore0box"); | |||
ignore0.appendChild(ignoreLabel); | |||
var result = jsonp; | var result = jsonp; | ||
| Line 187: | Line 261: | ||
showHeatmap(result); | showHeatmap(result); | ||
document.getElementById("showButton").disabled = false; | document.getElementById("showButton").disabled = false; | ||
document.getElementById("bar") .disabled = false; | |||
document.getElementById("heatmap") .disabled = false; | |||
document.getElementById("sortableList").style.display = "block"; | |||
} | } | ||
// バーチャート /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
var gBarData; | var gBarData; | ||
function getInchiOnBar(seq, x) | function getInchiOnBar(seq, x) | ||
| Line 195: | Line 273: | ||
console.log(seq + "/" + x + " => " + gBarData[seq][x]); | console.log(seq + "/" + x + " => " + gBarData[seq][x]); | ||
} | } | ||
var chart; | |||
var piechart; | |||
var defaultTickInterval = currentTickInterval = 5; | |||
// バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function unzoomBarCharts() { | |||
for(var i = 0; i < chart.length; i ++){ | |||
//chart[i].xAxis[0].options.tickInterval = defaultTickInterval; | |||
chart[i].xAxis[0].isDirty = true; | |||
chart[i].xAxis[0].setExtremes(null, null, animation=true); | |||
} | |||
document.getElementById("resetZoomButton").style = "visibility: hidden"; | |||
} | |||
// データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function setBarchartData() | |||
{ // inchiキー未処理 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
var target = []; | |||
var ignore0 = !document.getElementById("ignore0box").checked; | |||
var xLabels = []; | |||
for(var j = 0; j < chart[0].data.length; j ++){ | |||
var not0 = false; | |||
for(var i = 0; i < chart.length; i ++){ | |||
if(ignore0 || chart[i].data[j] != 0){ | |||
not0 = true; | |||
break; | |||
} | |||
} | |||
target[j] = not0; | |||
} | |||
for(var j = 0; j < chart.length; j ++){ | |||
var i = 0; | |||
var data = []; | |||
for(var k = 0,l = 0; k < chart[j].data.length; k ++){ | |||
if(target[k]){ | |||
data[i++] = chart[j].data[k]; | |||
} | |||
} | |||
chart[j].series[0].setData(data, true); | |||
} | |||
unzoomBarCharts(); | |||
} | |||
// 表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function showBarChart(result) | function showBarChart(result) | ||
{ | { | ||
function computeTickInterval(xMin, xMax) | |||
{ | |||
var zoomRange = xMax - xMin; | |||
if(zoomRange <= 2) | |||
currentTickInterval = 0.5; | |||
if(zoomRange < 20) | |||
currentTickInterval = 1; | |||
else if(zoomRange < 100) | |||
currentTickInterval = 5; | |||
} | |||
// create ignore 0-intensity button | |||
document.getElementById("ignore0box").onchange = function(){ | |||
setBarchartData(); | |||
}; | |||
// create sortable list | |||
var sortableList = document.getElementById("sortableList"); | |||
for(var i = 0; i < result[0].map.length; i ++){ | |||
var line = document.createElement("div"); | |||
var cbox = document.createElement("input"); | |||
cbox.setAttribute("type", "checkbox"); | |||
cbox.setAttribute("checked", "yes"); | |||
cbox.setAttribute("seq", i); | |||
cbox.id = "item" + i; | |||
cbox.onchange = function(e){ | |||
// 表示/非表示の切り替え | |||
var seq = this.getAttribute("seq"); | |||
var option; | |||
if(this.checked){ | |||
option = "block"; | |||
} else { | |||
option = "none"; | |||
} | |||
document.getElementById("container" + seq).style.display = option; | |||
document.getElementById("pieContainer" + seq).style.display = option; | |||
}; | |||
line.appendChild(cbox); | |||
var label = document.createElement("label"); | |||
label.setAttribute("for", "item" + i); | |||
label.innerHTML = (i+1) + "." + escape(result[0].map[i].title); | |||
line.appendChild(label); | |||
sortableList.appendChild(line); | |||
} | |||
$('#sortableList').sortable({ | |||
cursor: 'move', | |||
update: function(event, ui){ | |||
var sortableList = document.getElementById("sortableList"); | |||
for(var i = 0; i < sortableList.childNodes.length; i ++){ | |||
var seq = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); | |||
document.getElementById("container" + seq).setAttribute("order", i); | |||
document.getElementById("pieContainer" + seq).setAttribute("order", i); | |||
} | |||
$("#container").html( | |||
$("#container > div").sort(function(o1,o2) | |||
{ | |||
var n1 = parseInt($(o1).attr("order"), 10); | |||
var n2 = parseInt($(o2).attr("order"), 10); | |||
if(n1 < n2) return -1; | |||
if(n1 > n2) return 1; | |||
return 0; | |||
}) | |||
); | |||
$("#pieContainer").html( | |||
$("#pieContainer > div").sort(function(o1,o2) | |||
{ | |||
var n1 = parseInt($(o1).attr("order"), 10); | |||
var n2 = parseInt($(o2).attr("order"), 10); | |||
if(n1 < n2) return -1; | |||
if(n1 > n2) return 1; | |||
return 0; | |||
}) | |||
); | |||
} | |||
}); | |||
// create barchart(s) | |||
gBarData = []; | gBarData = []; | ||
var root = document.getElementById('container'); | chart = []; | ||
for(var i = 0; i < result.length; i ++){ | piechart = []; | ||
var root = document.getElementById('container'); | |||
var pieRoot = document.getElementById('pieContainer'); | |||
for(var i = 0; i < result[0].map.length; i ++){ | |||
gBarData[i] = []; | gBarData[i] = []; | ||
// データの整理 | // データの整理 | ||
var data = []; | var data = []; | ||
for(var j = 0; j < result[i].data.length; j ++){ | for(var j = 0; j < result[0].map[i].data.length; j ++){ | ||
data[j] = [attrEscape(result[ | data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0])]; | ||
gBarData[i][j] = inchiEscape(result[i].data[j][ | gBarData[i][j] = inchiEscape(result[0].map[i].data[j][2]); // InChIキー | ||
} | } | ||
| Line 211: | Line 413: | ||
var parent = document.createElement('div'); | var parent = document.createElement('div'); | ||
parent.id = 'container' + i; | parent.id = 'container' + i; | ||
parent.setAttribute("order", i); | |||
root.appendChild(parent); | root.appendChild(parent); | ||
chart[i] = new Highcharts.Chart({ | |||
chart: { | chart: { | ||
type: 'column', | type: 'column', | ||
zoomType: 'x', | |||
renderTo: parent, | renderTo: parent, | ||
height: 250, | height: 250, | ||
resetZoomButton: { | |||
theme: { | |||
display: 'none' | |||
} | |||
} | |||
}, | }, | ||
title: { | title: { | ||
text: (i+1) + '.' + attrEscape(result[i].title) | text: (i+1) + '.' + attrEscape(result[0].map[i].title) | ||
}, | }, | ||
xAxis: { | xAxis: { | ||
min: 0, | |||
type: 'category', | type: 'category', | ||
labels: { | labels: { | ||
| Line 233: | Line 443: | ||
text: '分子種' | text: '分子種' | ||
}, | }, | ||
events : { | |||
afterSetExtremes: function(){ | |||
if(!this.chart.options.chart.isZoomed){ | |||
var xMin = this.chart.xAxis[0].min; | |||
var xMax = this.chart.xAxis[0].max; | |||
var zmRange = computeTickInterval(xMin, xMax); | |||
for(var i = 0; i < chart.length; i ++){ | |||
chart[i].xAxis[0].options.tickInterval = zmRange; | |||
chart[i].xAxis[0].isDirty = true; | |||
if(chart[i] !== this){ | |||
chart[i].options.chart.isZoomed = true; | |||
chart[i].xAxis[0].setExtremes(xMin, xMax, true); | |||
chart[i].options.chart.isZoomed = false; | |||
} | |||
} | |||
document.getElementById("resetZoomButton").style = "visibility: visible"; | |||
} | |||
}, | |||
} | |||
}, | }, | ||
scrollbar: { | scrollbar: { | ||
| Line 241: | Line 471: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: ' | text: 'Relative Intensity(%)' | ||
} | } | ||
}, | }, | ||
| Line 248: | Line 478: | ||
}, | }, | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f}</b>' | pointFormat: '<b>{point.y:.1f} %</b>' | ||
}, | }, | ||
series: [{ | series: [{ | ||
| Line 260: | Line 490: | ||
} | } | ||
} | } | ||
}] | |||
}); | |||
chart[i].data = data; | |||
// piechartの追加 | |||
var pieParent = document.createElement('div'); | |||
pieParent.id = 'pieContainer' + i; | |||
pieParent.setAttribute("order", i); | |||
pieRoot.appendChild(pieParent); | |||
piechart[i] = new Highcharts.Chart({ | |||
chart: { | |||
plotBackgroundColor: null, | |||
plotBorderWidth: null, | |||
plotShadow: false, | |||
type: 'pie', | |||
renderTo: pieParent, | |||
height: 250 | |||
}, | |||
title: { | |||
text: (i+1) + '.amount' | |||
}, | |||
tooltip: { | |||
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' | |||
}, | |||
plotOptions: { | |||
pie: { | |||
allowPointSelect: true, | |||
cursor: 'pointer', | |||
dataLabels: { | |||
enabled: true, | |||
format: '<b>{point.name}</b>: {point.percentage:.1f} %', | |||
style: { | |||
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black' | |||
} | |||
} | |||
} | |||
}, | |||
series: [{ | |||
name: 'Brands', | |||
colorByPoint: true, | |||
data: result[0].map[i].pie, | |||
events: { | |||
click: function(event) { | |||
var nextType = event.point.name; | |||
var targets = ''; | |||
var sortableList = document.getElementById("sortableList"); | |||
for(var i = 0; i < sortableList.childNodes.length; i ++){ | |||
var w = sortableList.childNodes[i].childNodes[1].innerHTML.replace(/^[0-9]+./,"").split("/"); | |||
targets += "," + w[0] + "/" + w[1] + "/" + nextType; | |||
} | |||
targets = targets.substring(1); | |||
document.getElementById("showButton").disabled = true; | |||
document.getElementById("bar") .disabled = true; | |||
document.getElementById("heatmap") .disabled = true; | |||
document.getElementById("sortableList").style.display = "none"; | |||
var sortableList = document.getElementById("sortableList"); | |||
for(var i = sortableList.childNodes.length-1; i >= 0; i --) | |||
sortableList.removeChild(sortableList.childNodes[i]); | |||
retrieveChartData(targets, 'bar'); | |||
} | |||
} | |||
}] | }] | ||
}); | }); | ||
} | } | ||
} | } | ||
// ヒートマップ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
var chart; | |||
var gHeatmapData; | var gHeatmapData; | ||
function getInchiOnHeatmap(seq, x, y) | function getInchiOnHeatmap(seq, x, y) // 未使用 | ||
{ | { | ||
window.open("http://jcbl.jp/","new"); | window.open("http://jcbl.jp/","new"); | ||
console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq][y][x]); | console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq][y][x]); | ||
} | } | ||
function jumpToJcbl(inchi) | |||
{ | |||
window.open("http://jcbl.jp/","new"); | |||
console.log(inchi); | |||
} | |||
// データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function setHeatmapData(index, seq) | |||
{ | |||
var i = 0; | |||
var length = gHeatmapData[index].map.length; | |||
var target = []; | |||
var ignore0 = !document.getElementById("ignore0box").checked; | |||
var xLabels = []; | |||
for(var k = 0; k < gHeatmapData[index].map[0].data.length; k ++){ | |||
var not0 = false; | |||
for(var j = 0; j < length; j ++){ | |||
if(ignore0 || gHeatmapData[index].map[j].data[k][0] != 0){ | |||
not0 = true; | |||
break; | |||
} | |||
} | |||
target[k] = not0; | |||
if(not0) | |||
xLabels[i++] = gHeatmapData[index].x[k]; | |||
} | |||
var data = []; | |||
var yLabels = []; | |||
chart[index].inchi = []; | |||
i = 0; | |||
for(var j = 0; j < seq.length && j < length; j ++){ | |||
chart[index].inchi[j] = []; | |||
for(var k = 0,l = 0; k < gHeatmapData[index].map[seq[j]].data.length; k ++){ | |||
if(target[k]){ | |||
data[i] = [l++, seq.length-j-1, attrEscape(gHeatmapData[index].map[seq[j]].data[k][0])]; | |||
chart[index].inchi[j][k] = inchiEscape(gHeatmapData[index].map[seq[j]].data[k][2]); | |||
i ++; | |||
} | |||
} | |||
yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(gHeatmapData[index].map[seq[j]].title); | |||
} | |||
yLabels.reverse(); | |||
chart[index].series[0].setData(data, true); | |||
chart[index].yAxis[0].setCategories(yLabels); | |||
chart[index].xAxis[0].setCategories(xLabels); | |||
} | |||
// 表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function showHeatmap(result) | function showHeatmap(result) | ||
{ | { | ||
gHeatmapData = []; | gHeatmapData = []; | ||
var root = document.getElementById('container'); | var root = document.getElementById('container'); | ||
var sortableList = document.getElementById("sortableList"); | |||
chart = []; | |||
gHeatmapData = result; | |||
for(var i = 0; i < result.length; i ++){ | for(var i = 0; i < result.length; i ++){ | ||
// タイトル | // タイトル | ||
| Line 286: | Line 633: | ||
var data = []; | var data = []; | ||
var yLabels = []; | var yLabels = []; | ||
var length = result[i].map.length | |||
for(var j = 0; j < | var inchi = []; | ||
for(var j = 0; j < length; j ++){ | |||
inchi[j] = []; | |||
for(var k = 0; k < result[i].map[j].data.length; k ++){ | for(var k = 0; k < result[i].map[j].data.length; k ++){ | ||
data[index] = [k, j, attrEscape(result[i].map[j].data[k][0])]; | data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0])]; | ||
inchi[j][k] = inchiEscape(result[i].map[j].data[k][2]); | |||
index ++; | index ++; | ||
} | } | ||
yLabels[j] = attrEscape(result[i].map[j].title); | yLabels[j] = (j+1) + "." + attrEscape(result[i].map[j].title); | ||
} | } | ||
yLabels.reverse(); | |||
for(var j = 0; j < result[i].x.length; j ++) | for(var j = 0; j < result[i].x.length; j ++) | ||
result[i].x[j] = attrEscape(result[i].x[j]); | result[i].x[j] = attrEscape(result[i].x[j]); | ||
var | |||
if( | // create ignore 0-intensity button | ||
document.getElementById("ignore0box").onchange = function(){ | |||
// 表示/非表示の切り替え // 下と同じなので、後でまとめる | |||
for(var index = 0; index < chart.length; index ++){ | |||
var sortableList = document.getElementById("sortableList" + index); | |||
var sequence = []; | |||
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ | |||
if(sortableList.childNodes[i].childNodes[0].checked) | |||
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); | |||
} | |||
setHeatmapData(index, sequence); | |||
} | |||
}; | |||
// create sortable list | |||
var listDiv = document.createElement("div"); | |||
listDiv.id = "sortableList" + i; | |||
for(var j = 0; j < result[i].map.length; j ++){ | |||
var line = document.createElement("div"); | |||
var cbox = document.createElement("input"); | |||
cbox.setAttribute("type", "checkbox"); | |||
cbox.setAttribute("checked", "yes"); | |||
cbox.setAttribute("seq", j); | |||
cbox.id = "item" + j; | |||
cbox.onchange = function(e){ | |||
// 表示/非表示の切り替え | |||
var index = this.parentElement.parentElement.id.replace("sortableList", ""); | |||
var sortableList = document.getElementById("sortableList" + index); | |||
var sequence = []; | |||
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ | |||
if(sortableList.childNodes[i].childNodes[0].checked) | |||
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); | |||
} | |||
setHeatmapData(index, sequence); | |||
}; | |||
line.appendChild(cbox); | |||
var label = document.createElement("label"); | |||
label.setAttribute("for", "item" + j); | |||
label.innerHTML = (j+1) + "." + escape(result[i].map[j].title); | |||
line.appendChild(label); | |||
listDiv.appendChild(line); | |||
} | |||
sortableList.appendChild(listDiv); | |||
$('#sortableList' + i).sortable({ | |||
cursor: 'move', | |||
update: function(event, ui){ | |||
var index = ui.item[0].parentElement.id.replace("sortableList", ""); | |||
var sortableList = document.getElementById("sortableList" + index); | |||
var sequence = []; | |||
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ | |||
if(sortableList.childNodes[i].childNodes[0].checked) | |||
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); | |||
} | |||
setHeatmapData(index, sequence); | |||
} | |||
}); | |||
$('#sortableList').sortable(false); | |||
// ヒートマップ | // ヒートマップ | ||
chart[i] = new Highcharts.Chart({ | |||
chart: { | chart: { | ||
type: 'heatmap', | type: 'heatmap', | ||
zoomType: 'xy', | |||
animation: 1, | |||
marginBottom: 0, | marginBottom: 0, | ||
plotBorderWidth: 1, | plotBorderWidth: 1, | ||
renderTo: parent, | renderTo: parent, | ||
animation: true, | |||
}, | }, | ||
| Line 316: | Line 724: | ||
title: { | title: { | ||
text: title | text: title, | ||
align: 'left' | |||
}, | }, | ||
| Line 329: | Line 738: | ||
} | } | ||
}, | }, | ||
}, | }, | ||
| Line 340: | Line 748: | ||
min: 0, | min: 0, | ||
max: 100, | max: 100, | ||
minColor: '# | minColor: '#ffffff', | ||
maxColor: Highcharts.getOptions().colors[8] | maxColor: Highcharts.getOptions().colors[8] | ||
}, | }, | ||
| Line 357: | Line 765: | ||
return this.series.yAxis.categories[this.point.y] + '<br />' + | return this.series.yAxis.categories[this.point.y] + '<br />' + | ||
this.series.xAxis.categories[this.point.x] + '<br />' + | this.series.xAxis.categories[this.point.x] + '<br />' + | ||
(Math.round(this.point.value*10)/10); | (Math.round(this.point.value*10)/10) + ' %'; | ||
} | } | ||
}, | }, | ||
| Line 394: | Line 802: | ||
},*/ | },*/ | ||
click: function(event){ | click: function(event){ | ||
// var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container",""); | |||
// getInchiOnHeatmap(index, event.point.x, event.point.y); | |||
jumpToJcbl(event.point.series.chart.inchi[event.point.y][event.point.x]); | |||
} | } | ||
} | } | ||
| Line 402: | Line 811: | ||
}); | }); | ||
chart[i].inchi = inchi; | |||
//chart.setSize(600,300,false); | //chart.setSize(600,300,false); | ||
} | } | ||
resizeHeatmap(); | |||
} | } | ||
// ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function getTarget(children, target) | function getTarget(children, target) | ||
{ | { | ||
Revision as of 15:51, 19 April 2016
// html /////////////////////////////////////////////////////////////////////////////////////////////////////////
// <span id="search"></span><span id="show"></span>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// external script //////////////////////////////////////////////////////////////////////////////////////////////
mw.loader.load( ['jquery.ui.sortable'] );
mw.loader.load('https://code.highcharts.com/stock/highstock.js', "text/javascript");
// initialize //////////////////////////////////////////////////////////////////////////////////////////////////
addOnloadHook(init);
// 初期化 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function init()
{
// highstock.jsに依存するため、別で読み込む
var heatmapJS = document.createElement("script");
heatmapJS.src = "https://code.highcharts.com/modules/heatmap.js";
document.getElementsByTagName("head")[0].appendChild(heatmapJS);
var searchButton = document.createElement("input");
searchButton.value = "search";
searchButton.id = "searchButton";
searchButton.type = "button";
searchButton.onclick = function(){search()};
document.getElementById("search").appendChild(searchButton);
var showButton = document.createElement("input");
showButton.value = "show";
showButton.id = "showButton";
showButton.type = "button";
showButton.onclick = function(){showChart()};
document.getElementById("show").appendChild(showButton);
// insert "Reset zoom" button
var resetZoomButton = document.createElement("input");
resetZoomButton.setAttribute("type", "button");
resetZoomButton.value = "Reset zoom";
resetZoomButton.id = "resetZoomButton";
resetZoomButton.style = "visibility: hidden";
resetZoomButton.onclick = unzoomBarCharts;
document.getElementById("resetZoom").appendChild(resetZoomButton);
setCombobox('Classification');
setCombobox('Sample');
setCombobox('Type');
$(window).resize(function() {
resizeHeatmap();
});
}
// ウィンドウサイズが変更されたとき、ヒートマップの幅も修正する ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function resizeHeatmap()
{
var height = 400;
var width = $(window).width() - $("#sortableList").width() - $("#mw-panel").width();
if(chart == undefined || chart.length == 0 || chart[0].options.chart.type != "heatmap")
return;
for(var i = 0; i < chart.length; i ++)
$("#container" + i).highcharts().setSize(width, height);
}
// 検索ボックスの初期化 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function setCombobox(name)
{
var url = '/mediawiki/api.php?action=query&prop=revisions&redirects=1&titles=Lipoquality:' + name + '&rvprop=content&format=xml'
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function()
{
var READYSTATE_COMPLETED = 4;
if(this.readyState == READYSTATE_COMPLETED){
var HTTP_STATUS_OK = 200;
if(this.status == HTTP_STATUS_OK) {
// success
var parser = new DOMParser();
var dom = parser.parseFromString(this.response.trim(), "text/xml");
var text = dom.getElementsByTagName("rev");
var lines = text[0].textContent.split("\n");
var select = document.getElementById(name.toLowerCase());
if(name != 'Type')
lines.unshift('All');
for(var i = 0; i < lines.length; i ++){
var opt = document.createElement('option');
opt.value = opt.textContent = lines[i].replace(/^\*/, '').replace(/^ */, '').replace(/ *$/, '').replace(/"/g, """).replace(/'/g, "&rsquo");;
select.appendChild(opt);
}
} else {
// error
console.log('search failed. ' + this.status + ':' + this.statusText + "/" + this.readyState);
}
}
}
// search
xmlHttpRequest.open('GET', url, true);
xmlHttpRequest.responseType = 'text';
xmlHttpRequest.send(null);
}
// XSS対策用 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function escape(text)
{
if(isFinite(text))
return text;
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
}
function attrEscape(text)
{
if(isFinite(text))
return text;
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "’");
}
function inchiEscape(text)
{
if(isFinite(text))
return text;
return text.replace(/[^A-Z0-9-]/g, "");
}
// 検索 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function search()
{
document.getElementById("searchButton").disabled = true;
document.getElementById('hit').innerHTML = '';
var classification = document.getElementById("classification").value;
var sample = document.getElementById("sample").value;
var type = document.getElementById("type").value;
var url = 'https://script.google.com/macros/s/AKfycbwnSskrJWOPYksPyPqL5zHhGQxqeRpHhxt6ZzfaH-OCoMbG_w51/exec?classification=' + classification + '&sample=' + sample + '&type=' + type + '&q=search&callback=hasSearched';
// var url = '/lipo/json.txt'
// jsonpを使って検索
var root = document.getElementById('result');
root.textContent = 'Searching...';
var jsonp = document.createElement('script');
jsonp.src = url;
document.head.appendChild(jsonp);
}
function hasSearched(jsonp)
{
var root = document.getElementById('result');
// remove old elements
root.textContent = '';
for(var i = root.childNodes.length-1; i >= 0; i --)
root.removeChild(root.childNodes[i]);
var result = jsonp;
//var result = JSON.parse(escape(jsonp));
document.getElementById('hit').innerHTML = 'result. ' + escape(result.length) + ' hit(s).';
// 最長文字数を調べる
var lenmax = 0;
for(var i = 0; i < result.length; i ++){
if(result[i].title.length > lenmax)
lenmax = result[i].title.length;
}
lenmax /= 2;
for(var i = 0; i < result.length; i ++){
var span = document.createElement('span');
span.style = "display: inline-block; width: " + lenmax + "em";
var check = document.createElement('input');
check.type = 'checkbox';
check.id = attrEscape(result[i].title);
check.value = attrEscape(result[i].title);
check.name = 'target';
span.appendChild(check);
var title = document.createElement('label');
title.setAttribute('for', attrEscape(result[i].title));
title.innerHTML = escape(result[i].title);
span.appendChild(title);
root.appendChild(span);
}
document.getElementById("searchButton").disabled = false;
}
// チャート表示 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function showChart()
{
var targets = '';
var boxes = document.getElementsByName('target');
for(var i = 0; i < boxes.length; i ++){
if(boxes[i].checked)
targets += ',' + boxes[i].value;
}
if(targets.length == 0){
alert("選択してください");
return;
}
targets = targets.substring(1);
document.getElementById("resetZoomButton").style = "visibility: hidden";
document.getElementById("showButton").disabled = true;
document.getElementById("bar") .disabled = true;
document.getElementById("heatmap") .disabled = true;
document.getElementById("sortableList").style.display = "none";
var sortableList = document.getElementById("sortableList");
for(var i = sortableList.childNodes.length-1; i >= 0; i --)
sortableList.removeChild(sortableList.childNodes[i]);
var chartType;
if(document.getElementById('bar').checked)
chartType = 'bar';
else
chartType = 'heatmap';
retrieveChartData(targets, chartType);
}
// データ取得 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function retrieveChartData(targets, chartType)
{
var url = 'https://script.google.com/macros/s/AKfycbwnSskrJWOPYksPyPqL5zHhGQxqeRpHhxt6ZzfaH-OCoMbG_w51/exec?id=' + targets + '&type=' + chartType + '&q=data&callback=hasRetrieved';
//var url = '/lipo/data.php?id=' + targets + '&type=' + chartType + '&q=data';
// jsonpを使った取得
var ignore0 = document.getElementById("ignore0");
for(var i = ignore0.childNodes.length-1; i >= 0; i --)
ignore0.removeChild(ignore0.childNodes[i]);
var pieRoot = document.getElementById('pieContainer');
for(var i = pieRoot.childNodes.length-1; i >= 0; i --)
pieRoot.removeChild(pieRoot.childNodes[i]);
var root = document.getElementById('container');
for(var i = root.childNodes.length-1; i >= 0; i --)
root.removeChild(root.childNodes[i]);
root.textContent = 'Retrieving...';
var jsonp = document.createElement('script');
jsonp.src = url;
document.head.appendChild(jsonp);
}
// コールバック関数(jsonp) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function hasRetrieved(jsonp)
{
var root = document.getElementById('container');
// remove old elements
root.textContent = '';
// for(var i = root.childNodes.length-1; i >= 0; i --)
// root.removeChild(root.childNodes[i]);
var chartType;
if(document.getElementById('bar').checked)
chartType = 'bar';
else
chartType = 'heatmap';
var ignore0 = document.getElementById("ignore0");
var cbox0ignore = document.createElement("input");
cbox0ignore.id = "ignore0box";
cbox0ignore.setAttribute("type","checkbox");
ignore0.appendChild(cbox0ignore);
var ignoreLabel = document.createElement("label");
ignoreLabel.innerHTML = "ignore 0-intensity column(s)";
ignoreLabel.setAttribute("for", "ignore0box");
ignore0.appendChild(ignoreLabel);
var result = jsonp;
//var result = JSON.parse(escape(jsonp));
if(chartType == 'bar')
showBarChart(result);
else
showHeatmap(result);
document.getElementById("showButton").disabled = false;
document.getElementById("bar") .disabled = false;
document.getElementById("heatmap") .disabled = false;
document.getElementById("sortableList").style.display = "block";
}
// バーチャート ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
var gBarData;
function getInchiOnBar(seq, x)
{
window.open("http://jcbl.jp/","new");
console.log(seq + "/" + x + " => " + gBarData[seq][x]);
}
var chart;
var piechart;
var defaultTickInterval = currentTickInterval = 5;
// バーチャートのズーム解除 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function unzoomBarCharts() {
for(var i = 0; i < chart.length; i ++){
//chart[i].xAxis[0].options.tickInterval = defaultTickInterval;
chart[i].xAxis[0].isDirty = true;
chart[i].xAxis[0].setExtremes(null, null, animation=true);
}
document.getElementById("resetZoomButton").style = "visibility: hidden";
}
// データの切り替え(表示/非表示、0-intensity) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function setBarchartData()
{ // inchiキー未処理 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var target = [];
var ignore0 = !document.getElementById("ignore0box").checked;
var xLabels = [];
for(var j = 0; j < chart[0].data.length; j ++){
var not0 = false;
for(var i = 0; i < chart.length; i ++){
if(ignore0 || chart[i].data[j] != 0){
not0 = true;
break;
}
}
target[j] = not0;
}
for(var j = 0; j < chart.length; j ++){
var i = 0;
var data = [];
for(var k = 0,l = 0; k < chart[j].data.length; k ++){
if(target[k]){
data[i++] = chart[j].data[k];
}
}
chart[j].series[0].setData(data, true);
}
unzoomBarCharts();
}
// 表示 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function showBarChart(result)
{
function computeTickInterval(xMin, xMax)
{
var zoomRange = xMax - xMin;
if(zoomRange <= 2)
currentTickInterval = 0.5;
if(zoomRange < 20)
currentTickInterval = 1;
else if(zoomRange < 100)
currentTickInterval = 5;
}
// create ignore 0-intensity button
document.getElementById("ignore0box").onchange = function(){
setBarchartData();
};
// create sortable list
var sortableList = document.getElementById("sortableList");
for(var i = 0; i < result[0].map.length; i ++){
var line = document.createElement("div");
var cbox = document.createElement("input");
cbox.setAttribute("type", "checkbox");
cbox.setAttribute("checked", "yes");
cbox.setAttribute("seq", i);
cbox.id = "item" + i;
cbox.onchange = function(e){
// 表示/非表示の切り替え
var seq = this.getAttribute("seq");
var option;
if(this.checked){
option = "block";
} else {
option = "none";
}
document.getElementById("container" + seq).style.display = option;
document.getElementById("pieContainer" + seq).style.display = option;
};
line.appendChild(cbox);
var label = document.createElement("label");
label.setAttribute("for", "item" + i);
label.innerHTML = (i+1) + "." + escape(result[0].map[i].title);
line.appendChild(label);
sortableList.appendChild(line);
}
$('#sortableList').sortable({
cursor: 'move',
update: function(event, ui){
var sortableList = document.getElementById("sortableList");
for(var i = 0; i < sortableList.childNodes.length; i ++){
var seq = sortableList.childNodes[i].childNodes[0].getAttribute("seq");
document.getElementById("container" + seq).setAttribute("order", i);
document.getElementById("pieContainer" + seq).setAttribute("order", i);
}
$("#container").html(
$("#container > div").sort(function(o1,o2)
{
var n1 = parseInt($(o1).attr("order"), 10);
var n2 = parseInt($(o2).attr("order"), 10);
if(n1 < n2) return -1;
if(n1 > n2) return 1;
return 0;
})
);
$("#pieContainer").html(
$("#pieContainer > div").sort(function(o1,o2)
{
var n1 = parseInt($(o1).attr("order"), 10);
var n2 = parseInt($(o2).attr("order"), 10);
if(n1 < n2) return -1;
if(n1 > n2) return 1;
return 0;
})
);
}
});
// create barchart(s)
gBarData = [];
chart = [];
piechart = [];
var root = document.getElementById('container');
var pieRoot = document.getElementById('pieContainer');
for(var i = 0; i < result[0].map.length; i ++){
gBarData[i] = [];
// データの整理
var data = [];
for(var j = 0; j < result[0].map[i].data.length; j ++){
data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0])];
gBarData[i][j] = inchiEscape(result[0].map[i].data[j][2]); // InChIキー
}
// barchartの追加
var parent = document.createElement('div');
parent.id = 'container' + i;
parent.setAttribute("order", i);
root.appendChild(parent);
chart[i] = new Highcharts.Chart({
chart: {
type: 'column',
zoomType: 'x',
renderTo: parent,
height: 250,
resetZoomButton: {
theme: {
display: 'none'
}
}
},
title: {
text: (i+1) + '.' + attrEscape(result[0].map[i].title)
},
xAxis: {
min: 0,
type: 'category',
labels: {
rotation: -90,
style: {
fontSize: '11px',
fontFamily: 'Verdana, sans-serif'
}
},
title: {
text: '分子種'
},
events : {
afterSetExtremes: function(){
if(!this.chart.options.chart.isZoomed){
var xMin = this.chart.xAxis[0].min;
var xMax = this.chart.xAxis[0].max;
var zmRange = computeTickInterval(xMin, xMax);
for(var i = 0; i < chart.length; i ++){
chart[i].xAxis[0].options.tickInterval = zmRange;
chart[i].xAxis[0].isDirty = true;
if(chart[i] !== this){
chart[i].options.chart.isZoomed = true;
chart[i].xAxis[0].setExtremes(xMin, xMax, true);
chart[i].options.chart.isZoomed = false;
}
}
document.getElementById("resetZoomButton").style = "visibility: visible";
}
},
}
},
scrollbar: {
enabled: true
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Relative Intensity(%)'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: '<b>{point.y:.1f} %</b>'
},
series: [{
name: 'Population',
data: data,
events: {
click: function(event) {
//alert(event.point.name);
var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container","");
getInchiOnBar(index, event.point.x);
}
}
}]
});
chart[i].data = data;
// piechartの追加
var pieParent = document.createElement('div');
pieParent.id = 'pieContainer' + i;
pieParent.setAttribute("order", i);
pieRoot.appendChild(pieParent);
piechart[i] = new Highcharts.Chart({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie',
renderTo: pieParent,
height: 250
},
title: {
text: (i+1) + '.amount'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
name: 'Brands',
colorByPoint: true,
data: result[0].map[i].pie,
events: {
click: function(event) {
var nextType = event.point.name;
var targets = '';
var sortableList = document.getElementById("sortableList");
for(var i = 0; i < sortableList.childNodes.length; i ++){
var w = sortableList.childNodes[i].childNodes[1].innerHTML.replace(/^[0-9]+./,"").split("/");
targets += "," + w[0] + "/" + w[1] + "/" + nextType;
}
targets = targets.substring(1);
document.getElementById("showButton").disabled = true;
document.getElementById("bar") .disabled = true;
document.getElementById("heatmap") .disabled = true;
document.getElementById("sortableList").style.display = "none";
var sortableList = document.getElementById("sortableList");
for(var i = sortableList.childNodes.length-1; i >= 0; i --)
sortableList.removeChild(sortableList.childNodes[i]);
retrieveChartData(targets, 'bar');
}
}
}]
});
}
}
// ヒートマップ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
var chart;
var gHeatmapData;
function getInchiOnHeatmap(seq, x, y) // 未使用
{
window.open("http://jcbl.jp/","new");
console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq][y][x]);
}
function jumpToJcbl(inchi)
{
window.open("http://jcbl.jp/","new");
console.log(inchi);
}
// データの切り替え(表示/非表示、0-intensity) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function setHeatmapData(index, seq)
{
var i = 0;
var length = gHeatmapData[index].map.length;
var target = [];
var ignore0 = !document.getElementById("ignore0box").checked;
var xLabels = [];
for(var k = 0; k < gHeatmapData[index].map[0].data.length; k ++){
var not0 = false;
for(var j = 0; j < length; j ++){
if(ignore0 || gHeatmapData[index].map[j].data[k][0] != 0){
not0 = true;
break;
}
}
target[k] = not0;
if(not0)
xLabels[i++] = gHeatmapData[index].x[k];
}
var data = [];
var yLabels = [];
chart[index].inchi = [];
i = 0;
for(var j = 0; j < seq.length && j < length; j ++){
chart[index].inchi[j] = [];
for(var k = 0,l = 0; k < gHeatmapData[index].map[seq[j]].data.length; k ++){
if(target[k]){
data[i] = [l++, seq.length-j-1, attrEscape(gHeatmapData[index].map[seq[j]].data[k][0])];
chart[index].inchi[j][k] = inchiEscape(gHeatmapData[index].map[seq[j]].data[k][2]);
i ++;
}
}
yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(gHeatmapData[index].map[seq[j]].title);
}
yLabels.reverse();
chart[index].series[0].setData(data, true);
chart[index].yAxis[0].setCategories(yLabels);
chart[index].xAxis[0].setCategories(xLabels);
}
// 表示 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function showHeatmap(result)
{
gHeatmapData = [];
var root = document.getElementById('container');
var sortableList = document.getElementById("sortableList");
chart = [];
gHeatmapData = result;
for(var i = 0; i < result.length; i ++){
// タイトル
var title = attrEscape(result[i].title);
// 親要素
var parent = document.createElement('div');
parent.id = 'container' + i;
root.appendChild(parent);
var index = 0;
var data = [];
var yLabels = [];
var length = result[i].map.length
var inchi = [];
for(var j = 0; j < length; j ++){
inchi[j] = [];
for(var k = 0; k < result[i].map[j].data.length; k ++){
data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0])];
inchi[j][k] = inchiEscape(result[i].map[j].data[k][2]);
index ++;
}
yLabels[j] = (j+1) + "." + attrEscape(result[i].map[j].title);
}
yLabels.reverse();
for(var j = 0; j < result[i].x.length; j ++)
result[i].x[j] = attrEscape(result[i].x[j]);
// create ignore 0-intensity button
document.getElementById("ignore0box").onchange = function(){
// 表示/非表示の切り替え // 下と同じなので、後でまとめる
for(var index = 0; index < chart.length; index ++){
var sortableList = document.getElementById("sortableList" + index);
var sequence = [];
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){
if(sortableList.childNodes[i].childNodes[0].checked)
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq");
}
setHeatmapData(index, sequence);
}
};
// create sortable list
var listDiv = document.createElement("div");
listDiv.id = "sortableList" + i;
for(var j = 0; j < result[i].map.length; j ++){
var line = document.createElement("div");
var cbox = document.createElement("input");
cbox.setAttribute("type", "checkbox");
cbox.setAttribute("checked", "yes");
cbox.setAttribute("seq", j);
cbox.id = "item" + j;
cbox.onchange = function(e){
// 表示/非表示の切り替え
var index = this.parentElement.parentElement.id.replace("sortableList", "");
var sortableList = document.getElementById("sortableList" + index);
var sequence = [];
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){
if(sortableList.childNodes[i].childNodes[0].checked)
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq");
}
setHeatmapData(index, sequence);
};
line.appendChild(cbox);
var label = document.createElement("label");
label.setAttribute("for", "item" + j);
label.innerHTML = (j+1) + "." + escape(result[i].map[j].title);
line.appendChild(label);
listDiv.appendChild(line);
}
sortableList.appendChild(listDiv);
$('#sortableList' + i).sortable({
cursor: 'move',
update: function(event, ui){
var index = ui.item[0].parentElement.id.replace("sortableList", "");
var sortableList = document.getElementById("sortableList" + index);
var sequence = [];
for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){
if(sortableList.childNodes[i].childNodes[0].checked)
sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq");
}
setHeatmapData(index, sequence);
}
});
$('#sortableList').sortable(false);
// ヒートマップ
chart[i] = new Highcharts.Chart({
chart: {
type: 'heatmap',
zoomType: 'xy',
animation: 1,
marginBottom: 0,
plotBorderWidth: 1,
renderTo: parent,
animation: true,
},
scrollbar: {
enabled: true
},
title: {
text: title,
align: 'left'
},
xAxis: {
categories: result[i].x,
opposite: true,
labels: {
rotation: -90,
style: {
fontSize: '11px',
fontFamily: 'Verdana, sans-serif'
}
},
},
yAxis: {
categories: yLabels,
title: null
},
colorAxis: {
min: 0,
max: 100,
minColor: '#ffffff',
maxColor: Highcharts.getOptions().colors[8]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 100,
symbolHeight: 145
},
tooltip: {
formatter: function () {
return this.series.yAxis.categories[this.point.y] + '<br />' +
this.series.xAxis.categories[this.point.x] + '<br />' +
(Math.round(this.point.value*10)/10) + ' %';
}
},
series: [{
name: 'HEK',
borderWidth: 1,
data: data,
dataLabels: {
enabled: false,
color: '#000000'
},
point: {
events: {
/*mouseOver: function() {
var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container", "");
var target = getTarget(this.series.chart.xAxis[0].labelGroup.element.childNodes, result[index].x[this.x]);
if(target != null){
target.css('fill', 'red');
target.css('fontWeight', 'bold');
}
$(this.series.chart.yAxis[0].labelGroup.element.childNodes[this.y]).css('fill', 'red');
$(this.series.chart.yAxis[0].labelGroup.element.childNodes[this.y]).css('fontWeight', 'bold');
},
mouseOut: function() {
var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container", "");
var target = getTarget(this.series.chart.xAxis[0].labelGroup.element.childNodes, result[index].x[this.x]);
if(target != null){
target.css('fill', '#666666');
target.css('fontWeight', '');
}
$(this.series.chart.yAxis[0].labelGroup.element.childNodes[this.y]).css('fill', '#666666');
$(this.series.chart.yAxis[0].labelGroup.element.childNodes[this.y]).css('fontWeight', '');
},*/
click: function(event){
// var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container","");
// getInchiOnHeatmap(index, event.point.x, event.point.y);
jumpToJcbl(event.point.series.chart.inchi[event.point.y][event.point.x]);
}
}
}
}]
});
chart[i].inchi = inchi;
//chart.setSize(600,300,false);
}
resizeHeatmap();
}
// ※未使用※ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getTarget(children, target)
{
for(var i = 0; i < children.length; i ++){
if(target == children[i].childNodes[0].textContent){
return $(children[i]);
}
// console.log(children[i].childNodes[0].textContent);
}
return null;
}