js: remove obsolete js file that are no longer required in project.

This commit is contained in:
Marcin Kuzminski 2016-10-14 19:28:15 +02:00
parent eed69a96af
commit 1e9bb6006b
4 changed files with 0 additions and 4448 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,360 +0,0 @@
/* Flot plugin for selecting regions of a plot.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
The plugin supports these options:
selection: {
mode: null or "x" or "y" or "xy",
color: color,
shape: "round" or "miter" or "bevel",
minSize: number of pixels
}
Selection support is enabled by setting the mode to one of "x", "y" or "xy".
In "x" mode, the user will only be able to specify the x range, similarly for
"y" mode. For "xy", the selection becomes a rectangle where both ranges can be
specified. "color" is color of the selection (if you need to change the color
later on, you can get to it with plot.getOptions().selection.color). "shape"
is the shape of the corners of the selection.
"minSize" is the minimum size a selection can be in pixels. This value can
be customized to determine the smallest size a selection can be and still
have the selection rectangle be displayed. When customizing this value, the
fact that it refers to pixels, not axis units must be taken into account.
Thus, for example, if there is a bar graph in time mode with BarWidth set to 1
minute, setting "minSize" to 1 will not make the minimum selection size 1
minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent
"plotunselected" events from being fired when the user clicks the mouse without
dragging.
When selection support is enabled, a "plotselected" event will be emitted on
the DOM element you passed into the plot function. The event handler gets a
parameter with the ranges selected on the axes, like this:
placeholder.bind( "plotselected", function( event, ranges ) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis - with multiple axes, the extra ones are in
// x2axis, x3axis, ...
});
The "plotselected" event is only fired when the user has finished making the
selection. A "plotselecting" event is fired during the process with the same
parameters as the "plotselected" event, in case you want to know what's
happening while it's happening,
A "plotunselected" event with no arguments is emitted when the user clicks the
mouse to remove the selection. As stated above, setting "minSize" to 0 will
destroy this behavior.
The plugin allso adds the following methods to the plot object:
- setSelection( ranges, preventEvent )
Set the selection rectangle. The passed in ranges is on the same form as
returned in the "plotselected" event. If the selection mode is "x", you
should put in either an xaxis range, if the mode is "y" you need to put in
an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If you don't
want that to happen, e.g. if you're inside a "plotselected" handler, pass
true as the second parameter. If you are using multiple axes, you can
specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of
xaxis, the plugin picks the first one it sees.
- clearSelection( preventEvent )
Clear the selection rectangle. Pass in true to avoid getting a
"plotunselected" event.
- getSelection()
Returns the current selection in the same format as the "plotselected"
event. If there's currently no selection, the function returns null.
*/
(function ($) {
function init(plot) {
var selection = {
first: { x: -1, y: -1}, second: { x: -1, y: -1},
show: false,
active: false
};
// FIXME: The drag handling implemented here should be
// abstracted out, there's some similar code from a library in
// the navigation plugin, this should be massaged a bit to fit
// the Flot cases here better and reused. Doing this would
// make this plugin much slimmer.
var savedhandlers = {};
var mouseUpHandler = null;
function onMouseMove(e) {
if (selection.active) {
updateSelection(e);
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
}
}
function onMouseDown(e) {
if (e.which != 1) // only accept left-click
return;
// cancel out any text selections
document.body.focus();
// prevent text selection and drag in old-school browsers
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
savedhandlers.onselectstart = document.onselectstart;
document.onselectstart = function () { return false; };
}
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
savedhandlers.ondrag = document.ondrag;
document.ondrag = function () { return false; };
}
setSelectionPos(selection.first, e);
selection.active = true;
// this is a bit silly, but we have to use a closure to be
// able to whack the same handler again
mouseUpHandler = function (e) { onMouseUp(e); };
$(document).one("mouseup", mouseUpHandler);
}
function onMouseUp(e) {
mouseUpHandler = null;
// revert drag stuff for old-school browsers
if (document.onselectstart !== undefined)
document.onselectstart = savedhandlers.onselectstart;
if (document.ondrag !== undefined)
document.ondrag = savedhandlers.ondrag;
// no more dragging
selection.active = false;
updateSelection(e);
if (selectionIsSane())
triggerSelectedEvent();
else {
// this counts as a clear
plot.getPlaceholder().trigger("plotunselected", [ ]);
plot.getPlaceholder().trigger("plotselecting", [ null ]);
}
return false;
}
function getSelection() {
if (!selectionIsSane())
return null;
if (!selection.show) return null;
var r = {}, c1 = selection.first, c2 = selection.second;
$.each(plot.getAxes(), function (name, axis) {
if (axis.used) {
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
}
});
return r;
}
function triggerSelectedEvent() {
var r = getSelection();
plot.getPlaceholder().trigger("plotselected", [ r ]);
// backwards-compat stuff, to be removed in future
if (r.xaxis && r.yaxis)
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
}
function clamp(min, value, max) {
return value < min ? min: (value > max ? max: value);
}
function setSelectionPos(pos, e) {
var o = plot.getOptions();
var offset = plot.getPlaceholder().offset();
var plotOffset = plot.getPlotOffset();
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
if (o.selection.mode == "y")
pos.x = pos == selection.first ? 0 : plot.width();
if (o.selection.mode == "x")
pos.y = pos == selection.first ? 0 : plot.height();
}
function updateSelection(pos) {
if (pos.pageX == null)
return;
setSelectionPos(selection.second, pos);
if (selectionIsSane()) {
selection.show = true;
plot.triggerRedrawOverlay();
}
else
clearSelection(true);
}
function clearSelection(preventEvent) {
if (selection.show) {
selection.show = false;
plot.triggerRedrawOverlay();
if (!preventEvent)
plot.getPlaceholder().trigger("plotunselected", [ ]);
}
}
// function taken from markings support in Flot
function extractRange(ranges, coord) {
var axis, from, to, key, axes = plot.getAxes();
for (var k in axes) {
axis = axes[k];
if (axis.direction == coord) {
key = coord + axis.n + "axis";
if (!ranges[key] && axis.n == 1)
key = coord + "axis"; // support x1axis as xaxis
if (ranges[key]) {
from = ranges[key].from;
to = ranges[key].to;
break;
}
}
}
// backwards-compat stuff - to be removed in future
if (!ranges[key]) {
axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
from = ranges[coord + "1"];
to = ranges[coord + "2"];
}
// auto-reverse as an added bonus
if (from != null && to != null && from > to) {
var tmp = from;
from = to;
to = tmp;
}
return { from: from, to: to, axis: axis };
}
function setSelection(ranges, preventEvent) {
var axis, range, o = plot.getOptions();
if (o.selection.mode == "y") {
selection.first.x = 0;
selection.second.x = plot.width();
}
else {
range = extractRange(ranges, "x");
selection.first.x = range.axis.p2c(range.from);
selection.second.x = range.axis.p2c(range.to);
}
if (o.selection.mode == "x") {
selection.first.y = 0;
selection.second.y = plot.height();
}
else {
range = extractRange(ranges, "y");
selection.first.y = range.axis.p2c(range.from);
selection.second.y = range.axis.p2c(range.to);
}
selection.show = true;
plot.triggerRedrawOverlay();
if (!preventEvent && selectionIsSane())
triggerSelectedEvent();
}
function selectionIsSane() {
var minSize = plot.getOptions().selection.minSize;
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
Math.abs(selection.second.y - selection.first.y) >= minSize;
}
plot.clearSelection = clearSelection;
plot.setSelection = setSelection;
plot.getSelection = getSelection;
plot.hooks.bindEvents.push(function(plot, eventHolder) {
var o = plot.getOptions();
if (o.selection.mode != null) {
eventHolder.mousemove(onMouseMove);
eventHolder.mousedown(onMouseDown);
}
});
plot.hooks.drawOverlay.push(function (plot, ctx) {
// draw selection
if (selection.show && selectionIsSane()) {
var plotOffset = plot.getPlotOffset();
var o = plot.getOptions();
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
var c = $.color.parse(o.selection.color);
ctx.strokeStyle = c.scale('a', 0.8).toString();
ctx.lineWidth = 1;
ctx.lineJoin = o.selection.shape;
ctx.fillStyle = c.scale('a', 0.4).toString();
var x = Math.min(selection.first.x, selection.second.x) + 0.5,
y = Math.min(selection.first.y, selection.second.y) + 0.5,
w = Math.abs(selection.second.x - selection.first.x) - 1,
h = Math.abs(selection.second.y - selection.first.y) - 1;
ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
ctx.restore();
}
});
plot.hooks.shutdown.push(function (plot, eventHolder) {
eventHolder.unbind("mousemove", onMouseMove);
eventHolder.unbind("mousedown", onMouseDown);
if (mouseUpHandler)
$(document).unbind("mouseup", mouseUpHandler);
});
}
$.plot.plugins.push({
init: init,
options: {
selection: {
mode: null, // one of null, "x", "y" or "xy"
color: "#e8cfac",
shape: "round", // one of "round", "miter", or "bevel"
minSize: 5 // minimum number of pixels
}
},
name: 'selection',
version: '1.1'
});
})(jQuery);

