(function ($) {
var setupTooltip = function () {
$('[data-toggle="tooltip"]').tooltip({
'placement': 'top',
'container': 'body',
'html': 'true',
'white-space': 'nowrap'
});
};
var setupClick = function ($graphDiv) {
$('a', $graphDiv).click(function (evt) {
evt.preventDefault();
evt.stopPropagation();
window.location.hash = $(this).attr('href');
});
};
var setupResponsiveness = function ($queryDiv, $graphDiv, index, opts) {
var currentWidth = $(window).width();
var debounced_draw = _.debounce(function () {
if (currentWidth !== $(window).width()) {
var shownHits = $queryDiv.find('.ghit > g').length;
$.graphIt($queryDiv, $graphDiv, shownHits, index, opts);
currentWidth = $(window).width();
}
}, 125);
$(window).resize(debounced_draw);
};
var graphControls = function ($queryDiv, $graphDiv, isInit) {
var MIN_HITS_TO_SHOW = 20;
var totalHits, shownHits, lessButton, moreButton;
var countHits = function () {
totalHits = $queryDiv.data().hitCount;
shownHits = $queryDiv.find('.ghit > g').length;
};
var setupButtons = function($queryDiv, $graphDiv) {
$graphDiv
.append(
$('')
.addClass('btn btn-link more')
.attr('type', 'button')
.attr('data-parent-query', $queryDiv.attr('id'))
.html('View More ')
.append(
$('')
.addClass('fa fa-angle-double-down')
),
$('')
.addClass('btn btn-link less')
.attr('type', 'button')
.attr('data-parent-query', $queryDiv.attr('id'))
.html('View Less ')
.append(
$('')
.addClass('fa fa-angle-double-up')
)
);
lessButton = $('.less', $graphDiv);
moreButton = $('.more', $graphDiv);
};
var initButtons = function () {
countHits();
if (totalHits === MIN_HITS_TO_SHOW ||
shownHits < MIN_HITS_TO_SHOW) {
lessButton.hide();
moreButton.hide();
}
else if (shownHits === totalHits) {
moreButton.hide();
lessButton.show();
}
else if (shownHits === MIN_HITS_TO_SHOW) {
lessButton.hide();
moreButton.show();
}
else {
lessButton.show();
moreButton.show();
}
};
// Setup view buttons' state properly if called for first time.
if (isInit === true) {
setupButtons($queryDiv, $graphDiv);
initButtons();
}
moreButton.on('click', function (e) {
countHits();
$.graphIt($queryDiv, $graphDiv, shownHits, MIN_HITS_TO_SHOW);
initButtons();
setupTooltip();
e.stopPropagation();
});
lessButton.on('click', function (e) {
countHits();
var diff = shownHits - MIN_HITS_TO_SHOW;
// Decrease number of shown hits by defined constant.
if (diff >= MIN_HITS_TO_SHOW) {
$.graphIt($queryDiv, $graphDiv, shownHits, -MIN_HITS_TO_SHOW);
initButtons();
}
else if (diff !== 0) {
// Ensure a certain number of hits always stay in graph.
$.graphIt($queryDiv, $graphDiv, shownHits, MIN_HITS_TO_SHOW - shownHits);
initButtons();
}
setupTooltip();
e.stopPropagation();
});
};
/* Extracts data from document data-attribs are returns in
* suitable object.
*/
var extractData = function ($queryDiv, index, howMany) {
var hitPanels, hits = [];
hitPanels = $queryDiv.find('.hitn').slice(0, index + howMany);
hitPanels.map(function () {
var $this = $(this);
var _hsps = [];
$this.find('.hsp').each(function () {
var __hsps = [];
__hsps = $(this).data();
__hsps.hspId = this.id;
_hsps.push(__hsps);
});
_hsps.hitId = $this.attr('id');
_hsps.hitDef = $this.data().hitDef;
_hsps.hitEvalue = $this.data().hitEvalue;
hits.push(_hsps);
});
return hits;
};
var drawLegend = function (svg, options, width, height) {
var svg_legend = svg.append('g')
.attr('transform',
'translate(0,' + (height - options.margin - options.legend * 1.25) + ')');
svg_legend.append('rect')
.attr('x', 7 * (width - 2 * options.margin) / 10)
.attr('width', 2 * (width - 4 * options.margin) / 10)
.attr('height', options.legend)
.attr('fill', 'url(#legend-grad)');
svg_legend.append('text')
.attr('transform', 'translate(0, ' +options.legend +')')
.attr('x', 6 * (width - 2 * options.margin) / 10 - options.margin / 2)
.text("Weaker hits");
svg_legend.append('text')
.attr('transform', 'translate(0, ' + options.legend + ')')
.attr('x', 9 * (width - 2 * options.margin) / 10 + options.margin / 2)
.text("Stronger hits");
svg.append('linearGradient')
.attr('id', 'legend-grad')
.selectAll('stop')
.data([
{offset: "0%", color: "#ccc"},
{offset: '50%', color: '#888'},
{offset: "100%", color: "#000"}
])
.enter()
.append('stop')
.attr('offset', function (d) {
return d.offset;
})
.attr('stop-color', function (d) {
return d.color;
});
};
/* Main method responsible for drawing the graphical overview.
* Query div and target div element along with suitable options
* are provided by the calling function.
*/
$.extend({
graphIt: function ($queryDiv, $graphDiv, index, howMany, opts) {
/* barHeight: Height of each hit track.
* barPadding: Padding around each hit track.
* legend: Height reserved for the overview legend.
* margin: Margin around the svg element.
*/
var defaults = {
barHeight: 4,
barPadding: 5,
legend: 10,
margin: 20
},
options = $.extend(defaults, opts),
hits = extractData($queryDiv, index, howMany);
// Don't draw anything when no hits are obtained.
if (hits.length < 1) return false;
if (index !== 0) {
// Currently, we have no good way to extend pre-existing graph
// and hence, are removing the old one and redrawing.
$graphDiv.find('svg').remove();
}
var queryLen = $queryDiv.data().queryLen;
var q_i = $queryDiv.attr('id');
var width = $graphDiv.width();
var height = hits.length * (options.barHeight + options.barPadding) +
5 * options.margin + options.legend * 3;
var svg = d3.select($graphDiv[0])
.selectAll('svg')
.data([hits])
.enter()
.insert('svg', ':first-child')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + options.margin / 4 + ', ' + options.margin / 4 + ')');
var x = d3.scale
.linear()
.range([0, width - options.margin]);
x.domain([1, queryLen]);
var _tValues = x.ticks(11);
_tValues.pop();
var xAxis = d3.svg
.axis()
.scale(x)
.orient('top')
.tickValues(_tValues.concat([1, queryLen]));
// Attach the axis to DOM (