201 lines
6.8 KiB
JavaScript
201 lines
6.8 KiB
JavaScript
|
/*
|
||
|
* Flot plugin to order bars side by side.
|
||
|
*
|
||
|
* Released under the MIT license by Benjamin BUFFET, 20-Sep-2010.
|
||
|
* Modifications made by Steven Hall <github.com/emmerich>, 01-May-2013.
|
||
|
*
|
||
|
* This plugin is an alpha version.
|
||
|
*
|
||
|
* To activate the plugin you must specify the parameter "order" for the specific serie :
|
||
|
*
|
||
|
* $.plot($("#placeholder"), [{ data: [ ... ], bars :{ order = null or integer }])
|
||
|
*
|
||
|
* If 2 series have the same order param, they are ordered by the position in the array;
|
||
|
*
|
||
|
* The plugin adjust the point by adding a value depanding of the barwidth
|
||
|
* Exemple for 3 series (barwidth : 0.1) :
|
||
|
*
|
||
|
* first bar décalage : -0.15
|
||
|
* second bar décalage : -0.05
|
||
|
* third bar décalage : 0.05
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
// INFO: decalage/decallage is French for gap. It's used to denote the spacing applied to each
|
||
|
// bar.
|
||
|
(function($){
|
||
|
function init(plot){
|
||
|
var orderedBarSeries;
|
||
|
var nbOfBarsToOrder;
|
||
|
var borderWidth;
|
||
|
var borderWidthInXabsWidth;
|
||
|
var pixelInXWidthEquivalent = 1;
|
||
|
var isHorizontal = false;
|
||
|
|
||
|
// A mapping of order integers to decallage.
|
||
|
var decallageByOrder = {};
|
||
|
|
||
|
/*
|
||
|
* This method add shift to x values
|
||
|
*/
|
||
|
function reOrderBars(plot, serie, datapoints){
|
||
|
var shiftedPoints = null;
|
||
|
|
||
|
if(serieNeedToBeReordered(serie)){
|
||
|
checkIfGraphIsHorizontal(serie);
|
||
|
calculPixel2XWidthConvert(plot);
|
||
|
retrieveBarSeries(plot);
|
||
|
calculBorderAndBarWidth(serie);
|
||
|
|
||
|
if(nbOfBarsToOrder >= 2){
|
||
|
var position = findPosition(serie);
|
||
|
var decallage = 0;
|
||
|
|
||
|
var centerBarShift = calculCenterBarShift();
|
||
|
|
||
|
// If we haven't already calculated the decallage for this order value, do it.
|
||
|
if(typeof decallageByOrder[serie.bars.order] === 'undefined') {
|
||
|
if (isBarAtLeftOfCenter(position)){
|
||
|
decallageByOrder[serie.bars.order] = -1*(sumWidth(orderedBarSeries,position-1,Math.floor(nbOfBarsToOrder / 2)-1)) - centerBarShift;
|
||
|
}else{
|
||
|
decallageByOrder[serie.bars.order] = sumWidth(orderedBarSeries,Math.ceil(nbOfBarsToOrder / 2),position-2) + centerBarShift + borderWidthInXabsWidth*2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Lookup the decallage based on the series' order value.
|
||
|
decallage = decallageByOrder[serie.bars.order];
|
||
|
|
||
|
shiftedPoints = shiftPoints(datapoints,serie,decallage);
|
||
|
datapoints.points = shiftedPoints;
|
||
|
}
|
||
|
}
|
||
|
return shiftedPoints;
|
||
|
}
|
||
|
|
||
|
function serieNeedToBeReordered(serie){
|
||
|
return serie.bars != null
|
||
|
&& serie.bars.show
|
||
|
&& serie.bars.order != null;
|
||
|
}
|
||
|
|
||
|
function calculPixel2XWidthConvert(plot){
|
||
|
var gridDimSize = isHorizontal ? plot.getPlaceholder().innerHeight() : plot.getPlaceholder().innerWidth();
|
||
|
var minMaxValues = isHorizontal ? getAxeMinMaxValues(plot.getData(),1) : getAxeMinMaxValues(plot.getData(),0);
|
||
|
var AxeSize = minMaxValues[1] - minMaxValues[0];
|
||
|
pixelInXWidthEquivalent = AxeSize / gridDimSize;
|
||
|
}
|
||
|
|
||
|
function getAxeMinMaxValues(series,AxeIdx){
|
||
|
var minMaxValues = new Array();
|
||
|
for(var i = 0; i < series.length; i++){
|
||
|
minMaxValues[0] = (series[i].data[0]) ? series[i].data[0][AxeIdx]: null;
|
||
|
minMaxValues[1] = (series[i].data[series[i].data.length - 1]) ? series[i].data[series[i].data.length - 1][AxeIdx]: null;
|
||
|
}
|
||
|
return minMaxValues;
|
||
|
}
|
||
|
|
||
|
function retrieveBarSeries(plot){
|
||
|
orderedBarSeries = findOthersBarsToReOrders(plot.getData());
|
||
|
nbOfBarsToOrder = orderedBarSeries.length;
|
||
|
}
|
||
|
|
||
|
function findOthersBarsToReOrders(series){
|
||
|
var retSeries = new Array();
|
||
|
var orderValuesSeen = [];
|
||
|
|
||
|
for(var i = 0; i < series.length; i++){
|
||
|
if(series[i].bars.order != null && series[i].bars.show &&
|
||
|
orderValuesSeen.indexOf(series[i].bars.order) < 0){
|
||
|
|
||
|
orderValuesSeen.push(series[i].bars.order);
|
||
|
retSeries.push(series[i]);
|
||
|
}
|
||
|
}
|
||
|
return retSeries.sort(sortByOrder);
|
||
|
}
|
||
|
|
||
|
function sortByOrder(serie1,serie2){
|
||
|
var x = serie1.bars.order;
|
||
|
var y = serie2.bars.order;
|
||
|
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
||
|
}
|
||
|
|
||
|
function calculBorderAndBarWidth(serie){
|
||
|
borderWidth = typeof serie.bars.lineWidth !== 'undefined' ? serie.bars.lineWidth : 2;
|
||
|
borderWidthInXabsWidth = borderWidth * pixelInXWidthEquivalent;
|
||
|
}
|
||
|
|
||
|
function checkIfGraphIsHorizontal(serie){
|
||
|
if(serie.bars.horizontal){
|
||
|
isHorizontal = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function findPosition(serie){
|
||
|
var pos = 0
|
||
|
for (var i = 0; i < orderedBarSeries.length; ++i) {
|
||
|
if (serie == orderedBarSeries[i]){
|
||
|
pos = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pos+1;
|
||
|
}
|
||
|
|
||
|
function calculCenterBarShift(){
|
||
|
var width = 0;
|
||
|
|
||
|
if(nbOfBarsToOrder%2 != 0)
|
||
|
width = (orderedBarSeries[Math.ceil(nbOfBarsToOrder / 2)].bars.barWidth)/2;
|
||
|
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
function isBarAtLeftOfCenter(position){
|
||
|
return position <= Math.ceil(nbOfBarsToOrder / 2);
|
||
|
}
|
||
|
|
||
|
function sumWidth(series,start,end){
|
||
|
var totalWidth = 0;
|
||
|
|
||
|
for(var i = start; i <= end; i++){
|
||
|
totalWidth += series[i].bars.barWidth+borderWidthInXabsWidth*2;
|
||
|
}
|
||
|
|
||
|
return totalWidth;
|
||
|
}
|
||
|
|
||
|
function shiftPoints(datapoints,serie,dx){
|
||
|
var ps = datapoints.pointsize;
|
||
|
var points = datapoints.points;
|
||
|
var j = 0;
|
||
|
for(var i = isHorizontal ? 1 : 0;i < points.length; i += ps){
|
||
|
points[i] += dx;
|
||
|
//Adding the new x value in the serie to be abble to display the right tooltip value,
|
||
|
//using the index 3 to not overide the third index.
|
||
|
serie.data[j][3] = points[i];
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
return points;
|
||
|
}
|
||
|
|
||
|
plot.hooks.processDatapoints.push(reOrderBars);
|
||
|
|
||
|
}
|
||
|
|
||
|
var options = {
|
||
|
series : {
|
||
|
bars: {order: null} // or number/string
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$.plot.plugins.push({
|
||
|
init: init,
|
||
|
options: options,
|
||
|
name: "orderBars",
|
||
|
version: "0.2"
|
||
|
});
|
||
|
|
||
|
})(jQuery);
|