View file

@ -1,432 +0,0 @@
/* Pretty handling of time axes.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
Set axis.mode to "time" to enable. See the section "Time series data" in
API.txt for details.
*/
(function($) {
var options = {
xaxis: {
timezone: null, // "browser" for local to the client or timezone for timezone-js
timeformat: null, // format string to use
twelveHourClock: false, // 12 or 24 time in time mode
monthNames: null // list of names of months
}
};
// round to nearby lower multiple of base
function floorInBase(n, base) {
return base * Math.floor(n / base);
}
// Returns a string with the date d formatted according to fmt.
// A subset of the Open Group's strftime format is supported.
function formatDate(d, fmt, monthNames, dayNames) {
if (typeof d.strftime == "function") {
return d.strftime(fmt);
}
var leftPad = function(n, pad) {
n = "" + n;
pad = "" + (pad == null ? "0" : pad);
return n.length == 1 ? pad + n : n;
};
var r = [];
var escape = false;
var hours = d.getHours();
var isAM = hours < 12;
if (monthNames == null) {
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
}
if (dayNames == null) {
dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
}
var hours12;
if (hours > 12) {
hours12 = hours - 12;
} else if (hours == 0) {
hours12 = 12;
} else {
hours12 = hours;
}
for (var i = 0; i < fmt.length; ++i) {
var c = fmt.charAt(i);
if (escape) {
switch (c) {
case 'a': c = "" + dayNames[d.getDay()]; break;
case 'b': c = "" + monthNames[d.getMonth()]; break;
case 'd': c = leftPad(d.getDate()); break;
case 'e': c = leftPad(d.getDate(), " "); break;
case 'h': // For back-compat with 0.7; remove in 1.0
case 'H': c = leftPad(hours); break;
case 'I': c = leftPad(hours12); break;
case 'l': c = leftPad(hours12, " "); break;
case 'm': c = leftPad(d.getMonth() + 1); break;
case 'M': c = leftPad(d.getMinutes()); break;
// quarters not in Open Group's strftime specification
case 'q':
c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
case 'S': c = leftPad(d.getSeconds()); break;
case 'y': c = leftPad(d.getFullYear() % 100); break;
case 'Y': c = "" + d.getFullYear(); break;
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
case 'w': c = "" + d.getDay(); break;
}
r.push(c);
escape = false;
} else {
if (c == "%") {
escape = true;
} else {
r.push(c);
}
}
}
return r.join("");
}
// To have a consistent view of time-based data independent of which time
// zone the client happens to be in we need a date-like object independent
// of time zones. This is done through a wrapper that only calls the UTC
// versions of the accessor methods.
function makeUtcWrapper(d) {
function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
sourceObj[sourceMethod] = function() {
return targetObj[targetMethod].apply(targetObj, arguments);
};
};
var utc = {
date: d
};
// support strftime, if found
if (d.strftime != undefined) {
addProxyMethod(utc, "strftime", d, "strftime");
}
addProxyMethod(utc, "getTime", d, "getTime");
addProxyMethod(utc, "setTime", d, "setTime");
var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
for (var p = 0; p < props.length; p++) {
addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
}
return utc;
};
// select time zone strategy. This returns a date-like object tied to the
// desired timezone
function dateGenerator(ts, opts) {
if (opts.timezone == "browser") {
return new Date(ts);
} else if (!opts.timezone || opts.timezone == "utc") {
return makeUtcWrapper(new Date(ts));
} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
var d = new timezoneJS.Date();
// timezone-js is fickle, so be sure to set the time zone before
// setting the time.
d.setTimezone(opts.timezone);
d.setTime(ts);
return d;
} else {
return makeUtcWrapper(new Date(ts));
}
}
// map of app. size of time units in milliseconds
var timeUnitSize = {
"second": 1000,
"minute": 60 * 1000,
"hour": 60 * 60 * 1000,
"day": 24 * 60 * 60 * 1000,
"month": 30 * 24 * 60 * 60 * 1000,
"quarter": 3 * 30 * 24 * 60 * 60 * 1000,
"year": 365.2425 * 24 * 60 * 60 * 1000
};
// the allowed tick sizes, after 1 year we use
// an integer algorithm
var baseSpec = [
[1, "second"], [2, "second"], [5, "second"], [10, "second"],
[30, "second"],
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
[30, "minute"],
[1, "hour"], [2, "hour"], [4, "hour"],
[8, "hour"], [12, "hour"],
[1, "day"], [2, "day"], [3, "day"],
[0.25, "month"], [0.5, "month"], [1, "month"],
[2, "month"]
];
// we don't know which variant(s) we'll need yet, but generating both is
// cheap
var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
[1, "year"]]);
var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
[1, "year"]]);
function init(plot) {
plot.hooks.processOptions.push(function (plot, options) {
$.each(plot.getAxes(), function(axisName, axis) {
var opts = axis.options;
if (opts.mode == "time") {
axis.tickGenerator = function(axis) {
var ticks = [];
var d = dateGenerator(axis.min, opts);
var minSize = 0;
// make quarter use a possibility if quarters are
// mentioned in either of these options
var spec = (opts.tickSize && opts.tickSize[1] ===
"quarter") ||
(opts.minTickSize && opts.minTickSize[1] ===
"quarter") ? specQuarters : specMonths;
if (opts.minTickSize != null) {
if (typeof opts.tickSize == "number") {
minSize = opts.tickSize;
} else {
minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
}
}
for (var i = 0; i < spec.length - 1; ++i) {
if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
+ spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
&& spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
break;
}
}
var size = spec[i][0];
var unit = spec[i][1];
// special-case the possibility of several years
if (unit == "year") {
// if given a minTickSize in years, just use it,
// ensuring that it's an integer
if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
size = Math.floor(opts.minTickSize[0]);
} else {
var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
var norm = (axis.delta / timeUnitSize.year) / magn;
if (norm < 1.5) {
size = 1;
} else if (norm < 3) {
size = 2;
} else if (norm < 7.5) {
size = 5;
} else {
size = 10;
}
size *= magn;
}
// minimum size for years is 1
if (size < 1) {
size = 1;
}
}
axis.tickSize = opts.tickSize || [size, unit];
var tickSize = axis.tickSize[0];
unit = axis.tickSize[1];
var step = tickSize * timeUnitSize[unit];
if (unit == "second") {
d.setSeconds(floorInBase(d.getSeconds(), tickSize));
} else if (unit == "minute") {
d.setMinutes(floorInBase(d.getMinutes(), tickSize));
} else if (unit == "hour") {
d.setHours(floorInBase(d.getHours(), tickSize));
} else if (unit == "month") {
d.setMonth(floorInBase(d.getMonth(), tickSize));
} else if (unit == "quarter") {
d.setMonth(3 * floorInBase(d.getMonth() / 3,
tickSize));
} else if (unit == "year") {
d.setFullYear(floorInBase(d.getFullYear(), tickSize));
}
// reset smaller components
d.setMilliseconds(0);
if (step >= timeUnitSize.minute) {
d.setSeconds(0);
}
if (step >= timeUnitSize.hour) {
d.setMinutes(0);
}
if (step >= timeUnitSize.day) {
d.setHours(0);
}
if (step >= timeUnitSize.day * 4) {
d.setDate(1);
}
if (step >= timeUnitSize.month * 2) {
d.setMonth(floorInBase(d.getMonth(), 3));
}
if (step >= timeUnitSize.quarter * 2) {
d.setMonth(floorInBase(d.getMonth(), 6));
}
if (step >= timeUnitSize.year) {
d.setMonth(0);
}
var carry = 0;
var v = Number.NaN;
var prev;
do {
prev = v;
v = d.getTime();
ticks.push(v);
if (unit == "month" || unit == "quarter") {
if (tickSize < 1) {
// a bit complicated - we'll divide the
// month/quarter up but we need to take
// care of fractions so we don't end up in
// the middle of a day
d.setDate(1);
var start = d.getTime();
d.setMonth(d.getMonth() +
(unit == "quarter" ? 3 : 1));
var end = d.getTime();
d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
carry = d.getHours();
d.setHours(0);
} else {
d.setMonth(d.getMonth() +
tickSize * (unit == "quarter" ? 3 : 1));
}
} else if (unit == "year") {
d.setFullYear(d.getFullYear() + tickSize);
} else {
d.setTime(v + step);
}
} while (v < axis.max && v != prev);
return ticks;
};
axis.tickFormatter = function (v, axis) {
var d = dateGenerator(v, axis.options);
// first check global format
if (opts.timeformat != null) {
return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
}
// possibly use quarters if quarters are mentioned in
// any of these places
var useQuarters = (axis.options.tickSize &&
axis.options.tickSize[1] == "quarter") ||
(axis.options.minTickSize &&
axis.options.minTickSize[1] == "quarter");
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
var span = axis.max - axis.min;
var suffix = (opts.twelveHourClock) ? " %p" : "";
var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
var fmt;
if (t < timeUnitSize.minute) {
fmt = hourCode + ":%M:%S" + suffix;
} else if (t < timeUnitSize.day) {
if (span < 2 * timeUnitSize.day) {
fmt = hourCode + ":%M" + suffix;
} else {
fmt = "%b %d " + hourCode + ":%M" + suffix;
}
} else if (t < timeUnitSize.month) {
fmt = "%b %d";
} else if ((useQuarters && t < timeUnitSize.quarter) ||
(!useQuarters && t < timeUnitSize.year)) {
if (span < timeUnitSize.year) {
fmt = "%b";
} else {
fmt = "%b %Y";
}
} else if (useQuarters && t < timeUnitSize.year) {
if (span < timeUnitSize.year) {
fmt = "Q%q";
} else {
fmt = "Q%q %Y";
}
} else {
fmt = "%Y";
}
var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
return rt;
};
}
});
});
}
$.plot.plugins.push({
init: init,
options: options,
name: 'time',
version: '1.0'
});
// Time-axis support used to be in Flot core, which exposed the
// formatDate function on the plot object. Various plugins depend
// on the function, so we need to re-expose it here.
$.plot.formatDate = formatDate;
$.plot.dateGenerator = dateGenerator;
})(jQuery);

