MediaWiki:Lipoquality.js: Difference between revisions

mNo edit summary
No edit summary
Line 72: Line 72:
function escape(text)
function escape(text)
{
{
if(isFinite(text))
return text;
return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
}
Line 79: Line 81:
return text;
return text;
return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&rsquo;");
return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&rsquo;");
}
function inchiEscape(text)
{
if(isFinite(text))
return text;
return text.replace(/[^A-Z0-9-]/g, "");
}
}
function search()
function search()
Line 89: Line 97:
var type    = document.getElementById("type").value;
var type    = document.getElementById("type").value;


var url = 'https://script.google.com/macros/s/AKfycbzx6dDKYI8fDsEpKJtHCtsjIGYS3sgfEFIuLbN9zJb6ba_yxAAs/exec?classification=' + classification + '&sample=' + sample + '&type=' + type + '&q=search';
var url = 'https://script.google.com/macros/s/AKfycbx3YyRXv0nkMVsJqasLJBp0n1j744dkI8AOXDibLJVx0_D4MKo/exec?classification=' + classification + '&sample=' + sample + '&type=' + type + '&q=search&callback=hasSearched';
// var url = '/lipo/json.txt'
// var url = '/lipo/json.txt'


var xmlHttpRequest = new XMLHttpRequest();
// jsonpを使って検索
xmlHttpRequest.onreadystatechange = function()
var root = document.getElementById('result');
{
root.textContent = 'Searching...';
var root = document.getElementById('result');
var jsonp = document.createElement('script');
// remove old elements
jsonp.src = url;
root.textContent = '';
document.head.appendChild(jsonp);
for(var i = root.childNodes.length-1; i >= 0; i --)
}
root.removeChild(root.childNodes[i]);