View file

@ -1,488 +0,0 @@
/*
* jquery.flot.tooltip
*
* description: easy-to-use tooltips for Flot charts
* version: 0.8.4
* authors: Krzysztof Urbas @krzysu [myviews.pl],Evan Steinkerchner @Roundaround
* website: https://github.com/krzysu/flot.tooltip
*
* build on 2014-08-06
* released under MIT License, 2012
*/
(function ($) {
// plugin options, default values
var defaultOptions = {
tooltip: false,
tooltipOpts: {
id: "flotTip",
content: "%s | X: %x | Y: %y",
// allowed templates are:
// %s -> series label,
// %lx -> x axis label (requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels),
// %ly -> y axis label (requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels),
// %x -> X value,
// %y -> Y value,
// %x.2 -> precision of X value,
// %p -> percent
xDateFormat: null,
yDateFormat: null,
monthNames: null,
dayNames: null,
shifts: {
x: 10,
y: 20
},
defaultTheme: true,
lines: false,
// callbacks
onHover: function (flotItem, $tooltipEl) {},
$compat: false
}
};
// object
var FlotTooltip = function (plot) {
// variables
this.tipPosition = {x: 0, y: 0};
this.init(plot);
};
// main plugin function
FlotTooltip.prototype.init = function (plot) {
var that = this;
// detect other flot plugins
var plotPluginsLength = $.plot.plugins.length;
this.plotPlugins = [];
if (plotPluginsLength) {
for (var p = 0; p < plotPluginsLength; p++) {
this.plotPlugins.push($.plot.plugins[p].name);
}
}
plot.hooks.bindEvents.push(function (plot, eventHolder) {
// get plot options
that.plotOptions = plot.getOptions();
// if not enabled return
if (that.plotOptions.tooltip === false || typeof that.plotOptions.tooltip === 'undefined') return;
// shortcut to access tooltip options
that.tooltipOptions = that.plotOptions.tooltipOpts;
if (that.tooltipOptions.$compat) {
that.wfunc = 'width';
that.hfunc = 'height';
} else {
that.wfunc = 'innerWidth';
that.hfunc = 'innerHeight';
}
// create tooltip DOM element
var $tip = that.getDomElement();
// bind event
$( plot.getPlaceholder() ).bind("plothover", plothover);
$(eventHolder).bind('mousemove', mouseMove);
});
plot.hooks.shutdown.push(function (plot, eventHolder){
$(plot.getPlaceholder()).unbind("plothover", plothover);
$(eventHolder).unbind("mousemove", mouseMove);
});
function mouseMove(e){
var pos = {};
pos.x = e.pageX;
pos.y = e.pageY;
plot.setTooltipPosition(pos);
}
function plothover(event, pos, item) {
// Simple distance formula.
var lineDistance = function (p1x, p1y, p2x, p2y) {
return Math.sqrt((p2x - p1x) * (p2x - p1x) + (p2y - p1y) * (p2y - p1y));
};
// Here is some voodoo magic for determining the distance to a line form a given point {x, y}.
var dotLineLength = function (x, y, x0, y0, x1, y1, o) {
if (o && !(o =
function (x, y, x0, y0, x1, y1) {
if (typeof x0 !== 'undefined') return { x: x0, y: y };
else if (typeof y0 !== 'undefined') return { x: x, y: y0 };
var left,
tg = -1 / ((y1 - y0) / (x1 - x0));
return {
x: left = (x1 * (x * tg - y + y0) + x0 * (x * -tg + y - y1)) / (tg * (x1 - x0) + y0 - y1),
y: tg * left - tg * x + y
};
} (x, y, x0, y0, x1, y1),
o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))
) {
var l1 = lineDistance(x, y, x0, y0), l2 = lineDistance(x, y, x1, y1);
return l1 > l2 ? l2 : l1;
} else {
var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
}
};
if (item) {
plot.showTooltip(item, pos);
} else if (that.plotOptions.series.lines.show && that.tooltipOptions.lines === true) {
var maxDistance = that.plotOptions.grid.mouseActiveRadius;
var closestTrace = {
distance: maxDistance + 1
};
$.each(plot.getData(), function (i, series) {
var xBeforeIndex = 0,
xAfterIndex = -1;
// Our search here assumes our data is sorted via the x-axis.
// TODO: Improve efficiency somehow - search smaller sets of data.
for (var j = 1; j < series.data.length; j++) {
if (series.data[j - 1][0] <= pos.x && series.data[j][0] >= pos.x) {
xBeforeIndex = j - 1;
xAfterIndex = j;
}
}
if (xAfterIndex === -1) {
plot.hideTooltip();
return;
}
var pointPrev = { x: series.data[xBeforeIndex][0], y: series.data[xBeforeIndex][1] },
pointNext = { x: series.data[xAfterIndex][0], y: series.data[xAfterIndex][1] };
var distToLine = dotLineLength(series.xaxis.p2c(pos.x), series.yaxis.p2c(pos.y), series.xaxis.p2c(pointPrev.x),
series.yaxis.p2c(pointPrev.y), series.xaxis.p2c(pointNext.x), series.yaxis.p2c(pointNext.y), false);
if (distToLine < closestTrace.distance) {
var closestIndex = lineDistance(pointPrev.x, pointPrev.y, pos.x, pos.y) <
lineDistance(pos.x, pos.y, pointNext.x, pointNext.y) ? xBeforeIndex : xAfterIndex;
var pointSize = series.datapoints.pointsize;
// Calculate the point on the line vertically closest to our cursor.
var pointOnLine = [
pos.x,
pointPrev.y + ((pointNext.y - pointPrev.y) * ((pos.x - pointPrev.x) / (pointNext.x - pointPrev.x)))
];
var item = {
datapoint: pointOnLine,
dataIndex: closestIndex,
series: series,
seriesIndex: i
};
closestTrace = {
distance: distToLine,
item: item
};
}
});
if (closestTrace.distance < maxDistance + 1)
plot.showTooltip(closestTrace.item, pos);
else
plot.hideTooltip();
} else {
plot.hideTooltip();
}
}
// Quick little function for setting the tooltip position.
plot.setTooltipPosition = function (pos) {
var $tip = that.getDomElement();
var totalTipWidth = $tip.outerWidth() + that.tooltipOptions.shifts.x;
var totalTipHeight = $tip.outerHeight() + that.tooltipOptions.shifts.y;
if ((pos.x - $(window).scrollLeft()) > ($(window)[that.wfunc]() - totalTipWidth)) {
pos.x -= totalTipWidth;
}
if ((pos.y - $(window).scrollTop()) > ($(window)[that.hfunc]() - totalTipHeight)) {
pos.y -= totalTipHeight;
}
that.tipPosition.x = pos.x;
that.tipPosition.y = pos.y;
};
// Quick little function for showing the tooltip.
plot.showTooltip = function (target, position) {
var $tip = that.getDomElement();
// convert tooltip content template to real tipText
var tipText = that.stringFormat(that.tooltipOptions.content, target);
$tip.html(tipText);
plot.setTooltipPosition({ x: position.pageX, y: position.pageY });
$tip.css({
left: that.tipPosition.x + that.tooltipOptions.shifts.x,
top: that.tipPosition.y + that.tooltipOptions.shifts.y
}).show();
// run callback
if (typeof that.tooltipOptions.onHover === 'function') {
that.tooltipOptions.onHover(target, $tip);
}
};
// Quick little function for hiding the tooltip.
plot.hideTooltip = function () {
that.getDomElement().hide().html('');
};
};
/**
* get or create tooltip DOM element
* @return jQuery object
*/
FlotTooltip.prototype.getDomElement = function () {
var $tip = $('#' + this.tooltipOptions.id);
if( $tip.length === 0 ){
$tip = $('<div />').attr('id', this.tooltipOptions.id);
$tip.appendTo('body').hide().css({position: 'absolute'});
if(this.tooltipOptions.defaultTheme) {
$tip.css({
'background': '#fff',
'z-index': '1040',
'padding': '0.4em 0.6em',
'border-radius': '0.5em',
'font-size': '0.8em',
'border': '1px solid #111',
'display': 'none',
'white-space': 'nowrap'
});
}
}
return $tip;
};
/**
* core function, create tooltip content
* @param {string} content - template with tooltip content
* @param {object} item - Flot item
* @return {string} real tooltip content for current item
*/
FlotTooltip.prototype.stringFormat = function (content, item) {
var percentPattern = /%p\.{0,1}(\d{0,})/;
var seriesPattern = /%s/;
var xLabelPattern = /%lx/; // requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels, will be ignored if plugin isn't loaded
var yLabelPattern = /%ly/; // requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels, will be ignored if plugin isn't loaded
var xPattern = /%x\.{0,1}(\d{0,})/;
var yPattern = /%y\.{0,1}(\d{0,})/;
var xPatternWithoutPrecision = "%x";
var yPatternWithoutPrecision = "%y";
var customTextPattern = "%ct";
var x, y, customText, p;
// for threshold plugin we need to read data from different place
if (typeof item.series.threshold !== "undefined") {
x = item.datapoint[0];
y = item.datapoint[1];
customText = item.datapoint[2];
} else if (typeof item.series.lines !== "undefined" && item.series.lines.steps) {
x = item.series.datapoints.points[item.dataIndex * 2];
y = item.series.datapoints.points[item.dataIndex * 2 + 1];
// TODO: where to find custom text in this variant?
customText = "";
} else {
x = item.series.data[item.dataIndex][0];
y = item.series.data[item.dataIndex][1];
customText = item.series.data[item.dataIndex][2];
}
// I think this is only in case of threshold plugin
if (item.series.label === null && item.series.originSeries) {
item.series.label = item.series.originSeries.label;
}
// if it is a function callback get the content string
if (typeof(content) === 'function') {
content = content(item.series.label, x, y, item);
}
// percent match for pie charts and stacked percent
if (typeof (item.series.percent) !== 'undefined') {
p = item.series.percent;
} else if (typeof (item.series.percents) !== 'undefined') {
p = item.series.percents[item.dataIndex];
}
if (typeof p === 'number') {
content = this.adjustValPrecision(percentPattern, content, p);
}
// series match
if (typeof(item.series.label) !== 'undefined') {
content = content.replace(seriesPattern, item.series.label);
} else {
//remove %s if label is undefined
content = content.replace(seriesPattern, "");
}
// x axis label match
if (this.hasAxisLabel('xaxis', item)) {
content = content.replace(xLabelPattern, item.series.xaxis.options.axisLabel);
} else {
//remove %lx if axis label is undefined or axislabels plugin not present
content = content.replace(xLabelPattern, "");
}
// y axis label match
if (this.hasAxisLabel('yaxis', item)) {
content = content.replace(yLabelPattern, item.series.yaxis.options.axisLabel);
} else {
//remove %ly if axis label is undefined or axislabels plugin not present
content = content.replace(yLabelPattern, "");
}
// time mode axes with custom dateFormat
if (this.isTimeMode('xaxis', item) && this.isXDateFormat(item)) {
content = content.replace(xPattern, this.timestampToDate(x, this.tooltipOptions.xDateFormat, item.series.xaxis.options));
}
if (this.isTimeMode('yaxis', item) && this.isYDateFormat(item)) {
content = content.replace(yPattern, this.timestampToDate(y, this.tooltipOptions.yDateFormat, item.series.yaxis.options));
}
// set precision if defined
if (typeof x === 'number') {
content = this.adjustValPrecision(xPattern, content, x);
}
if (typeof y === 'number') {
content = this.adjustValPrecision(yPattern, content, y);
}
// change x from number to given label, if given
if (typeof item.series.xaxis.ticks !== 'undefined') {
var ticks;
if (this.hasRotatedXAxisTicks(item)) {
// xaxis.ticks will be an empty array if tickRotor is being used, but the values are available in rotatedTicks
ticks = 'rotatedTicks';
} else {
ticks = 'ticks';
}
// see https://github.com/krzysu/flot.tooltip/issues/65
var tickIndex = item.dataIndex + item.seriesIndex;
if (item.series.xaxis[ticks].length > tickIndex && !this.isTimeMode('xaxis', item)) {
var valueX = (this.isCategoriesMode('xaxis', item)) ? item.series.xaxis[ticks][tickIndex].label : item.series.xaxis[ticks][tickIndex].v;
if (valueX === x) {
content = content.replace(xPattern, item.series.xaxis[ticks][tickIndex].label);
}
}
}
// change y from number to given label, if given
if (typeof item.series.yaxis.ticks !== 'undefined') {
for (var index in item.series.yaxis.ticks) {
if (item.series.yaxis.ticks.hasOwnProperty(index)) {
var valueY = (this.isCategoriesMode('yaxis', item)) ? item.series.yaxis.ticks[index].label : item.series.yaxis.ticks[index].v;
if (valueY === y) {
content = content.replace(yPattern, item.series.yaxis.ticks[index].label);
}
}
}
}
// if no value customization, use tickFormatter by default
if (typeof item.series.xaxis.tickFormatter !== 'undefined') {
//escape dollar
content = content.replace(xPatternWithoutPrecision, item.series.xaxis.tickFormatter(x, item.series.xaxis).replace(/\$/g, '$$'));
}
if (typeof item.series.yaxis.tickFormatter !== 'undefined') {
//escape dollar
content = content.replace(yPatternWithoutPrecision, item.series.yaxis.tickFormatter(y, item.series.yaxis).replace(/\$/g, '$$'));
}
if (customText)
content = content.replace(customTextPattern, customText);
return content;
};
// helpers just for readability
FlotTooltip.prototype.isTimeMode = function (axisName, item) {
return (typeof item.series[axisName].options.mode !== 'undefined' && item.series[axisName].options.mode === 'time');
};
FlotTooltip.prototype.isXDateFormat = function (item) {
return (typeof this.tooltipOptions.xDateFormat !== 'undefined' && this.tooltipOptions.xDateFormat !== null);
};
FlotTooltip.prototype.isYDateFormat = function (item) {
return (typeof this.tooltipOptions.yDateFormat !== 'undefined' && this.tooltipOptions.yDateFormat !== null);
};
FlotTooltip.prototype.isCategoriesMode = function (axisName, item) {
return (typeof item.series[axisName].options.mode !== 'undefined' && item.series[axisName].options.mode === 'categories');
};
//
FlotTooltip.prototype.timestampToDate = function (tmst, dateFormat, options) {
var theDate = $.plot.dateGenerator(tmst, options);
return $.plot.formatDate(theDate, dateFormat, this.tooltipOptions.monthNames, this.tooltipOptions.dayNames);
};
//
FlotTooltip.prototype.adjustValPrecision = function (pattern, content, value) {
var precision;
var matchResult = content.match(pattern);
if( matchResult !== null ) {
if(RegExp.$1 !== '') {
precision = RegExp.$1;
value = value.toFixed(precision);
// only replace content if precision exists, in other case use thickformater
content = content.replace(pattern, value);
}
}
return content;
};
// other plugins detection below
// check if flot-axislabels plugin (https://github.com/markrcote/flot-axislabels) is used and that an axis label is given
FlotTooltip.prototype.hasAxisLabel = function (axisName, item) {
return ($.inArray(this.plotPlugins, 'axisLabels') !== -1 && typeof item.series[axisName].options.axisLabel !== 'undefined' && item.series[axisName].options.axisLabel.length > 0);
};
// check whether flot-tickRotor, a plugin which allows rotation of X-axis ticks, is being used
FlotTooltip.prototype.hasRotatedXAxisTicks = function (item) {
return ($.inArray(this.plotPlugins, 'tickRotor') !== -1 && typeof item.series.xaxis.rotatedTicks !== 'undefined');
};
//
var init = function (plot) {
new FlotTooltip(plot);
};
// define Flot plugin
$.plot.plugins.push({
init: init,
options: defaultOptions,
name: 'tooltip',
version: '0.8.4'
});
})(jQuery);