var READYSTATE_COMPLETED = 4;
function hasSearched(jsonp)
if(this.readyState == READYSTATE_COMPLETED){
{
var HTTP_STATUS_OK = 200;
var root = document.getElementById('result');
if(this.status == HTTP_STATUS_OK ) {
// remove old elements
// success
root.textContent = '';
var result = JSON.parse(escape(this.response));
for(var i = root.childNodes.length-1; i >= 0; i --)
document.getElementById('hit').innerHTML = 'result. ' + result.length + ' hit(s).';
root.removeChild(root.childNodes[i]);
for(var i = 0; i < result.length; i ++){
 
var check = document.createElement('input');
var result = jsonp;
check.type = 'checkbox';
//var result = JSON.parse(escape(jsonp));
check.id = result[i].replace(/"/g, "&quot");
document.getElementById('hit').innerHTML = 'result. ' + escape(result.length) + ' hit(s).';
check.value = result[i].replace(/"/g, "&quot");
for(var i = 0; i < result.length; i ++){
check.name  = 'target';
var check = document.createElement('input');
root.appendChild(check);
check.type = 'checkbox';
var title = document.createElement('label');
check.id = attrEscape(result[i]);
title.setAttribute('for', result[i]);
check.value = attrEscape(result[i]);
title.innerHTML = result[i];
check.name  = 'target';
root.appendChild(title);
root.appendChild(check);
root.appendChild(document.createElement('br'));
var title = document.createElement('label');
}
title.setAttribute('for', attrEscape(result[i]));
} else {
title.innerHTML = escape(result[i]);
// error
root.appendChild(title);
root.textContent = 'search failed. ' + this.status + ':' + this.statusText;
root.appendChild(document.createElement('br'));
}
document.getElementById("searchButton").disabled = false;
}
}
}
document.getElementById("searchButton").disabled = false;
}


// search
xmlHttpRequest.open('GET', url, true);
xmlHttpRequest.responseType = 'text';
xmlHttpRequest.send(null);
var root = document.getElementById('result');
root.textContent = 'Searching...';
}
function showChart()
function showChart()
{
{
Line 156: Line 155:
else
else
chartType = 'heatmap';
chartType = 'heatmap';
var url = 'https://script.google.com/macros/s/AKfycbzx6dDKYI8fDsEpKJtHCtsjIGYS3sgfEFIuLbN9zJb6ba_yxAAs/exec?id=' + targets + '&type=' + chartType + '&q=data';
var url = 'https://script.google.com/macros/s/AKfycbx3YyRXv0nkMVsJqasLJBp0n1j744dkI8AOXDibLJVx0_D4MKo/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';


var xmlHttpRequest = new XMLHttpRequest();
// jsonpを使った取得
xmlHttpRequest.onreadystatechange = function()
var root = document.getElementById('container');
{
root.textContent = 'Retrieving...';
var root = document.getElementById('container');
var jsonp = document.createElement('script');
// remove old elements
jsonp.src = url;
root.textContent = '';
document.head.appendChild(jsonp);
for(var i = root.childNodes.length-1; i >= 0; i --)
}
root.removeChild(root.childNodes[i]);


var READYSTATE_COMPLETED = 4;
function hasRetrieved(jsonp)
var HTTP_STATUS_OK = 200;
{
if(this.readyState == READYSTATE_COMPLETED){
if(this.status == HTTP_STATUS_OK) {
    // success
  var result = JSON.parse(escape(this.response));
if(chartType == 'bar')
showBarChart(result);
else
showHeatmap(result);
} else {
// error
root.textContent = 'retrieving failed. ' + this.status + ':' + this.statusText;
}
document.getElementById("showButton").disabled = false;
}
}
// retrieving
xmlHttpRequest.open('GET', url, true);
xmlHttpRequest.responseType = 'text';
xmlHttpRequest.send(null);
var root = document.getElementById('container');
var root = document.getElementById('container');
root.textContent = 'Retrieving...';
// 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 result = jsonp;
//var result = JSON.parse(escape(jsonp));
if(chartType == 'bar')
showBarChart(result);
else
showHeatmap(result);
document.getElementById("showButton").disabled = false;
}
}
var gBarData;
var gBarData;
function getInchiOnBar(seq, x)
function getInchiOnBar(seq, x)
Line 209: Line 205:
for(var j = 0; j < result[i].data.length; j ++){
for(var j = 0; j < result[i].data.length; j ++){
data[j] = [attrEscape(result[i].data[j][2]), attrEscape(result[i].data[j][3])];
data[j] = [attrEscape(result[i].data[j][2]), attrEscape(result[i].data[j][3])];
gBarData[i][j] = result[i].data[j][5]; // InChIキー
gBarData[i][j] = inchiEscape(result[i].data[j][5]); // InChIキー
}
}


Line 295: Line 291:
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, j, attrEscape(result[i].map[j].data[k][0])];
gHeatmapData[i][j][k] = result[i].map[j].data[k][2];
gHeatmapData[i][j][k] = inchiEscape(result[i].map[j].data[k][2]);
index ++;
index ++;
}
}

Revision as of 04:56, 15 March 2016

// html /////////////////////////////////////////////////////////////////////////////////////////////////////////
// <span id="search"></span><span id="show"></span>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// external script //////////////////////////////////////////////////////////////////////////////////////////////
mw.loader.load('https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js', "text/javascript");
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);

	setCombobox('Classification');
	setCombobox('Sample');
	setCombobox('Type');
}
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, "&quot;").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);
}
function escape(text)
{
	if(isFinite(text))
		return text;
	return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
function attrEscape(text)
{
	if(isFinite(text))
		return text;
	return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&rsquo;");
}
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/AKfycbx3YyRXv0nkMVsJqasLJBp0n1j744dkI8AOXDibLJVx0_D4MKo/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).';
	for(var i = 0; i < result.length; i ++){
		var check = document.createElement('input');
		check.type = 'checkbox';
		check.id	= attrEscape(result[i]);
		check.value = attrEscape(result[i]);
		check.name  = 'target';
		root.appendChild(check);
		var title = document.createElement('label');
		title.setAttribute('for', attrEscape(result[i]));
		title.innerHTML = escape(result[i]);
		root.appendChild(title);
		root.appendChild(document.createElement('br'));
	}
	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("showButton").disabled = true;
	var chartType;
	if(document.getElementById('bar').checked)
		chartType = 'bar';
	else
		chartType = 'heatmap';
	var url = 'https://script.google.com/macros/s/AKfycbx3YyRXv0nkMVsJqasLJBp0n1j744dkI8AOXDibLJVx0_D4MKo/exec?id=' + targets + '&type=' + chartType + '&q=data&callback=hasRetrieved';
	//var url = '/lipo/data.php?id=' +  targets + '&type=' + chartType + '&q=data';

	// jsonpを使った取得
	var root = document.getElementById('container');
	root.textContent = 'Retrieving...';
	var jsonp = document.createElement('script');
	jsonp.src = url;
	document.head.appendChild(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 result = jsonp;
	//var result = JSON.parse(escape(jsonp));
	if(chartType == 'bar')
		showBarChart(result);
	else
		showHeatmap(result);
	document.getElementById("showButton").disabled = false;
}

var gBarData;
function getInchiOnBar(seq, x)
{
	window.open("http://jcbl.jp/","new");
	console.log(seq + "/" + x + " => " + gBarData[seq][x]);
}
function showBarChart(result)
{
	gBarData = [];
	var root = document.getElementById('container');
	for(var i = 0; i < result.length; i ++){
		gBarData[i] = [];
		// データの整理
		var data = [];
		for(var j = 0; j < result[i].data.length; j ++){
			data[j] = [attrEscape(result[i].data[j][2]), attrEscape(result[i].data[j][3])];
			gBarData[i][j] = inchiEscape(result[i].data[j][5]); // InChIキー
		}

		// barchartの追加
		var parent = document.createElement('div');
		parent.id = 'container' + i;
		root.appendChild(parent);
		var chart = new Highcharts.Chart({
			chart: {
				type: 'column',
				renderTo: parent,
				height: 250,
			},
			title: {
				text: (i+1) + '.' + attrEscape(result[i].title)
			},
			xAxis: {
				type: 'category',
				labels: {
					rotation: -90,
					style: {
						fontSize: '11px',
						fontFamily: 'Verdana, sans-serif'
					}
				},
				title: {
					text: '分子種'
				},
			},
			scrollbar: {
				enabled: true
			},
			yAxis: {
				min: 0,
				max: 100,
				title: {
					text: 'Height'
				}
			},
			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);
				  }
				} 
			}]
		});
	}
}
var gHeatmapData;
function getInchiOnHeatmap(seq, x, y)
{
	window.open("http://jcbl.jp/","new");
	console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq][y][x]);
}
function showHeatmap(result)
{
	gHeatmapData = [];
	var root = document.getElementById('container');
	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 = [];
		gHeatmapData[i] = [];
		for(var j = 0; j < result[i].map.length; j ++){
			gHeatmapData[i][j] = [];
			for(var k = 0; k < result[i].map[j].data.length; k ++){
				data[index] = [k, j, attrEscape(result[i].map[j].data[k][0])];
				gHeatmapData[i][j][k] = inchiEscape(result[i].map[j].data[k][2]);
				index ++;
			}
			yLabels[j] = attrEscape(result[i].map[j].title);
		}
		for(var j = 0; j < result[i].x.length; j ++)
			result[i].x[j] = attrEscape(result[i].x[j]);
		var xMax = result[i].x.length-1;
		if(xMax > 10)
			xMax = 10;
		// ヒートマップ
		var chart = new Highcharts.Chart({
	
			chart: {
				type: 'heatmap',
				marginBottom: 0,
				plotBorderWidth: 1,
				renderTo: parent,
			},
	
			scrollbar: {
				enabled: true
			},
	
			title: {
				text: title
			},
	
			xAxis: {
				categories: result[i].x,
				opposite: true,
				labels: {
					rotation: -90,
					style: {
						fontSize: '11px',
						fontFamily: 'Verdana, sans-serif'
					}
				},
				max: xMax
			},
	
			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);
						}
					}
				}
			}]
	
		});
		//chart.setSize(600,300,false);
	}
}
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;
}