")
- .attr({
- id: id,
- role: "tooltip"
- })
- .addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content " +
- ( this.options.tooltipClass || "" ));
- $("
")
- .addClass("ui-tooltip-content")
- .appendTo(tooltip);
- tooltip.appendTo(this.document[0].body);
- this.tooltips[ id ] = element;
- return tooltip;
- },
-
- _find: function (target) {
- var id = target.data("ui-tooltip-id");
- return id ? $("#" + id) : $();
- },
-
- _removeTooltip: function (tooltip) {
- tooltip.remove();
- delete this.tooltips[ tooltip.attr("id") ];
- },
-
- _destroy: function () {
- var that = this;
-
- // close open tooltips
- $.each(this.tooltips, function (id, element) {
- // Delegate to close method to handle common cleanup
- var event = $.Event("blur");
- event.target = event.currentTarget = element[0];
- that.close(event, true);
-
- // Remove immediately; destroying an open tooltip doesn't use the
- // hide animation
- $("#" + id).remove();
-
- // Restore the title
- if (element.data("ui-tooltip-title")) {
- element.attr("title", element.data("ui-tooltip-title"));
- element.removeData("ui-tooltip-title");
- }
- });
- }
- });
-
-}(jQuery) );
diff --git a/src/main/webapp/static/script/jquery.cookie.js b/src/main/webapp/static/script/jquery.cookie.js
deleted file mode 100644
index 6412847..0000000
--- a/src/main/webapp/static/script/jquery.cookie.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/*!
- * jQuery Cookie Plugin v1.4.0
- * https://github.com/carhartl/jquery-cookie
- *
- * Copyright 2013 Klaus Hartl
- * Released under the MIT license
- */
-(function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as anonymous module.
- define(['jquery'], factory);
- } else {
- // Browser globals.
- factory(jQuery);
- }
-}(function ($) {
-
- var pluses = /\+/g;
-
- function encode(s) {
- return config.raw ? s : encodeURIComponent(s);
- }
-
- function decode(s) {
- return config.raw ? s : decodeURIComponent(s);
- }
-
- function stringifyCookieValue(value) {
- return encode(config.json ? JSON.stringify(value) : String(value));
- }
-
- function parseCookieValue(s) {
- if (s.indexOf('"') === 0) {
- // This is a quoted cookie as according to RFC2068, unescape...
- s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
- }
-
- try {
- // Replace server-side written pluses with spaces.
- // If we can't decode the cookie, ignore it, it's unusable.
- // If we can't parse the cookie, ignore it, it's unusable.
- s = decodeURIComponent(s.replace(pluses, ' '));
- return config.json ? JSON.parse(s) : s;
- } catch(e) {}
- }
-
- function read(s, converter) {
- var value = config.raw ? s : parseCookieValue(s);
- return $.isFunction(converter) ? converter(value) : value;
- }
-
- var config = $.cookie = function (key, value, options) {
-
- // Write
-
- if (value !== undefined && !$.isFunction(value)) {
- options = $.extend({}, config.defaults, options);
-
- if (typeof options.expires === 'number') {
- var days = options.expires, t = options.expires = new Date();
- t.setTime(+t + days * 864e+5);
- }
-
- return (document.cookie = [
- encode(key), '=', stringifyCookieValue(value),
- options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
- options.path ? '; path=' + options.path : '',
- options.domain ? '; domain=' + options.domain : '',
- options.secure ? '; secure' : ''
- ].join(''));
- }
-
- // Read
-
- var result = key ? undefined : {};
-
- // To prevent the for loop in the first place assign an empty array
- // in case there are no cookies at all. Also prevents odd result when
- // calling $.cookie().
- var cookies = document.cookie ? document.cookie.split('; ') : [];
-
- for (var i = 0, l = cookies.length; i < l; i++) {
- var parts = cookies[i].split('=');
- var name = decode(parts.shift());
- var cookie = parts.join('=');
-
- if (key && key === name) {
- // If second argument (value) is a function it's a converter...
- result = read(cookie, value);
- break;
- }
-
- // Prevent storing a cookie that we couldn't decode.
- if (!key && (cookie = read(cookie)) !== undefined) {
- result[name] = cookie;
- }
- }
-
- return result;
- };
-
- config.defaults = {};
-
- $.removeCookie = function (key, options) {
- if ($.cookie(key) === undefined) {
- return false;
- }
-
- // Must not alter options, thus extending a fresh object...
- $.cookie(key, '', $.extend({}, options, { expires: -1 }));
- return !$.cookie(key);
- };
-
-}));
diff --git a/src/main/webapp/static/script/jquery.flot.categories.js b/src/main/webapp/static/script/jquery.flot.categories.js
deleted file mode 100644
index 6e6e8ba..0000000
--- a/src/main/webapp/static/script/jquery.flot.categories.js
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Flot plugin for plotting textual data or categories.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-Consider a dataset like [["February", 34], ["March", 20], ...]. This plugin
-allows you to plot such a dataset directly.
-
-To enable it, you must specify mode: "categories" on the axis with the textual
-labels, e.g.
-
- $.plot("#placeholder", data, { xaxis: { mode: "categories" } });
-
-By default, the labels are ordered as they are met in the data series. If you
-need a different ordering, you can specify "categories" on the axis options
-and list the categories there:
-
- xaxis: {
- mode: "categories",
- categories: ["February", "March", "April"]
- }
-
-If you need to customize the distances between the categories, you can specify
-"categories" as an object mapping labels to values
-
- xaxis: {
- mode: "categories",
- categories: { "February": 1, "March": 3, "April": 4 }
- }
-
-If you don't specify all categories, the remaining categories will be numbered
-from the max value plus 1 (with a spacing of 1 between each).
-
-Internally, the plugin works by transforming the input data through an auto-
-generated mapping where the first category becomes 0, the second 1, etc.
-Hence, a point like ["February", 34] becomes [0, 34] internally in Flot (this
-is visible in hover and click events that return numbers rather than the
-category labels). The plugin also overrides the tick generator to spit out the
-categories as ticks instead of the values.
-
-If you need to map a value back to its label, the mapping is always accessible
-as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories.
-
-*/
-
-(function ($) {
- var options = {
- xaxis: {
- categories: null
- },
- yaxis: {
- categories: null
- }
- };
-
- function processRawData(plot, series, data, datapoints) {
- // if categories are enabled, we need to disable
- // auto-transformation to numbers so the strings are intact
- // for later processing
-
- var xCategories = series.xaxis.options.mode == "categories",
- yCategories = series.yaxis.options.mode == "categories";
-
- if (!(xCategories || yCategories))
- return;
-
- var format = datapoints.format;
-
- if (!format) {
- // FIXME: auto-detection should really not be defined here
- var s = series;
- format = [];
- format.push({ x: true, number: true, required: true });
- format.push({ y: true, number: true, required: true });
-
- if (s.bars.show || (s.lines.show && s.lines.fill)) {
- var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
- format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
- if (s.bars.horizontal) {
- delete format[format.length - 1].y;
- format[format.length - 1].x = true;
- }
- }
-
- datapoints.format = format;
- }
-
- for (var m = 0; m < format.length; ++m) {
- if (format[m].x && xCategories)
- format[m].number = false;
-
- if (format[m].y && yCategories)
- format[m].number = false;
- }
- }
-
- function getNextIndex(categories) {
- var index = -1;
-
- for (var v in categories)
- if (categories[v] > index)
- index = categories[v];
-
- return index + 1;
- }
-
- function categoriesTickGenerator(axis) {
- var res = [];
- for (var label in axis.categories) {
- var v = axis.categories[label];
- if (v >= axis.min && v <= axis.max)
- res.push([v, label]);
- }
-
- res.sort(function (a, b) { return a[0] - b[0]; });
-
- return res;
- }
-
- function setupCategoriesForAxis(series, axis, datapoints) {
- if (series[axis].options.mode != "categories")
- return;
-
- if (!series[axis].categories) {
- // parse options
- var c = {}, o = series[axis].options.categories || {};
- if ($.isArray(o)) {
- for (var i = 0; i < o.length; ++i)
- c[o[i]] = i;
- }
- else {
- for (var v in o)
- c[v] = o[v];
- }
-
- series[axis].categories = c;
- }
-
- // fix ticks
- if (!series[axis].options.ticks)
- series[axis].options.ticks = categoriesTickGenerator;
-
- transformPointsOnAxis(datapoints, axis, series[axis].categories);
- }
-
- function transformPointsOnAxis(datapoints, axis, categories) {
- // go through the points, transforming them
- var points = datapoints.points,
- ps = datapoints.pointsize,
- format = datapoints.format,
- formatColumn = axis.charAt(0),
- index = getNextIndex(categories);
-
- for (var i = 0; i < points.length; i += ps) {
- if (points[i] == null)
- continue;
-
- for (var m = 0; m < ps; ++m) {
- var val = points[i + m];
-
- if (val == null || !format[m][formatColumn])
- continue;
-
- if (!(val in categories)) {
- categories[val] = index;
- ++index;
- }
-
- points[i + m] = categories[val];
- }
- }
- }
-
- function processDatapoints(plot, series, datapoints) {
- setupCategoriesForAxis(series, "xaxis", datapoints);
- setupCategoriesForAxis(series, "yaxis", datapoints);
- }
-
- function init(plot) {
- plot.hooks.processRawData.push(processRawData);
- plot.hooks.processDatapoints.push(processDatapoints);
- }
-
- $.plot.plugins.push({
- init: init,
- options: options,
- name: 'categories',
- version: '1.0'
- });
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.fillbetween.js b/src/main/webapp/static/script/jquery.flot.fillbetween.js
deleted file mode 100644
index 2854d2d..0000000
--- a/src/main/webapp/static/script/jquery.flot.fillbetween.js
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Flot plugin for computing bottoms for filled line and bar charts.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-The case: you've got two series that you want to fill the area between. In Flot
-terms, you need to use one as the fill bottom of the other. You can specify the
-bottom of each data point as the third coordinate manually, or you can use this
-plugin to compute it for you.
-
-In order to name the other series, you need to give it an id, like this:
-
- var dataset = [
- { data: [ ... ], id: "foo" } , // use default bottom
- { data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
- ];
-
- $.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
-
-As a convenience, if the id given is a number that doesn't appear as an id in
-the series, it is interpreted as the index in the array instead (so fillBetween:
-0 can also mean the first series).
-
-Internally, the plugin modifies the datapoints in each series. For line series,
-extra data points might be inserted through interpolation. Note that at points
-where the bottom line is not defined (due to a null point or start/end of line),
-the current line will show a gap too. The algorithm comes from the
-jquery.flot.stack.js plugin, possibly some code could be shared.
-
-*/
-
-(function ( $ ) {
-
- var options = {
- series: {
- fillBetween: null // or number
- }
- };
-
- function init( plot ) {
-
- function findBottomSeries( s, allseries ) {
-
- var i;
-
- for ( i = 0; i < allseries.length; ++i ) {
- if ( allseries[ i ].id === s.fillBetween ) {
- return allseries[ i ];
- }
- }
-
- if ( typeof s.fillBetween === "number" ) {
- if ( s.fillBetween < 0 || s.fillBetween >= allseries.length ) {
- return null;
- }
- return allseries[ s.fillBetween ];
- }
-
- return null;
- }
-
- function computeFillBottoms( plot, s, datapoints ) {
-
- if ( s.fillBetween == null ) {
- return;
- }
-
- var other = findBottomSeries( s, plot.getData() );
-
- if ( !other ) {
- return;
- }
-
- var ps = datapoints.pointsize,
- points = datapoints.points,
- otherps = other.datapoints.pointsize,
- otherpoints = other.datapoints.points,
- newpoints = [],
- px, py, intery, qx, qy, bottom,
- withlines = s.lines.show,
- withbottom = ps > 2 && datapoints.format[2].y,
- withsteps = withlines && s.lines.steps,
- fromgap = true,
- i = 0,
- j = 0,
- l, m;
-
- while ( true ) {
-
- if ( i >= points.length ) {
- break;
- }
-
- l = newpoints.length;
-
- if ( points[ i ] == null ) {
-
- // copy gaps
-
- for ( m = 0; m < ps; ++m ) {
- newpoints.push( points[ i + m ] );
- }
-
- i += ps;
-
- } else if ( j >= otherpoints.length ) {
-
- // for lines, we can't use the rest of the points
-
- if ( !withlines ) {
- for ( m = 0; m < ps; ++m ) {
- newpoints.push( points[ i + m ] );
- }
- }
-
- i += ps;
-
- } else if ( otherpoints[ j ] == null ) {
-
- // oops, got a gap
-
- for ( m = 0; m < ps; ++m ) {
- newpoints.push( null );
- }
-
- fromgap = true;
- j += otherps;
-
- } else {
-
- // cases where we actually got two points
-
- px = points[ i ];
- py = points[ i + 1 ];
- qx = otherpoints[ j ];
- qy = otherpoints[ j + 1 ];
- bottom = 0;
-
- if ( px === qx ) {
-
- for ( m = 0; m < ps; ++m ) {
- newpoints.push( points[ i + m ] );
- }
-
- //newpoints[ l + 1 ] += qy;
- bottom = qy;
-
- i += ps;
- j += otherps;
-
- } else if ( px > qx ) {
-
- // we got past point below, might need to
- // insert interpolated extra point
-
- if ( withlines && i > 0 && points[ i - ps ] != null ) {
- intery = py + ( points[ i - ps + 1 ] - py ) * ( qx - px ) / ( points[ i - ps ] - px );
- newpoints.push( qx );
- newpoints.push( intery );
- for ( m = 2; m < ps; ++m ) {
- newpoints.push( points[ i + m ] );
- }
- bottom = qy;
- }
-
- j += otherps;
-
- } else { // px < qx
-
- // if we come from a gap, we just skip this point
-
- if ( fromgap && withlines ) {
- i += ps;
- continue;
- }
-
- for ( m = 0; m < ps; ++m ) {
- newpoints.push( points[ i + m ] );
- }
-
- // we might be able to interpolate a point below,
- // this can give us a better y
-
- if ( withlines && j > 0 && otherpoints[ j - otherps ] != null ) {
- bottom = qy + ( otherpoints[ j - otherps + 1 ] - qy ) * ( px - qx ) / ( otherpoints[ j - otherps ] - qx );
- }
-
- //newpoints[l + 1] += bottom;
-
- i += ps;
- }
-
- fromgap = false;
-
- if ( l !== newpoints.length && withbottom ) {
- newpoints[ l + 2 ] = bottom;
- }
- }
-
- // maintain the line steps invariant
-
- if ( withsteps && l !== newpoints.length && l > 0 &&
- newpoints[ l ] !== null &&
- newpoints[ l ] !== newpoints[ l - ps ] &&
- newpoints[ l + 1 ] !== newpoints[ l - ps + 1 ] ) {
- for (m = 0; m < ps; ++m) {
- newpoints[ l + ps + m ] = newpoints[ l + m ];
- }
- newpoints[ l + 1 ] = newpoints[ l - ps + 1 ];
- }
- }
-
- datapoints.points = newpoints;
- }
-
- plot.hooks.processDatapoints.push( computeFillBottoms );
- }
-
- $.plot.plugins.push({
- init: init,
- options: options,
- name: "fillbetween",
- version: "1.0"
- });
-
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.js b/src/main/webapp/static/script/jquery.flot.js
deleted file mode 100644
index f2a31c5..0000000
--- a/src/main/webapp/static/script/jquery.flot.js
+++ /dev/null
@@ -1,3004 +0,0 @@
-/* Javascript plotting library for jQuery, version 0.9.0-alpha.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-*/
-
-// first an inline dependency, jquery.colorhelpers.js, we inline it here
-// for convenience
-/* Plugin for jQuery for working with colors.
- *
- * Version 1.1.
- *
- * Inspiration from jQuery color animation plugin by John Resig.
- *
- * Released under the MIT license by Ole Laursen, October 2009.
- *
- * Examples:
- *
- * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
- * var c = $.color.extract($("#mydiv"), 'background-color');
- * console.log(c.r, c.g, c.b, c.a);
- * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
- *
- * Note that .scale() and .add() return the same modified object
- * instead of making a new one.
- *
- * V. 1.1: Fix error handling so e.g. parsing an empty string does
- * produce a color rather than just crashing.
- */ (function(B) {
- B.color = {};
- B.color.make = function(F, E, C, D) {
- var G = {};
- G.r = F || 0;
- G.g = E || 0;
- G.b = C || 0;
- G.a = D != null ? D : 1;
- G.add = function(J, I) {
- for (var H = 0; H < J.length; ++H) {
- G[J.charAt(H)] += I
- }
- return G.normalize()
- };
- G.scale = function(J, I) {
- for (var H = 0; H < J.length; ++H) {
- G[J.charAt(H)] *= I
- }
- return G.normalize()
- };
- G.toString = function() {
- if (G.a >= 1) {
- return "rgb(" + [G.r, G.g, G.b].join(",") + ")"
- } else {
- return "rgba(" + [G.r, G.g, G.b, G.a].join(",") + ")"
- }
- };
- G.normalize = function() {
- function H(J, K, I) {
- return K < J ? J : (K > I ? I : K)
- }
- G.r = H(0, parseInt(G.r), 255);
- G.g = H(0, parseInt(G.g), 255);
- G.b = H(0, parseInt(G.b), 255);
- G.a = H(0, G.a, 1);
- return G
- };
- G.clone = function() {
- return B.color.make(G.r, G.b, G.g, G.a)
- };
- return G.normalize()
- };
- B.color.extract = function(D, C) {
- var E;
- do {
- E = D.css(C).toLowerCase();
- if (E != "" && E != "transparent") {
- break
- }
- D = D.parent()
- } while (!B.nodeName(D.get(0), "body"));
- if (E == "rgba(0, 0, 0, 0)") {
- E = "transparent"
- }
- return B.color.parse(E)
- };
- B.color.parse = function(F) {
- var E, C = B.color.make;
- if (E = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)) {
- return C(parseInt(E[1], 10), parseInt(E[2], 10), parseInt(E[3], 10))
- }
- if (E = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)) {
- return C(parseInt(E[1], 10), parseInt(E[2], 10), parseInt(E[3], 10), parseFloat(E[4]))
- }
- if (E = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)) {
- return C(parseFloat(E[1]) * 2.55, parseFloat(E[2]) * 2.55, parseFloat(E[3]) * 2.55)
- }
- if (E = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)) {
- return C(parseFloat(E[1]) * 2.55, parseFloat(E[2]) * 2.55, parseFloat(E[3]) * 2.55, parseFloat(E[4]))
- }
- if (E = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)) {
- return C(parseInt(E[1], 16), parseInt(E[2], 16), parseInt(E[3], 16))
- }
- if (E = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)) {
- return C(parseInt(E[1] + E[1], 16), parseInt(E[2] + E[2], 16), parseInt(E[3] + E[3], 16))
- }
- var D = B.trim(F).toLowerCase();
- if (D == "transparent") {
- return C(255, 255, 255, 0)
- } else {
- E = A[D] || [0, 0, 0];
- return C(E[0], E[1], E[2])
- }
- };
- var A = {
- aqua: [0, 255, 255],
- azure: [240, 255, 255],
- beige: [245, 245, 220],
- black: [0, 0, 0],
- blue: [0, 0, 255],
- brown: [165, 42, 42],
- cyan: [0, 255, 255],
- darkblue: [0, 0, 139],
- darkcyan: [0, 139, 139],
- darkgrey: [169, 169, 169],
- darkgreen: [0, 100, 0],
- darkkhaki: [189, 183, 107],
- darkmagenta: [139, 0, 139],
- darkolivegreen: [85, 107, 47],
- darkorange: [255, 140, 0],
- darkorchid: [153, 50, 204],
- darkred: [139, 0, 0],
- darksalmon: [233, 150, 122],
- darkviolet: [148, 0, 211],
- fuchsia: [255, 0, 255],
- gold: [255, 215, 0],
- green: [0, 128, 0],
- indigo: [75, 0, 130],
- khaki: [240, 230, 140],
- lightblue: [173, 216, 230],
- lightcyan: [224, 255, 255],
- lightgreen: [144, 238, 144],
- lightgrey: [211, 211, 211],
- lightpink: [255, 182, 193],
- lightyellow: [255, 255, 224],
- lime: [0, 255, 0],
- magenta: [255, 0, 255],
- maroon: [128, 0, 0],
- navy: [0, 0, 128],
- olive: [128, 128, 0],
- orange: [255, 165, 0],
- pink: [255, 192, 203],
- purple: [128, 0, 128],
- violet: [128, 0, 128],
- red: [255, 0, 0],
- silver: [192, 192, 192],
- white: [255, 255, 255],
- yellow: [255, 255, 0]
- }
-})(jQuery);
-
-// the actual Flot code
-(function($) {
-
- // Cache the prototype hasOwnProperty for faster access
- var hasOwnProperty = Object.prototype.hasOwnProperty;
-
- ///////////////////////////////////////////////////////////////////////////
- // The Canvas object is a wrapper around an HTML5
tag.
- //
- // @constructor
- // @param {string} cls List of classes to apply to the canvas.
- // @param {element} container Element onto which to append the canvas.
- //
- // Requiring a container is a little iffy, but unfortunately canvas
- // operations don't work unless the canvas is attached to the DOM.
- function Canvas(cls, container) {
-
- var element = container.children("." + cls)[0];
-
- if (element == null) {
-
- element = document.createElement("canvas");
- element.className = cls;
-
- $(element).css({
- direction: "ltr",
- position: "absolute",
- left: 0,
- top: 0
- }).appendTo(container);
-
- // If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas
- if (!element.getContext) {
- if (window.G_vmlCanvasManager) {
- element = window.G_vmlCanvasManager.initElement(element);
- } else {
- throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");
- }
- }
- }
-
- this.element = element;
-
- var context = this.context = element.getContext("2d");
-
- // Determine the screen's ratio of physical to device-independent
- // pixels. This is the ratio between the canvas width that the browser
- // advertises and the number of pixels actually present in that space.
-
- // The iPhone 4, for example, has a device-independent width of 320px,
- // but its screen is actually 640px wide. It therefore has a pixel
- // ratio of 2, while most normal devices have a ratio of 1.
- var devicePixelRatio = window.devicePixelRatio || 1,
- backingStoreRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;
-
- this.pixelRatio = devicePixelRatio / backingStoreRatio;
-
- // Size the canvas to match the internal dimensions of its container
- this.resize(container.width(), container.height());
-
- // Collection of HTML div layers for text overlaid onto the canvas
- this.textContainer = null;
- this.text = {};
-
- // Cache of text fragments and metrics, so we can avoid expensively
- // re-calculating them when the plot is re-rendered in a loop.
- this._textCache = {};
- }
-
- // Resizes the canvas to the given dimensions.
- //
- // @param {number} width New width of the canvas, in pixels.
- // @param {number} width New height of the canvas, in pixels.
- Canvas.prototype.resize = function(width, height) {
-
- if (width <= 0 || height <= 0) {
- throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height);
- }
-
- var element = this.element,
- context = this.context,
- pixelRatio = this.pixelRatio;
-
- // Resize the canvas, increasing its density based on the display's
- // pixel ratio; basically giving it more pixels without increasing the
- // size of its element, to take advantage of the fact that retina
- // displays have that many more pixels in the same advertised space.
-
- // Resizing should reset the state (excanvas seems to be buggy though)
- if (this.width != width) {
- element.width = width * pixelRatio;
- element.style.width = width + "px";
- this.width = width;
- }
-
- if (this.height != height) {
- element.height = height * pixelRatio;
- element.style.height = height + "px";
- this.height = height;
- }
-
- // Save the context, so we can reset in case we get replotted. The
- // restore ensure that we're really back at the initial state, and
- // should be safe even if we haven't saved the initial state yet.
- context.restore();
- context.save();
-
- // Scale the coordinate space to match the display density; so even though we
- // may have twice as many pixels, we still want lines and other drawing to
- // appear at the same size; the extra pixels will just make them crisper.
- context.scale(pixelRatio, pixelRatio);
- };
-
- // Clears the entire canvas area, not including any overlaid HTML text
- Canvas.prototype.clear = function() {
- this.context.clearRect(0, 0, this.width, this.height);
- };
-
- // Finishes rendering the canvas, including managing the text overlay.
- Canvas.prototype.render = function() {
-
- var cache = this._textCache;
-
- // For each text layer, add elements marked as active that haven't
- // already been rendered, and remove those that are no longer active.
- for (var layerKey in cache) {
- if (hasOwnProperty.call(cache, layerKey)) {
-
- var layer = this.getTextLayer(layerKey),
- layerCache = cache[layerKey];
-
- layer.hide();
-
- for (var styleKey in layerCache) {
- if (hasOwnProperty.call(layerCache, styleKey)) {
- var styleCache = layerCache[styleKey];
- for (var key in styleCache) {
- if (hasOwnProperty.call(styleCache, key)) {
- var info = styleCache[key];
- if (info.active) {
- if (!info.rendered) {
- layer.append(info.element);
- info.rendered = true;
- }
- } else {
- delete styleCache[key];
- if (info.rendered) {
- info.element.detach();
- }
- }
- }
- }
- }
- }
-
- layer.show();
- }
- }
- };
-
- // Creates (if necessary) and returns the text overlay container.
- //
- // @param {string} classes String of space-separated CSS classes used to
- // uniquely identify the text layer.
- // @return {object} The jQuery-wrapped text-layer div.
- Canvas.prototype.getTextLayer = function(classes) {
-
- var layer = this.text[classes];
-
- // Create the text layer if it doesn't exist
- if (layer == null) {
-
- // Create the text layer container, if it doesn't exist
- if (this.textContainer == null) {
- this.textContainer = $("
").css({
- position: "absolute",
- top: 0,
- left: 0,
- bottom: 0,
- right: 0,
- 'font-size': "smaller",
- color: "#545454"
- }).insertAfter(this.element);
- }
-
- layer = this.text[classes] = $("
").addClass(classes).css({
- position: "absolute",
- top: 0,
- left: 0,
- bottom: 0,
- right: 0
- }).appendTo(this.textContainer);
- }
-
- return layer;
- };
-
- // Creates (if necessary) and returns a text info object.
- //
- // The object looks like this:
- //
- // {
- // width: Width of the text's wrapper div.
- // height: Height of the text's wrapper div.
- // active: Flag indicating whether the text should be visible.
- // rendered: Flag indicating whether the text is currently visible.
- // element: The jQuery-wrapped HTML div containing the text.
- // }
- //
- // Canvas maintains a cache of recently-used text info objects; getTextInfo
- // either returns the cached element or creates a new entry.
- //
- // @param {string} layer A string of space-separated CSS classes uniquely
- // identifying the layer containing this text.
- // @param {string} text Text string to retrieve info for.
- // @param {(string|object)=} font Either a string of space-separated CSS
- // classes or a font-spec object, defining the text's font and style.
- // @param {number=} angle Angle at which to rotate the text, in degrees.
- // Angle is currently unused, it will be implemented in the future.
- // @return {object} a text info object.
- Canvas.prototype.getTextInfo = function(layer, text, font, angle) {
-
- var textStyle, layerCache, styleCache, info;
-
- // Cast the value to a string, in case we were given a number or such
- text = "" + text;
-
- // If the font is a font-spec object, generate a CSS font definition
- if (typeof font === "object") {
- textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family;
- } else {
- textStyle = font;
- }
-
- // Retrieve (or create) the cache for the text's layer and styles
- layerCache = this._textCache[layer];
-
- if (layerCache == null) {
- layerCache = this._textCache[layer] = {};
- }
-
- styleCache = layerCache[textStyle];
-
- if (styleCache == null) {
- styleCache = layerCache[textStyle] = {};
- }
-
- info = styleCache[text];
-
- // If we can't find a matching element in our cache, create a new one
- if (info == null) {
-
- var element = $("
").html(text).css({
- position: "absolute",
- top: -9999
- }).appendTo(this.getTextLayer(layer));
-
- if (typeof font === "object") {
- element.css({
- font: textStyle,
- color: font.color
- });
- } else if (typeof font === "string") {
- element.addClass(font);
- }
-
- info = styleCache[text] = {
- active: false,
- rendered: false,
- element: element,
- width: element.outerWidth(true),
- height: element.outerHeight(true)
- };
-
- element.detach();
- }
-
- return info;
- };
-
- // Adds a text string to the canvas text overlay.
- //
- // The text isn't drawn immediately; it is marked as rendering, which will
- // result in its addition to the canvas on the next render pass.
- //
- // @param {string} layer A string of space-separated CSS classes uniquely
- // identifying the layer containing this text.
- // @param {number} x X coordinate at which to draw the text.
- // @param {number} y Y coordinate at which to draw the text.
- // @param {string} text Text string to draw.
- // @param {(string|object)=} font Either a string of space-separated CSS
- // classes or a font-spec object, defining the text's font and style.
- // @param {number=} angle Angle at which to rotate the text, in degrees.
- // Angle is currently unused, it will be implemented in the future.
- // @param {string=} halign Horizontal alignment of the text; either "left",
- // "center" or "right".
- // @param {string=} valign Vertical alignment of the text; either "top",
- // "middle" or "bottom".
- Canvas.prototype.addText = function(layer, x, y, text, font, angle, halign, valign) {
-
- var info = this.getTextInfo(layer, text, font, angle);
-
- // Mark the div for inclusion in the next render pass
- info.active = true;
-
- // Tweak the div's position to match the text's alignment
- if (halign == "center") {
- x -= info.width / 2;
- } else if (halign == "right") {
- x -= info.width;
- }
-
- if (valign == "middle") {
- y -= info.height / 2;
- } else if (valign == "bottom") {
- y -= info.height;
- }
-
- // Move the element to its final position within the container
- info.element.css({
- top: Math.round(y),
- left: Math.round(x)
- });
- };
-
- // Removes one or more text strings from the canvas text overlay.
- //
- // If no parameters are given, all text within the layer is removed.
- // The text is not actually removed; it is simply marked as inactive, which
- // will result in its removal on the next render pass.
- //
- // @param {string} layer A string of space-separated CSS classes uniquely
- // identifying the layer containing this text.
- // @param {string} text Text string to remove.
- // @param {(string|object)=} font Either a string of space-separated CSS
- // classes or a font-spec object, defining the text's font and style.
- // @param {number=} angle Angle at which the text is rotated, in degrees.
- // Angle is currently unused, it will be implemented in the future.
- Canvas.prototype.removeText = function(layer, text, font, angle) {
- if (text == null) {
- var layerCache = this._textCache[layer];
- if (layerCache != null) {
- for (var styleKey in layerCache) {
- if (hasOwnProperty.call(layerCache, styleKey)) {
- var styleCache = layerCache[styleKey]
- for (var key in styleCache) {
- if (hasOwnProperty.call(styleCache, key)) {
- styleCache[key].active = false;
- }
- }
- }
- }
- }
- } else {
- this.getTextInfo(layer, text, font, angle).active = false;
- }
- };
-
- ///////////////////////////////////////////////////////////////////////////
- // The top-level container for the entire plot.
- function Plot(placeholder, data_, options_, plugins) {
- // data is on the form:
- // [ series1, series2 ... ]
- // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
- // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
- var series = [],
- options = {
- // the color theme used for graphs
- colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
- legend: {
- show: true,
- noColumns: 1,
- // number of colums in legend table
- labelFormatter: null,
- // fn: string -> string
- labelBoxBorderColor: "#ccc",
- // border color for the little label boxes
- container: null,
- // container (as jQuery object) to put legend in, null means default on top of graph
- position: "ne",
- // position of default legend container within plot
- margin: 5,
- // distance from grid edge to default legend container within plot
- backgroundColor: null,
- // null means auto-detect
- backgroundOpacity: 0.85,
- // set to 0 to avoid background
- sorted: null // default to no legend sorting
- },
- xaxis: {
- show: null,
- // null = auto-detect, true = always, false = never
- position: "bottom",
- // or "top"
- mode: null,
- // null or "time"
- font: null,
- // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
- color: null,
- // base color, labels, ticks
- tickColor: null,
- // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
- transform: null,
- // null or f: number -> number to transform axis
- inverseTransform: null,
- // if transform is set, this should be the inverse function
- min: null,
- // min. value to show, null means set automatically
- max: null,
- // max. value to show, null means set automatically
- autoscaleMargin: null,
- // margin in % to add if auto-setting min/max
- ticks: null,
- // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
- tickFormatter: null,
- // fn: number -> string
- labelWidth: null,
- // size of tick labels in pixels
- labelHeight: null,
- reserveSpace: null,
- // whether to reserve space even if axis isn't shown
- tickLength: null,
- // size in pixels of ticks, or "full" for whole line
- alignTicksWithAxis: null,
- // axis number or null for no sync
- tickDecimals: null,
- // no. of decimals, null means auto
- tickSize: null,
- // number or [number, "unit"]
- minTickSize: null // number or [number, "unit"]
- },
- yaxis: {
- autoscaleMargin: 0.02,
- position: "left" // or "right"
- },
- xaxes: [],
- yaxes: [],
- series: {
- points: {
- show: false,
- radius: 3,
- lineWidth: 2,
- // in pixels
- fill: true,
- fillColor: "#ffffff",
- strokeColor: null,
- symbol: "circle" // or callback
- },
- lines: {
- // we don't put in show: false so we can see
- // whether lines were actively disabled
- lineWidth: 2,
- // in pixels
- fill: false,
- fillColor: null,
- steps: false
- // Omit 'zero', so we can later default its value to
- // match that of the 'fill' option.
- },
- bars: {
- show: false,
- lineWidth: 2,
- // in pixels
- barWidth: 1,
- // in units of the x axis
- fill: true,
- fillColor: null,
- align: "left",
- // "left", "right", or "center"
- horizontal: false,
- zero: true
- },
- shadowSize: 3,
- highlightColor: null
- },
- grid: {
- show: true,
- aboveData: false,
- color: "#545454",
- // primary color used for outline and labels
- backgroundColor: null,
- // null for transparent, else color
- borderColor: null,
- // set if different from the grid color
- tickColor: null,
- // color for the ticks, e.g. "rgba(0,0,0,0.15)"
- margin: 0,
- // distance from the canvas edge to the grid
- labelMargin: 5,
- // in pixels
- axisMargin: 8,
- // in pixels
- borderWidth: 2,
- // in pixels
- minBorderMargin: null,
- // in pixels, null means taken from points radius
- markings: null,
- // array of ranges or fn: axes -> array of ranges
- markingsColor: "#f4f4f4",
- markingsLineWidth: 2,
- // interactive stuff
- clickable: false,
- hoverable: false,
- autoHighlight: true,
- // highlight in case mouse is near
- mouseActiveRadius: 10 // how far the mouse can be away to activate an item
- },
- interaction: {
- redrawOverlayInterval: 1000 / 60 // time between updates, -1 means in same flow
- },
- hooks: {}
- },
- surface = null,
- // the canvas for the plot itself
- overlay = null,
- // canvas for interactive stuff on top of plot
- eventHolder = null,
- // jQuery object that events should be bound to
- ctx = null,
- octx = null,
- xaxes = [],
- yaxes = [],
- plotOffset = {
- left: 0,
- right: 0,
- top: 0,
- bottom: 0
- },
- plotWidth = 0,
- plotHeight = 0,
- hooks = {
- processOptions: [],
- processRawData: [],
- processDatapoints: [],
- processOffset: [],
- drawBackground: [],
- drawSeries: [],
- draw: [],
- bindEvents: [],
- drawOverlay: [],
- shutdown: []
- },
- plot = this;
-
- // public functions
- plot.setData = setData;
- plot.setupGrid = setupGrid;
- plot.draw = draw;
- plot.findNearbyItem = findNearbyItem;
- plot.getPlaceholder = function() {
- return placeholder;
- };
- plot.getCanvas = function() {
- return surface.element;
- };
- plot.getPlotOffset = function() {
- return plotOffset;
- };
- plot.width = function() {
- return plotWidth;
- };
- plot.height = function() {
- return plotHeight;
- };
- plot.offset = function() {
- var o = eventHolder.offset();
- o.left += plotOffset.left;
- o.top += plotOffset.top;
- return o;
- };
- plot.getData = function() {
- return series;
- };
- plot.getAxes = function() {
- var res = {},
- i;
- $.each(xaxes.concat(yaxes), function(_, axis) {
- if (axis) res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
- });
- return res;
- };
- plot.getXAxes = function() {
- return xaxes;
- };
- plot.getYAxes = function() {
- return yaxes;
- };
- plot.c2p = canvasToAxisCoords;
- plot.p2c = axisToCanvasCoords;
- plot.getOptions = function() {
- return options;
- };
- plot.highlight = highlight;
- plot.unhighlight = unhighlight;
- plot.triggerRedrawOverlay = triggerRedrawOverlay;
- plot.pointOffset = function(point) {
- return {
- left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left, 10),
- top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10)
- };
- };
- plot.shutdown = shutdown;
- plot.resize = function() {
- var width = placeholder.width(),
- height = placeholder.height();
- surface.resize(width, height);
- overlay.resize(width, height);
- };
-
- // public attributes
- plot.hooks = hooks;
-
- // initialize
- initPlugins(plot);
- parseOptions(options_);
- setupCanvases();
- setData(data_);
- setupGrid();
- draw();
- bindEvents();
-
-
- function executeHooks(hook, args) {
- args = [plot].concat(args);
- for (var i = 0; i < hook.length; ++i)
- hook[i].apply(this, args);
- }
-
- function initPlugins() {
-
- // References to key classes, allowing plugins to modify them
- var classes = {
- Canvas: Canvas
- };
-
- for (var i = 0; i < plugins.length; ++i) {
- var p = plugins[i];
- p.init(plot, classes);
- if (p.options) $.extend(true, options, p.options);
- }
- }
-
- function parseOptions(opts) {
-
- $.extend(true, options, opts);
-
- if (options.xaxis.color == null) options.xaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
- if (options.yaxis.color == null) options.yaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
-
- if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility
- options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color;
- if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility
- options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color;
-
- if (options.grid.borderColor == null) options.grid.borderColor = options.grid.color;
- if (options.grid.tickColor == null) options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
-
- // Fill in defaults for axis options, including any unspecified
- // font-spec fields, if a font-spec was provided.
-
- // If no x/y axis options were provided, create one of each anyway,
- // since the rest of the code assumes that they exist.
- var i, axisOptions, axisCount, fontDefaults = {
- style: placeholder.css("font-style"),
- size: Math.round(0.8 * (+placeholder.css("font-size").replace("px", "") || 13)),
- variant: placeholder.css("font-variant"),
- weight: placeholder.css("font-weight"),
- family: placeholder.css("font-family")
- };
-
- fontDefaults.lineHeight = fontDefaults.size * 1.15;
-
- axisCount = options.xaxes.length || 1;
- for (i = 0; i < axisCount; ++i) {
-
- axisOptions = options.xaxes[i];
- if (axisOptions && !axisOptions.tickColor) {
- axisOptions.tickColor = axisOptions.color;
- }
-
- axisOptions = $.extend(true, {}, options.xaxis, axisOptions);
- options.xaxes[i] = axisOptions;
-
- if (axisOptions.font) {
- axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
- if (!axisOptions.font.color) {
- axisOptions.font.color = axisOptions.color;
- }
- }
- }
-
- axisCount = options.yaxes.length || 1;
- for (i = 0; i < axisCount; ++i) {
-
- axisOptions = options.yaxes[i];
- if (axisOptions && !axisOptions.tickColor) {
- axisOptions.tickColor = axisOptions.color;
- }
-
- axisOptions = $.extend(true, {}, options.yaxis, axisOptions);
- options.yaxes[i] = axisOptions;
-
- if (axisOptions.font) {
- axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
- if (!axisOptions.font.color) {
- axisOptions.font.color = axisOptions.color;
- }
- }
- }
-
- // backwards compatibility, to be removed in future
- if (options.xaxis.noTicks && options.xaxis.ticks == null) options.xaxis.ticks = options.xaxis.noTicks;
- if (options.yaxis.noTicks && options.yaxis.ticks == null) options.yaxis.ticks = options.yaxis.noTicks;
- if (options.x2axis) {
- options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
- options.xaxes[1].position = "top";
- }
- if (options.y2axis) {
- options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
- options.yaxes[1].position = "right";
- }
- if (options.grid.coloredAreas) options.grid.markings = options.grid.coloredAreas;
- if (options.grid.coloredAreasColor) options.grid.markingsColor = options.grid.coloredAreasColor;
- if (options.lines) $.extend(true, options.series.lines, options.lines);
- if (options.points) $.extend(true, options.series.points, options.points);
- if (options.bars) $.extend(true, options.series.bars, options.bars);
- if (options.shadowSize != null) options.series.shadowSize = options.shadowSize;
- if (options.highlightColor != null) options.series.highlightColor = options.highlightColor;
-
- // save options on axes for future reference
- for (i = 0; i < options.xaxes.length; ++i)
- getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
- for (i = 0; i < options.yaxes.length; ++i)
- getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
-
- // add hooks from options
- for (var n in hooks)
- if (options.hooks[n] && options.hooks[n].length) hooks[n] = hooks[n].concat(options.hooks[n]);
-
- executeHooks(hooks.processOptions, [options]);
- }
-
- function setData(d) {
- series = parseData(d);
- fillInSeriesOptions();
- processData();
- }
-
- function parseData(d) {
- var res = [];
- for (var i = 0; i < d.length; ++i) {
- var s = $.extend(true, {}, options.series);
-
- if (d[i].data != null) {
- s.data = d[i].data; // move the data instead of deep-copy
- delete d[i].data;
-
- $.extend(true, s, d[i]);
-
- d[i].data = s.data;
- } else s.data = d[i];
- res.push(s);
- }
-
- return res;
- }
-
- function axisNumber(obj, coord) {
- var a = obj[coord + "axis"];
- if (typeof a == "object") // if we got a real axis, extract number
- a = a.n;
- if (typeof a != "number") a = 1; // default to first axis
- return a;
- }
-
- function allAxes() {
- // return flat array without annoying null entries
- return $.grep(xaxes.concat(yaxes), function(a) {
- return a;
- });
- }
-
- function canvasToAxisCoords(pos) {
- // return an object with x/y corresponding to all used axes
- var res = {},
- i, axis;
- for (i = 0; i < xaxes.length; ++i) {
- axis = xaxes[i];
- if (axis && axis.used) res["x" + axis.n] = axis.c2p(pos.left);
- }
-
- for (i = 0; i < yaxes.length; ++i) {
- axis = yaxes[i];
- if (axis && axis.used) res["y" + axis.n] = axis.c2p(pos.top);
- }
-
- if (res.x1 !== undefined) res.x = res.x1;
- if (res.y1 !== undefined) res.y = res.y1;
-
- return res;
- }
-
- function axisToCanvasCoords(pos) {
- // get canvas coords from the first pair of x/y found in pos
- var res = {},
- i, axis, key;
-
- for (i = 0; i < xaxes.length; ++i) {
- axis = xaxes[i];
- if (axis && axis.used) {
- key = "x" + axis.n;
- if (pos[key] == null && axis.n == 1) key = "x";
-
- if (pos[key] != null) {
- res.left = axis.p2c(pos[key]);
- break;
- }
- }
- }
-
- for (i = 0; i < yaxes.length; ++i) {
- axis = yaxes[i];
- if (axis && axis.used) {
- key = "y" + axis.n;
- if (pos[key] == null && axis.n == 1) key = "y";
-
- if (pos[key] != null) {
- res.top = axis.p2c(pos[key]);
- break;
- }
- }
- }
-
- return res;
- }
-
- function getOrCreateAxis(axes, number) {
- if (!axes[number - 1]) axes[number - 1] = {
- n: number,
- // save the number for future reference
- direction: axes == xaxes ? "x" : "y",
- options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
- };
-
- return axes[number - 1];
- }
-
- function fillInSeriesOptions() {
-
- var neededColors = series.length,
- maxIndex = -1,
- i;
-
- // Subtract the number of series that already have fixed colors or
- // color indexes from the number that we still need to generate.
- for (i = 0; i < series.length; ++i) {
- var sc = series[i].color;
- if (sc != null) {
- neededColors--;
- if (typeof sc == "number" && sc > maxIndex) {
- maxIndex = sc;
- }
- }
- }
-
- // If any of the series have fixed color indexes, then we need to
- // generate at least as many colors as the highest index.
- if (neededColors <= maxIndex) {
- neededColors = maxIndex + 1;
- }
-
- // Generate all the colors, using first the option colors and then
- // variations on those colors once they're exhausted.
- var c, colors = [],
- colorPool = options.colors,
- colorPoolSize = colorPool.length,
- variation = 0;
-
- for (i = 0; i < neededColors; i++) {
-
- c = $.color.parse(colorPool[i % colorPoolSize] || "#666");
-
- // Each time we exhaust the colors in the pool we adjust
- // a scaling factor used to produce more variations on
- // those colors. The factor alternates negative/positive
- // to produce lighter/darker colors.
-
- // Reset the variation after every few cycles, or else
- // it will end up producing only white or black colors.
- if (i % colorPoolSize == 0 && i) {
- if (variation >= 0) {
- if (variation < 0.5) {
- variation = -variation - 0.2;
- } else variation = 0;
- } else variation = -variation;
- }
-
- colors[i] = c.scale('rgb', 1 + variation);
- }
-
- // Finalize the series options, filling in their colors
- var colori = 0,
- s;
- for (i = 0; i < series.length; ++i) {
- s = series[i];
-
- // assign colors
- if (s.color == null) {
- s.color = colors[colori].toString();
- ++colori;
- } else if (typeof s.color == "number") s.color = colors[s.color].toString();
-
- // turn on lines automatically in case nothing is set
- if (s.lines.show == null) {
- var v, show = true;
- for (v in s)
- if (s[v] && s[v].show) {
- show = false;
- break;
- }
- if (show) s.lines.show = true;
- }
-
- // If nothing was provided for lines.zero, default it to match
- // lines.fill, since areas by default should extend to zero.
- if (s.lines.zero == null) {
- s.lines.zero = !! s.lines.fill;
- }
-
- // setup axes
- s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
- s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
- }
- }
-
- function processData() {
- var topSentry = Number.POSITIVE_INFINITY,
- bottomSentry = Number.NEGATIVE_INFINITY,
- fakeInfinity = Number.MAX_VALUE,
- i, j, k, m, length, s, points, ps, x, y, axis, val, f, p, data, format;
-
- function updateAxis(axis, min, max) {
- if (min < axis.datamin && min != -fakeInfinity) axis.datamin = min;
- if (max > axis.datamax && max != fakeInfinity) axis.datamax = max;
- }
-
- $.each(allAxes(), function(_, axis) {
- // init axis
- axis.datamin = topSentry;
- axis.datamax = bottomSentry;
- axis.used = false;
- });
-
- for (i = 0; i < series.length; ++i) {
- s = series[i];
- s.datapoints = {
- points: []
- };
-
- executeHooks(hooks.processRawData, [s, s.data, s.datapoints]);
- }
-
- // first pass: clean and copy data
- for (i = 0; i < series.length; ++i) {
- s = series[i];
-
- data = s.data;
- format = s.datapoints.format;
-
- if (!format) {
- format = [];
- // find out how to copy
- format.push({
- x: true,
- number: true,
- required: true
- });
- format.push({
- y: true,
- number: true,
- required: true
- });
-
- if (s.bars.show || (s.lines.show && s.lines.fill)) {
- var autoscale = !! ((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
- format.push({
- y: true,
- number: true,
- required: false,
- defaultValue: 0,
- autoscale: autoscale
- });
- if (s.bars.horizontal) {
- delete format[format.length - 1].y;
- format[format.length - 1].x = true;
- }
- }
-
- s.datapoints.format = format;
- }
-
- if (s.datapoints.pointsize != null) continue; // already filled in
- s.datapoints.pointsize = format.length;
-
- ps = s.datapoints.pointsize;
- points = s.datapoints.points;
-
- var insertSteps = s.lines.show && s.lines.steps;
- s.xaxis.used = s.yaxis.used = true;
-
- for (j = k = 0; j < data.length; ++j, k += ps) {
- p = data[j];
-
- var nullify = p == null;
- if (!nullify) {
- for (m = 0; m < ps; ++m) {
- val = p[m];
- f = format[m];
-
- if (f) {
- if (f.number && val != null) {
- val = +val; // convert to number
- if (isNaN(val)) val = null;
- else if (val == Infinity) val = fakeInfinity;
- else if (val == -Infinity) val = -fakeInfinity;
- }
-
- if (val == null) {
- if (f.required) nullify = true;
-
- if (f.defaultValue != null) val = f.defaultValue;
- }
- }
-
- points[k + m] = val;
- }
- }
-
- if (nullify) {
- for (m = 0; m < ps; ++m) {
- val = points[k + m];
- if (val != null) {
- f = format[m];
- // extract min/max info
- if (f.x) updateAxis(s.xaxis, val, val);
- if (f.y) updateAxis(s.yaxis, val, val);
- }
- points[k + m] = null;
- }
- } else {
- // a little bit of line specific stuff that
- // perhaps shouldn't be here, but lacking
- // better means...
- if (insertSteps && k > 0 && points[k - ps] != null && points[k - ps] != points[k] && points[k - ps + 1] != points[k + 1]) {
- // copy the point to make room for a middle point
- for (m = 0; m < ps; ++m)
- points[k + ps + m] = points[k + m];
-
- // middle point has same y
- points[k + 1] = points[k - ps + 1];
-
- // we've added a point, better reflect that
- k += ps;
- }
- }
- }
- }
-
- // give the hooks a chance to run
- for (i = 0; i < series.length; ++i) {
- s = series[i];
-
- executeHooks(hooks.processDatapoints, [s, s.datapoints]);
- }
-
- // second pass: find datamax/datamin for auto-scaling
- for (i = 0; i < series.length; ++i) {
- s = series[i];
- points = s.datapoints.points, ps = s.datapoints.pointsize;
- format = s.datapoints.format;
-
- var xmin = topSentry,
- ymin = topSentry,
- xmax = bottomSentry,
- ymax = bottomSentry;
-
- for (j = 0; j < points.length; j += ps) {
- if (points[j] == null) continue;
-
- for (m = 0; m < ps; ++m) {
- val = points[j + m];
- f = format[m];
- if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity) continue;
-
- if (f.x) {
- if (val < xmin) xmin = val;
- if (val > xmax) xmax = val;
- }
- if (f.y) {
- if (val < ymin) ymin = val;
- if (val > ymax) ymax = val;
- }
- }
- }
-
- if (s.bars.show) {
- // make sure we got room for the bar on the dancing floor
- var delta;
-
- switch (s.bars.align) {
- case "left":
- delta = 0;
- break;
- case "right":
- delta = -s.bars.barWidth;
- break;
- case "center":
- delta = -s.bars.barWidth / 2;
- break;
- default:
- throw new Error("Invalid bar alignment: " + s.bars.align);
- }
-
- if (s.bars.horizontal) {
- ymin += delta;
- ymax += delta + s.bars.barWidth;
- } else {
- xmin += delta;
- xmax += delta + s.bars.barWidth;
- }
- }
-
- updateAxis(s.xaxis, xmin, xmax);
- updateAxis(s.yaxis, ymin, ymax);
- }
-
- $.each(allAxes(), function(_, axis) {
- if (axis.datamin == topSentry) axis.datamin = null;
- if (axis.datamax == bottomSentry) axis.datamax = null;
- });
- }
-
- function setupCanvases() {
-
- // Make sure the placeholder is clear of everything except canvases
- // from a previous plot in this container that we'll try to re-use.
- placeholder.css("padding", 0) // padding messes up the positioning
- .children(":not(.flot-base,.flot-overlay)").remove();
-
- if (placeholder.css("position") == 'static') placeholder.css("position", "relative"); // for positioning labels and overlay
- surface = new Canvas("flot-base", placeholder);
- overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features
- ctx = surface.context;
- octx = overlay.context;
-
- // define which element we're listening for events on
- eventHolder = $(overlay.element).unbind();
-
- // If we're re-using a plot object, shut down the old one
- var existing = placeholder.data("plot");
-
- if (existing) {
- existing.shutdown();
- overlay.clear();
- }
-
- // save in case we get replotted
- placeholder.data("plot", plot);
- }
-
- function bindEvents() {
- // bind events
- if (options.grid.hoverable) {
- eventHolder.mousemove(onMouseMove);
-
- // Use bind, rather than .mouseleave, because we officially
- // still support jQuery 1.2.6, which doesn't define a shortcut
- // for mouseenter or mouseleave. This was a bug/oversight that
- // was fixed somewhere around 1.3.x. We can return to using
- // .mouseleave when we drop support for 1.2.6.
- eventHolder.bind("mouseleave", onMouseLeave);
- }
-
- if (options.grid.clickable) eventHolder.click(onClick);
-
- executeHooks(hooks.bindEvents, [eventHolder]);
- }
-
- function shutdown() {
- if (redrawTimeout) clearTimeout(redrawTimeout);
-
- eventHolder.unbind("mousemove", onMouseMove);
- eventHolder.unbind("mouseleave", onMouseLeave);
- eventHolder.unbind("click", onClick);
-
- executeHooks(hooks.shutdown, [eventHolder]);
- }
-
- function setTransformationHelpers(axis) {
- // set helper functions on the axis, assumes plot area
- // has been computed already
- function identity(x) {
- return x;
- }
-
- var s, m, t = axis.options.transform || identity,
- it = axis.options.inverseTransform;
-
- // precompute how much the axis is scaling a point
- // in canvas space
- if (axis.direction == "x") {
- s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
- m = Math.min(t(axis.max), t(axis.min));
- } else {
- s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
- s = -s;
- m = Math.max(t(axis.max), t(axis.min));
- }
-
- // data point to canvas coordinate
- if (t == identity) // slight optimization
- axis.p2c = function(p) {
- return (p - m) * s;
- };
- else axis.p2c = function(p) {
- return (t(p) - m) * s;
- };
- // canvas coordinate to data point
- if (!it) axis.c2p = function(c) {
- return m + c / s;
- };
- else axis.c2p = function(c) {
- return it(m + c / s);
- };
- }
-
- function measureTickLabels(axis) {
-
- var opts = axis.options,
- ticks = axis.ticks || [],
- axisw = opts.labelWidth || 0,
- axish = opts.labelHeight || 0,
- legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
- layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
- font = opts.font || "flot-tick-label tickLabel";
-
- for (var i = 0; i < ticks.length; ++i) {
-
- var t = ticks[i];
-
- if (!t.label) continue;
-
- var info = surface.getTextInfo(layer, t.label, font);
-
- if (opts.labelWidth == null) axisw = Math.max(axisw, info.width);
- if (opts.labelHeight == null) axish = Math.max(axish, info.height);
- }
-
- axis.labelWidth = Math.ceil(axisw);
- axis.labelHeight = Math.ceil(axish);
- }
-
- function allocateAxisBoxFirstPhase(axis) {
- // find the bounding box of the axis by looking at label
- // widths/heights and ticks, make room by diminishing the
- // plotOffset; this first phase only looks at one
- // dimension per axis, the other dimension depends on the
- // other axes so will have to wait
- var lw = axis.labelWidth,
- lh = axis.labelHeight,
- pos = axis.options.position,
- tickLength = axis.options.tickLength,
- axisMargin = options.grid.axisMargin,
- padding = options.grid.labelMargin,
- all = axis.direction == "x" ? xaxes : yaxes,
- index, innermost;
-
- // determine axis margin
- var samePosition = $.grep(all, function(a) {
- return a && a.options.position == pos && a.reserveSpace;
- });
- if ($.inArray(axis, samePosition) == samePosition.length - 1) axisMargin = 0; // outermost
-
- // determine tick length - if we're innermost, we can use "full"
- if (tickLength == null) {
- var sameDirection = $.grep(all, function(a) {
- return a && a.reserveSpace;
- });
-
- innermost = $.inArray(axis, sameDirection) == 0;
- if (innermost) tickLength = "full";
- else tickLength = 5;
- }
-
- if (!isNaN(+tickLength)) padding += +tickLength;
-
- // compute box
- if (axis.direction == "x") {
- lh += padding;
-
- if (pos == "bottom") {
- plotOffset.bottom += lh + axisMargin;
- axis.box = {
- top: surface.height - plotOffset.bottom,
- height: lh
- };
- } else {
- axis.box = {
- top: plotOffset.top + axisMargin,
- height: lh
- };
- plotOffset.top += lh + axisMargin;
- }
- } else {
- lw += padding;
-
- if (pos == "left") {
- axis.box = {
- left: plotOffset.left + axisMargin,
- width: lw
- };
- plotOffset.left += lw + axisMargin;
- } else {
- plotOffset.right += lw + axisMargin;
- axis.box = {
- left: surface.width - plotOffset.right,
- width: lw
- };
- }
- }
-
- // save for future reference
- axis.position = pos;
- axis.tickLength = tickLength;
- axis.box.padding = padding;
- axis.innermost = innermost;
- }
-
- function allocateAxisBoxSecondPhase(axis) {
- // now that all axis boxes have been placed in one
- // dimension, we can set the remaining dimension coordinates
- if (axis.direction == "x") {
- axis.box.left = plotOffset.left - axis.labelWidth / 2;
- axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth;
- } else {
- axis.box.top = plotOffset.top - axis.labelHeight / 2;
- axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight;
- }
- }
-
- function adjustLayoutForThingsStickingOut() {
- // possibly adjust plot offset to ensure everything stays
- // inside the canvas and isn't clipped off
- var minMargin = options.grid.minBorderMargin,
- margins = {
- x: 0,
- y: 0
- },
- i, axis;
-
- // check stuff from the plot (FIXME: this should just read
- // a value from the series, otherwise it's impossible to
- // customize)
- if (minMargin == null) {
- minMargin = 0;
- for (i = 0; i < series.length; ++i)
- minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth / 2));
- }
-
- margins.x = margins.y = Math.ceil(minMargin);
-
- // check axis labels, note we don't check the actual
- // labels but instead use the overall width/height to not
- // jump as much around with replots
- $.each(allAxes(), function(_, axis) {
- var dir = axis.direction;
- if (axis.reserveSpace) margins[dir] = Math.ceil(Math.max(margins[dir], (dir == "x" ? axis.labelWidth : axis.labelHeight) / 2));
- });
-
- plotOffset.left = Math.max(margins.x, plotOffset.left);
- plotOffset.right = Math.max(margins.x, plotOffset.right);
- plotOffset.top = Math.max(margins.y, plotOffset.top);
- plotOffset.bottom = Math.max(margins.y, plotOffset.bottom);
- }
-
- function setupGrid() {
- var i, axes = allAxes(),
- showGrid = options.grid.show;
-
- // Initialize the plot's offset from the edge of the canvas
- for (var a in plotOffset) {
- var margin = options.grid.margin || 0;
- plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0;
- }
-
- executeHooks(hooks.processOffset, [plotOffset]);
-
- // If the grid is visible, add its border width to the offset
- for (var a in plotOffset) {
- if (typeof(options.grid.borderWidth) == "object") {
- plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0;
- } else {
- plotOffset[a] += showGrid ? options.grid.borderWidth : 0;
- }
- }
-
- // init axes
- $.each(axes, function(_, axis) {
- axis.show = axis.options.show;
- if (axis.show == null) axis.show = axis.used; // by default an axis is visible if it's got data
- axis.reserveSpace = axis.show || axis.options.reserveSpace;
-
- setRange(axis);
- });
-
- if (showGrid) {
-
- var allocatedAxes = $.grep(axes, function(axis) {
- return axis.reserveSpace;
- });
-
- $.each(allocatedAxes, function(_, axis) {
- // make the ticks
- setupTickGeneration(axis);
- setTicks(axis);
- snapRangeToTicks(axis, axis.ticks);
- // find labelWidth/Height for axis
- measureTickLabels(axis);
- });
-
- // with all dimensions calculated, we can compute the
- // axis bounding boxes, start from the outside
- // (reverse order)
- for (i = allocatedAxes.length - 1; i >= 0; --i)
- allocateAxisBoxFirstPhase(allocatedAxes[i]);
-
- // make sure we've got enough space for things that
- // might stick out
- adjustLayoutForThingsStickingOut();
-
- $.each(allocatedAxes, function(_, axis) {
- allocateAxisBoxSecondPhase(axis);
- });
- }
-
- plotWidth = surface.width - plotOffset.left - plotOffset.right;
- plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
-
- // now we got the proper plot dimensions, we can compute the scaling
- $.each(axes, function(_, axis) {
- setTransformationHelpers(axis);
- });
-
- if (showGrid) {
- drawAxisLabels();
- }
-
- insertLegend();
- }
-
- function setRange(axis) {
- var opts = axis.options,
- min = +(opts.min != null ? opts.min : axis.datamin),
- max = +(opts.max != null ? opts.max : axis.datamax),
- delta = max - min;
-
- if (delta == 0.0) {
- // degenerate case
- var widen = max == 0 ? 1 : 0.01;
-
- if (opts.min == null) min -= widen;
- // always widen max if we couldn't widen min to ensure we
- // don't fall into min == max which doesn't work
- if (opts.max == null || opts.min != null) max += widen;
- } else {
- // consider autoscaling
- var margin = opts.autoscaleMargin;
- if (margin != null) {
- if (opts.min == null) {
- min -= delta * margin;
- // make sure we don't go below zero if all values
- // are positive
- if (min < 0 && axis.datamin != null && axis.datamin >= 0) min = 0;
- }
- if (opts.max == null) {
- max += delta * margin;
- if (max > 0 && axis.datamax != null && axis.datamax <= 0) max = 0;
- }
- }
- }
- axis.min = min;
- axis.max = max;
- }
-
- function setupTickGeneration(axis) {
- var opts = axis.options;
-
- // estimate number of ticks
- var noTicks;
- if (typeof opts.ticks == "number" && opts.ticks > 0) noTicks = opts.ticks;
- else
- // heuristic based on the model a*sqrt(x) fitted to
- // some data points that seemed reasonable
- noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? surface.width : surface.height);
-
- var delta = (axis.max - axis.min) / noTicks,
- dec = -Math.floor(Math.log(delta) / Math.LN10),
- maxDec = opts.tickDecimals;
-
- if (maxDec != null && dec > maxDec) {
- dec = maxDec;
- }
-
- var magn = Math.pow(10, -dec),
- norm = delta / magn,
- // norm is between 1.0 and 10.0
- size;
-
- if (norm < 1.5) {
- size = 1;
- } else if (norm < 3) {
- size = 2;
- // special case for 2.5, requires an extra decimal
- if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
- size = 2.5;
- ++dec;
- }
- } else if (norm < 7.5) {
- size = 5;
- } else {
- size = 10;
- }
-
- size *= magn;
-
- if (opts.minTickSize != null && size < opts.minTickSize) {
- size = opts.minTickSize;
- }
-
- axis.delta = delta;
- axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
- axis.tickSize = opts.tickSize || size;
-
- // Time mode was moved to a plug-in in 0.8, but since so many people use this
- // we'll add an especially friendly make sure they remembered to include it.
- if (opts.mode == "time" && !axis.tickGenerator) {
- throw new Error("Time mode requires the flot.time plugin.");
- }
-
- // Flot supports base-10 axes; any other mode else is handled by a plug-in,
- // like flot.time.js.
- if (!axis.tickGenerator) {
-
- axis.tickGenerator = function(axis) {
-
- var ticks = [],
- start = floorInBase(axis.min, axis.tickSize),
- i = 0,
- v = Number.NaN,
- prev;
-
- do {
- prev = v;
- v = start + i * axis.tickSize;
- ticks.push(v);++i;
- } while (v < axis.max && v != prev);
- return ticks;
- };
-
- axis.tickFormatter = function(value, axis) {
-
- var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1;
- var formatted = "" + Math.round(value * factor) / factor;
-
- // If tickDecimals was specified, ensure that we have exactly that
- // much precision; otherwise default to the value's own precision.
- if (axis.tickDecimals != null) {
- var decimal = formatted.indexOf(".");
- var precision = decimal == -1 ? 0 : formatted.length - decimal - 1;
- if (precision < axis.tickDecimals) {
- return (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);
- }
- }
-
- return formatted;
- };
- }
-
- if ($.isFunction(opts.tickFormatter)) axis.tickFormatter = function(v, axis) {
- return "" + opts.tickFormatter(v, axis);
- };
-
- if (opts.alignTicksWithAxis != null) {
- var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
- if (otherAxis && otherAxis.used && otherAxis != axis) {
- // consider snapping min/max to outermost nice ticks
- var niceTicks = axis.tickGenerator(axis);
- if (niceTicks.length > 0) {
- if (opts.min == null) axis.min = Math.min(axis.min, niceTicks[0]);
- if (opts.max == null && niceTicks.length > 1) axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
- }
-
- axis.tickGenerator = function(axis) {
- // copy ticks, scaled to this axis
- var ticks = [],
- v, i;
- for (i = 0; i < otherAxis.ticks.length; ++i) {
- v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
- v = axis.min + v * (axis.max - axis.min);
- ticks.push(v);
- }
- return ticks;
- };
-
- // we might need an extra decimal since forced
- // ticks don't necessarily fit naturally
- if (!axis.mode && opts.tickDecimals == null) {
- var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
- ts = axis.tickGenerator(axis);
-
- // only proceed if the tick interval rounded
- // with an extra decimal doesn't give us a
- // zero at end
- if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec)))) axis.tickDecimals = extraDec;
- }
- }
- }
- }
-
- function setTicks(axis) {
- var oticks = axis.options.ticks,
- ticks = [];
- if (oticks == null || (typeof oticks == "number" && oticks > 0)) ticks = axis.tickGenerator(axis);
- else if (oticks) {
- if ($.isFunction(oticks))
- // generate the ticks
- ticks = oticks(axis);
- else ticks = oticks;
- }
-
- // clean up/labelify the supplied ticks, copy them over
- var i, v;
- axis.ticks = [];
- for (i = 0; i < ticks.length; ++i) {
- var label = null;
- var t = ticks[i];
- if (typeof t == "object") {
- v = +t[0];
- if (t.length > 1) label = t[1];
- } else v = +t;
- if (label == null) label = axis.tickFormatter(v, axis);
- if (!isNaN(v)) axis.ticks.push({
- v: v,
- label: label
- });
- }
- }
-
- function snapRangeToTicks(axis, ticks) {
- if (axis.options.autoscaleMargin && ticks.length > 0) {
- // snap to ticks
- if (axis.options.min == null) axis.min = Math.min(axis.min, ticks[0].v);
- if (axis.options.max == null && ticks.length > 1) axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
- }
- }
-
- function draw() {
-
- surface.clear();
-
- executeHooks(hooks.drawBackground, [ctx]);
-
- var grid = options.grid;
-
- // draw background, if any
- if (grid.show && grid.backgroundColor) drawBackground();
-
- if (grid.show && !grid.aboveData) {
- drawGrid();
- }
-
- for (var i = 0; i < series.length; ++i) {
- executeHooks(hooks.drawSeries, [ctx, series[i]]);
- drawSeries(series[i]);
- }
-
- executeHooks(hooks.draw, [ctx]);
-
- if (grid.show && grid.aboveData) {
- drawGrid();
- }
-
- surface.render();
- }
-
- function extractRange(ranges, coord) {
- var axis, from, to, key, axes = allAxes();
-
- for (var i = 0; i < axes.length; ++i) {
- axis = axes[i];
- 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" ? xaxes[0] : yaxes[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 drawBackground() {
- ctx.save();
- ctx.translate(plotOffset.left, plotOffset.top);
-
- ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
- ctx.fillRect(0, 0, plotWidth, plotHeight);
- ctx.restore();
- }
-
- function drawGrid() {
- var i, axes, bw, bc;
-
- ctx.save();
- ctx.translate(plotOffset.left, plotOffset.top);
-
- // draw markings
- var markings = options.grid.markings;
- if (markings) {
- if ($.isFunction(markings)) {
- axes = plot.getAxes();
- // xmin etc. is backwards compatibility, to be
- // removed in the future
- axes.xmin = axes.xaxis.min;
- axes.xmax = axes.xaxis.max;
- axes.ymin = axes.yaxis.min;
- axes.ymax = axes.yaxis.max;
-
- markings = markings(axes);
- }
-
- for (i = 0; i < markings.length; ++i) {
- var m = markings[i],
- xrange = extractRange(m, "x"),
- yrange = extractRange(m, "y");
-
- // fill in missing
- if (xrange.from == null) xrange.from = xrange.axis.min;
- if (xrange.to == null) xrange.to = xrange.axis.max;
- if (yrange.from == null) yrange.from = yrange.axis.min;
- if (yrange.to == null) yrange.to = yrange.axis.max;
-
- // clip
- if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) continue;
-
- xrange.from = Math.max(xrange.from, xrange.axis.min);
- xrange.to = Math.min(xrange.to, xrange.axis.max);
- yrange.from = Math.max(yrange.from, yrange.axis.min);
- yrange.to = Math.min(yrange.to, yrange.axis.max);
-
- if (xrange.from == xrange.to && yrange.from == yrange.to) continue;
-
- // then draw
- xrange.from = xrange.axis.p2c(xrange.from);
- xrange.to = xrange.axis.p2c(xrange.to);
- yrange.from = yrange.axis.p2c(yrange.from);
- yrange.to = yrange.axis.p2c(yrange.to);
-
- if (xrange.from == xrange.to || yrange.from == yrange.to) {
- // draw line
- ctx.beginPath();
- ctx.strokeStyle = m.color || options.grid.markingsColor;
- ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
- ctx.moveTo(xrange.from, yrange.from);
- ctx.lineTo(xrange.to, yrange.to);
- ctx.stroke();
- } else {
- // fill area
- ctx.fillStyle = m.color || options.grid.markingsColor;
- ctx.fillRect(xrange.from, yrange.to, xrange.to - xrange.from, yrange.from - yrange.to);
- }
- }
- }
-
- // draw the ticks
- axes = allAxes();
- bw = options.grid.borderWidth;
-
- for (var j = 0; j < axes.length; ++j) {
- var axis = axes[j],
- box = axis.box,
- t = axis.tickLength,
- x, y, xoff, yoff;
- if (!axis.show || axis.ticks.length == 0) continue;
-
- ctx.lineWidth = 1;
-
- // find the edges
- if (axis.direction == "x") {
- x = 0;
- if (t == "full") y = (axis.position == "top" ? 0 : plotHeight);
- else y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
- } else {
- y = 0;
- if (t == "full") x = (axis.position == "left" ? 0 : plotWidth);
- else x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
- }
-
- // draw tick bar
- if (!axis.innermost) {
- ctx.strokeStyle = axis.options.color;
- ctx.beginPath();
- xoff = yoff = 0;
- if (axis.direction == "x") xoff = plotWidth + 1;
- else yoff = plotHeight + 1;
-
- if (ctx.lineWidth == 1) {
- if (axis.direction == "x") {
- y = Math.floor(y) + 0.5;
- } else {
- x = Math.floor(x) + 0.5;
- }
- }
-
- ctx.moveTo(x, y);
- ctx.lineTo(x + xoff, y + yoff);
- ctx.stroke();
- }
-
- // draw ticks
- ctx.strokeStyle = axis.options.tickColor;
-
- ctx.beginPath();
- for (i = 0; i < axis.ticks.length; ++i) {
- var v = axis.ticks[i].v;
-
- xoff = yoff = 0;
-
- if (isNaN(v) || v < axis.min || v > axis.max
- // skip those lying on the axes if we got a border
- ||
- (t == "full" && ((typeof bw == "object" && bw[axis.position] > 0) || bw > 0) && (v == axis.min || v == axis.max))) continue;
-
- if (axis.direction == "x") {
- x = axis.p2c(v);
- yoff = t == "full" ? -plotHeight : t;
-
- if (axis.position == "top") yoff = -yoff;
- } else {
- y = axis.p2c(v);
- xoff = t == "full" ? -plotWidth : t;
-
- if (axis.position == "left") xoff = -xoff;
- }
-
- if (ctx.lineWidth == 1) {
- if (axis.direction == "x") x = Math.floor(x) + 0.5;
- else y = Math.floor(y) + 0.5;
- }
-
- ctx.moveTo(x, y);
- ctx.lineTo(x + xoff, y + yoff);
- }
-
- ctx.stroke();
- }
-
-
- // draw border
- if (bw) {
- // If either borderWidth or borderColor is an object, then draw the border
- // line by line instead of as one rectangle
- bc = options.grid.borderColor;
- if (typeof bw == "object" || typeof bc == "object") {
- if (typeof bw !== "object") {
- bw = {
- top: bw,
- right: bw,
- bottom: bw,
- left: bw
- };
- }
- if (typeof bc !== "object") {
- bc = {
- top: bc,
- right: bc,
- bottom: bc,
- left: bc
- };
- }
-
- if (bw.top > 0) {
- ctx.strokeStyle = bc.top;
- ctx.lineWidth = bw.top;
- ctx.beginPath();
- ctx.moveTo(0 - bw.left, 0 - bw.top / 2);
- ctx.lineTo(plotWidth, 0 - bw.top / 2);
- ctx.stroke();
- }
-
- if (bw.right > 0) {
- ctx.strokeStyle = bc.right;
- ctx.lineWidth = bw.right;
- ctx.beginPath();
- ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top);
- ctx.lineTo(plotWidth + bw.right / 2, plotHeight);
- ctx.stroke();
- }
-
- if (bw.bottom > 0) {
- ctx.strokeStyle = bc.bottom;
- ctx.lineWidth = bw.bottom;
- ctx.beginPath();
- ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2);
- ctx.lineTo(0, plotHeight + bw.bottom / 2);
- ctx.stroke();
- }
-
- if (bw.left > 0) {
- ctx.strokeStyle = bc.left;
- ctx.lineWidth = bw.left;
- ctx.beginPath();
- ctx.moveTo(0 - bw.left / 2, plotHeight + bw.bottom);
- ctx.lineTo(0 - bw.left / 2, 0);
- ctx.stroke();
- }
- } else {
- ctx.lineWidth = bw;
- ctx.strokeStyle = options.grid.borderColor;
- ctx.strokeRect(-bw / 2, -bw / 2, plotWidth + bw, plotHeight + bw);
- }
- }
-
- ctx.restore();
- }
-
- function drawAxisLabels() {
-
- $.each(allAxes(), function(_, axis) {
- if (!axis.show || axis.ticks.length == 0) return;
-
- var box = axis.box,
- legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
- layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
- font = axis.options.font || "flot-tick-label tickLabel",
- tick, x, y, halign, valign;
-
- surface.removeText(layer);
-
- for (var i = 0; i < axis.ticks.length; ++i) {
-
- tick = axis.ticks[i];
- if (!tick.label || tick.v < axis.min || tick.v > axis.max) continue;
-
- if (axis.direction == "x") {
- halign = "center";
- x = plotOffset.left + axis.p2c(tick.v);
- if (axis.position == "bottom") {
- y = box.top + box.padding;
- } else {
- y = box.top + box.height - box.padding;
- valign = "bottom";
- }
- } else {
- valign = "middle";
- y = plotOffset.top + axis.p2c(tick.v);
- if (axis.position == "left") {
- x = box.left + box.width - box.padding;
- halign = "right";
- } else {
- x = box.left + box.padding;
- }
- }
-
- surface.addText(layer, x, y, tick.label, font, null, halign, valign);
- }
- });
- }
-
- function drawSeries(series) {
- if (series.lines.show) drawSeriesLines(series);
- if (series.bars.show) drawSeriesBars(series);
- if (series.points.show) drawSeriesPoints(series);
- }
-
- function drawSeriesLines(series) {
- function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
- var points = datapoints.points,
- ps = datapoints.pointsize,
- prevx = null,
- prevy = null;
-
- ctx.beginPath();
- for (var i = ps; i < points.length; i += ps) {
- var x1 = points[i - ps],
- y1 = points[i - ps + 1],
- x2 = points[i],
- y2 = points[i + 1];
-
- if (x1 == null || x2 == null) continue;
-
- // clip with ymin
- if (y1 <= y2 && y1 < axisy.min) {
- if (y2 < axisy.min) continue; // line segment is outside
- // compute new intersection point
- x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
- y1 = axisy.min;
- } else if (y2 <= y1 && y2 < axisy.min) {
- if (y1 < axisy.min) continue;
- x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
- y2 = axisy.min;
- }
-
- // clip with ymax
- if (y1 >= y2 && y1 > axisy.max) {
- if (y2 > axisy.max) continue;
- x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
- y1 = axisy.max;
- } else if (y2 >= y1 && y2 > axisy.max) {
- if (y1 > axisy.max) continue;
- x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
- y2 = axisy.max;
- }
-
- // clip with xmin
- if (x1 <= x2 && x1 < axisx.min) {
- if (x2 < axisx.min) continue;
- y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
- x1 = axisx.min;
- } else if (x2 <= x1 && x2 < axisx.min) {
- if (x1 < axisx.min) continue;
- y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
- x2 = axisx.min;
- }
-
- // clip with xmax
- if (x1 >= x2 && x1 > axisx.max) {
- if (x2 > axisx.max) continue;
- y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
- x1 = axisx.max;
- } else if (x2 >= x1 && x2 > axisx.max) {
- if (x1 > axisx.max) continue;
- y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
- x2 = axisx.max;
- }
-
- if (x1 != prevx || y1 != prevy) ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
-
- prevx = x2;
- prevy = y2;
- ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
- }
- ctx.stroke();
- }
-
- function plotLineArea(datapoints, axisx, axisy) {
- var points = datapoints.points,
- ps = datapoints.pointsize,
- bottom = Math.min(Math.max(0, axisy.min), axisy.max),
- i = 0,
- top, areaOpen = false,
- ypos = 1,
- segmentStart = 0,
- segmentEnd = 0;
-
- // we process each segment in two turns, first forward
- // direction to sketch out top, then once we hit the
- // end we go backwards to sketch the bottom
- while (true) {
- if (ps > 0 && i > points.length + ps) break;
-
- i += ps; // ps is negative if going backwards
- var x1 = points[i - ps],
- y1 = points[i - ps + ypos],
- x2 = points[i],
- y2 = points[i + ypos];
-
- if (areaOpen) {
- if (ps > 0 && x1 != null && x2 == null) {
- // at turning point
- segmentEnd = i;
- ps = -ps;
- ypos = 2;
- continue;
- }
-
- if (ps < 0 && i == segmentStart + ps) {
- // done with the reverse sweep
- ctx.fill();
- areaOpen = false;
- ps = -ps;
- ypos = 1;
- i = segmentStart = segmentEnd + ps;
- continue;
- }
- }
-
- if (x1 == null || x2 == null) continue;
-
- // clip x values
-
- // clip with xmin
- if (x1 <= x2 && x1 < axisx.min) {
- if (x2 < axisx.min) continue;
- y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
- x1 = axisx.min;
- } else if (x2 <= x1 && x2 < axisx.min) {
- if (x1 < axisx.min) continue;
- y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
- x2 = axisx.min;
- }
-
- // clip with xmax
- if (x1 >= x2 && x1 > axisx.max) {
- if (x2 > axisx.max) continue;
- y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
- x1 = axisx.max;
- } else if (x2 >= x1 && x2 > axisx.max) {
- if (x1 > axisx.max) continue;
- y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
- x2 = axisx.max;
- }
-
- if (!areaOpen) {
- // open area
- ctx.beginPath();
- ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
- areaOpen = true;
- }
-
- // now first check the case where both is outside
- if (y1 >= axisy.max && y2 >= axisy.max) {
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
- continue;
- } else if (y1 <= axisy.min && y2 <= axisy.min) {
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
- continue;
- }
-
- // else it's a bit more complicated, there might
- // be a flat maxed out rectangle first, then a
- // triangular cutout or reverse; to find these
- // keep track of the current x values
- var x1old = x1,
- x2old = x2;
-
- // clip the y values, without shortcutting, we
- // go through all cases in turn
-
- // clip with ymin
- if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
- x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
- y1 = axisy.min;
- } else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
- x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
- y2 = axisy.min;
- }
-
- // clip with ymax
- if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
- x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
- y1 = axisy.max;
- } else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
- x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
- y2 = axisy.max;
- }
-
- // if the x value was changed we got a rectangle
- // to fill
- if (x1 != x1old) {
- ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
- // it goes to (x1, y1), but we fill that below
- }
-
- // fill triangular section, this sometimes result
- // in redundant points if (x1, y1) hasn't changed
- // from previous line to, but we just ignore that
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
-
- // fill the other rectangle if it's there
- if (x2 != x2old) {
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
- ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
- }
- }
- }
-
- ctx.save();
- ctx.translate(plotOffset.left, plotOffset.top);
- ctx.lineJoin = "round";
-
- var lw = series.lines.lineWidth,
- sw = series.shadowSize;
- // FIXME: consider another form of shadow when filling is turned on
- if (lw > 0 && sw > 0) {
- // draw shadow as a thick and thin line with transparency
- ctx.lineWidth = sw;
- ctx.strokeStyle = "rgba(0,0,0,0.1)";
- // position shadow at angle from the mid of line
- var angle = Math.PI / 18;
- plotLine(series.datapoints, Math.sin(angle) * (lw / 2 + sw / 2), Math.cos(angle) * (lw / 2 + sw / 2), series.xaxis, series.yaxis);
- ctx.lineWidth = sw / 2;
- plotLine(series.datapoints, Math.sin(angle) * (lw / 2 + sw / 4), Math.cos(angle) * (lw / 2 + sw / 4), series.xaxis, series.yaxis);
- }
-
- ctx.lineWidth = lw;
- ctx.strokeStyle = series.color;
- var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
- if (fillStyle) {
- ctx.fillStyle = fillStyle;
- plotLineArea(series.datapoints, series.xaxis, series.yaxis);
- }
-
- if (lw > 0) plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
- ctx.restore();
- }
-
- function drawSeriesPoints(series) {
- function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
- var points = datapoints.points,
- ps = datapoints.pointsize;
-
- for (var i = 0; i < points.length; i += ps) {
- var x = points[i],
- y = points[i + 1];
- if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) continue;
-
- ctx.beginPath();
- x = axisx.p2c(x);
- y = axisy.p2c(y) + offset;
- if (symbol == "circle") ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
- else symbol(ctx, x, y, radius, shadow);
- ctx.closePath();
-
- if (fillStyle) {
- ctx.fillStyle = fillStyle;
- ctx.fill();
- }
- ctx.stroke();
- }
- }
-
- ctx.save();
- ctx.translate(plotOffset.left, plotOffset.top);
-
- var lw = series.points.lineWidth,
- sw = series.shadowSize,
- radius = series.points.radius,
- symbol = series.points.symbol;
-
- // If the user sets the line width to 0, we change it to a very
- // small value. A line width of 0 seems to force the default of 1.
- // Doing the conditional here allows the shadow setting to still be
- // optional even with a lineWidth of 0.
- if (lw == 0) lw = 0.0001;
-
- if (lw > 0 && sw > 0) {
- // draw shadow in two steps
- var w = sw / 2;
- ctx.lineWidth = w;
- ctx.strokeStyle = "rgba(0,0,0,0.1)";
- plotPoints(series.datapoints, radius, null, w + w / 2, true, series.xaxis, series.yaxis, symbol);
-
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
- plotPoints(series.datapoints, radius, null, w / 2, true, series.xaxis, series.yaxis, symbol);
- }
-
- ctx.lineWidth = lw;
- ctx.strokeStyle = series.points.strokeColor ? series.points.strokeColor : series.color;
- plotPoints(series.datapoints, radius, getFillStyle(series.points, series.color), 0, false, series.xaxis, series.yaxis, symbol);
- ctx.restore();
- }
-
- function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
- var left, right, bottom, top, drawLeft, drawRight, drawTop, drawBottom, tmp;
-
- // in horizontal mode, we start the bar from the left
- // instead of from the bottom so it appears to be
- // horizontal rather than vertical
- if (horizontal) {
- drawBottom = drawRight = drawTop = true;
- drawLeft = false;
- left = b;
- right = x;
- top = y + barLeft;
- bottom = y + barRight;
-
- // account for negative bars
- if (right < left) {
- tmp = right;
- right = left;
- left = tmp;
- drawLeft = true;
- drawRight = false;
- }
- } else {
- drawLeft = drawRight = drawTop = true;
- drawBottom = false;
- left = x + barLeft;
- right = x + barRight;
- bottom = b;
- top = y;
-
- // account for negative bars
- if (top < bottom) {
- tmp = top;
- top = bottom;
- bottom = tmp;
- drawBottom = true;
- drawTop = false;
- }
- }
-
- // clip
- if (right < axisx.min || left > axisx.max || top < axisy.min || bottom > axisy.max) return;
-
- if (left < axisx.min) {
- left = axisx.min;
- drawLeft = false;
- }
-
- if (right > axisx.max) {
- right = axisx.max;
- drawRight = false;
- }
-
- if (bottom < axisy.min) {
- bottom = axisy.min;
- drawBottom = false;
- }
-
- if (top > axisy.max) {
- top = axisy.max;
- drawTop = false;
- }
-
- left = axisx.p2c(left);
- bottom = axisy.p2c(bottom);
- right = axisx.p2c(right);
- top = axisy.p2c(top);
-
- // fill the bar
- if (fillStyleCallback) {
- c.beginPath();
- c.moveTo(left, bottom);
- c.lineTo(left, top);
- c.lineTo(right, top);
- c.lineTo(right, bottom);
- c.fillStyle = fillStyleCallback(bottom, top);
- c.fill();
- }
-
- // draw outline
- if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
- c.beginPath();
-
- // FIXME: inline moveTo is buggy with excanvas
- c.moveTo(left, bottom + offset);
- if (drawLeft) c.lineTo(left, top + offset);
- else c.moveTo(left, top + offset);
- if (drawTop) c.lineTo(right, top + offset);
- else c.moveTo(right, top + offset);
- if (drawRight) c.lineTo(right, bottom + offset);
- else c.moveTo(right, bottom + offset);
- if (drawBottom) c.lineTo(left, bottom + offset);
- else c.moveTo(left, bottom + offset);
- c.stroke();
- }
- }
-
- function drawSeriesBars(series) {
- function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
- var points = datapoints.points,
- ps = datapoints.pointsize;
-
- for (var i = 0; i < points.length; i += ps) {
- if (points[i] == null) continue;
- drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
- }
- }
-
- ctx.save();
- ctx.translate(plotOffset.left, plotOffset.top);
-
- // FIXME: figure out a way to add shadows (for instance along the right edge)
- ctx.lineWidth = series.bars.lineWidth;
- ctx.strokeStyle = series.color;
-
- var barLeft;
-
- switch (series.bars.align) {
- case "left":
- barLeft = 0;
- break;
- case "right":
- barLeft = -series.bars.barWidth;
- break;
- case "center":
- barLeft = -series.bars.barWidth / 2;
- break;
- default:
- throw new Error("Invalid bar alignment: " + series.bars.align);
- }
-
- var fillStyleCallback = series.bars.fill ?
- function(bottom, top) {
- return getFillStyle(series.bars, series.color, bottom, top);
- } : null;
- plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
- ctx.restore();
- }
-
- function getFillStyle(filloptions, seriesColor, bottom, top) {
- var fill = filloptions.fill;
- if (!fill) return null;
-
- if (filloptions.fillColor) return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
-
- var c = $.color.parse(seriesColor);
- c.a = typeof fill == "number" ? fill : 0.4;
- c.normalize();
- return c.toString();
- }
-
- function insertLegend() {
-
- placeholder.find(".legend").remove();
-
- if (!options.legend.show) return;
-
- var fragments = [],
- entries = [],
- rowStarted = false,
- lf = options.legend.labelFormatter,
- s, label;
-
- // Build a list of legend entries, with each having a label and a color
- for (var i = 0; i < series.length; ++i) {
- s = series[i];
- if (s.label) {
- label = lf ? lf(s.label, s) : s.label;
- if (label) {
- entries.push({
- label: label,
- color: s.color
- });
- }
- }
- }
-
- // Sort the legend using either the default or a custom comparator
- if (options.legend.sorted) {
- if ($.isFunction(options.legend.sorted)) {
- entries.sort(options.legend.sorted);
- } else if (options.legend.sorted == "reverse") {
- entries.reverse();
- } else {
- var ascending = options.legend.sorted != "descending";
- entries.sort(function(a, b) {
- return a.label == b.label ? 0 : (
- (a.label < b.label) != ascending ? 1 : -1 // Logical XOR
- );
- });
- }
- }
-
- // Generate markup for the list of entries, in their final order
- for (var i = 0; i < entries.length; ++i) {
-
- var entry = entries[i];
-
- if (i % options.legend.noColumns == 0) {
- if (rowStarted) fragments.push('');
- fragments.push('');
- rowStarted = true;
- }
-
- fragments.push(' ' + '' + entry.label + ' ');
- }
-
- if (rowStarted) fragments.push(' ');
-
- if (fragments.length == 0) return;
-
- var table = '' + fragments.join("") + '
';
- if (options.legend.container != null) $(options.legend.container).html(table);
- else {
- var pos = "",
- p = options.legend.position,
- m = options.legend.margin;
- if (m[0] == null) m = [m, m];
- if (p.charAt(0) == "n") pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
- else if (p.charAt(0) == "s") pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
- if (p.charAt(1) == "e") pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
- else if (p.charAt(1) == "w") pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
- var legend = $('' + table.replace('style="', 'style="position:absolute;' + pos + ';') + '
').appendTo(placeholder);
- if (options.legend.backgroundOpacity != 0.0) {
- // put in the transparent background
- // separately to avoid blended labels and
- // label boxes
- var c = options.legend.backgroundColor;
- if (c == null) {
- c = options.grid.backgroundColor;
- if (c && typeof c == "string") c = $.color.parse(c);
- else c = $.color.extract(legend, 'background-color');
- c.a = 1;
- c = c.toString();
- }
- var div = legend.children();
- $('
').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
- }
- }
- }
-
-
- // interactive features
- var highlights = [],
- redrawTimeout = null;
-
- // returns the data item the mouse is over, or null if none is found
- function findNearbyItem(mouseX, mouseY, seriesFilter) {
- var maxDistance = options.grid.mouseActiveRadius,
- smallestDistance = maxDistance * maxDistance + 1,
- item = null,
- foundPoint = false,
- i, j, ps;
-
- for (i = series.length - 1; i >= 0; --i) {
- if (!seriesFilter(series[i])) continue;
-
- var s = series[i],
- axisx = s.xaxis,
- axisy = s.yaxis,
- points = s.datapoints.points,
- mx = axisx.c2p(mouseX),
- // precompute some stuff to make the loop faster
- my = axisy.c2p(mouseY),
- maxx = maxDistance / axisx.scale,
- maxy = maxDistance / axisy.scale;
-
- ps = s.datapoints.pointsize;
- // with inverse transforms, we can't use the maxx/maxy
- // optimization, sadly
- if (axisx.options.inverseTransform) maxx = Number.MAX_VALUE;
- if (axisy.options.inverseTransform) maxy = Number.MAX_VALUE;
-
- if (s.lines.show || s.points.show) {
- for (j = 0; j < points.length; j += ps) {
- var x = points[j], y = points[j + 1];
- if (x == null) continue;
-
- // For points and lines, the cursor must be within a
- // certain distance to the data point
- if (x - mx > maxx || x - mx < -maxx || y - my > maxy || y - my < -maxy) continue;
-
- // We have to calculate distances in pixels, not in
- // data units, because the scales of the axes may be different
- var dx = Math.abs(axisx.p2c(x) - mouseX),
- dy = Math.abs(axisy.p2c(y) - mouseY),
- dist = dx * dx; // we save the sqrt
-
- // use <= to ensure last point takes precedence
- // (last generally means on top of)
- if (dist < smallestDistance) {
- smallestDistance = dist;
- item = [i, j / ps];
- }
- }
- }
-
- if (s.bars.show && !item) { // no other point can be nearby
- var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth / 2,
- barRight = barLeft + s.bars.barWidth;
-
- for (j = 0; j < points.length; j += ps) {
- var x = points[j],
- y = points[j + 1],
- b = points[j + 2];
- if (x == null) continue;
-
- // for a bar graph, the cursor must be inside the bar
- if (series[i].bars.horizontal ? (mx <= Math.max(b, x) && mx >= Math.min(b, x) && my >= y + barLeft && my <= y + barRight) : (mx >= x + barLeft && mx <= x + barRight && my >= Math.min(b, y) && my <= Math.max(b, y))) item = [i, j / ps];
- }
- }
- }
-
- if (item) {
- i = item[0];
- j = item[1];
- ps = series[i].datapoints.pointsize;
-
- return {
- datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
- dataIndex: j,
- series: series[i],
- seriesIndex: i
- };
- }
-
- return null;
- }
-
- function onMouseMove(e) {
- if (options.grid.hoverable) triggerClickHoverEvent("plothover", e, function(s) {
- return s["hoverable"] != false;
- });
- }
-
- function onMouseLeave(e) {
- if (options.grid.hoverable) triggerClickHoverEvent("plothover", e, function(s) {
- return false;
- });
- }
-
- function onClick(e) {
- triggerClickHoverEvent("plotclick", e, function(s) {
- return s["clickable"] != false;
- });
- }
-
- // trigger click or hover event (they send the same parameters
- // so we share their code)
- function triggerClickHoverEvent(eventname, event, seriesFilter) {
- var offset = eventHolder.offset(),
- canvasX = event.pageX - offset.left - plotOffset.left,
- canvasY = event.pageY - offset.top - plotOffset.top,
- pos = canvasToAxisCoords({
- left: canvasX,
- top: canvasY
- });
-
- pos.pageX = event.pageX;
- pos.pageY = event.pageY;
-
- var item = findNearbyItem(canvasX, canvasY, seriesFilter);
-
- if (item) {
- // fill in mouse pos for any listeners out there
- item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left, 10);
- item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10);
- }
-
- if (options.grid.autoHighlight) {
- // clear auto-highlights
- for (var i = 0; i < highlights.length; ++i) {
- var h = highlights[i];
- if (h.auto == eventname && !(item && h.series == item.series && h.point[0] == item.datapoint[0] && h.point[1] == item.datapoint[1])) unhighlight(h.series, h.point);
- }
-
- if (item) highlight(item.series, item.datapoint, eventname);
- }
-
- placeholder.trigger(eventname, [pos, item]);
- }
-
- function triggerRedrawOverlay() {
- var t = options.interaction.redrawOverlayInterval;
- if (t == -1) { // skip event queue
- drawOverlay();
- return;
- }
-
- if (!redrawTimeout) redrawTimeout = setTimeout(drawOverlay, t);
- }
-
- function drawOverlay() {
- redrawTimeout = null;
-
- // draw highlights
- octx.save();
- overlay.clear();
- octx.translate(plotOffset.left, plotOffset.top);
-
- var i, hi;
- for (i = 0; i < highlights.length; ++i) {
- hi = highlights[i];
-
- if (hi.series.bars.show) drawBarHighlight(hi.series, hi.point);
- else drawPointHighlight(hi.series, hi.point);
- }
- octx.restore();
-
- executeHooks(hooks.drawOverlay, [octx]);
- }
-
- function highlight(s, point, auto) {
- if (typeof s == "number") s = series[s];
-
- if (typeof point == "number") {
- var ps = s.datapoints.pointsize;
- point = s.datapoints.points.slice(ps * point, ps * (point + 1));
- }
-
- var i = indexOfHighlight(s, point);
- if (i == -1) {
- highlights.push({
- series: s,
- point: point,
- auto: auto
- });
-
- triggerRedrawOverlay();
- } else if (!auto) highlights[i].auto = false;
- }
-
- function unhighlight(s, point) {
- if (s == null && point == null) {
- highlights = [];
- triggerRedrawOverlay();
- return;
- }
-
- if (typeof s == "number") s = series[s];
-
- if (typeof point == "number") {
- var ps = s.datapoints.pointsize;
- point = s.datapoints.points.slice(ps * point, ps * (point + 1));
- }
-
- var i = indexOfHighlight(s, point);
- if (i != -1) {
- highlights.splice(i, 1);
-
- triggerRedrawOverlay();
- }
- }
-
- function indexOfHighlight(s, p) {
- for (var i = 0; i < highlights.length; ++i) {
- var h = highlights[i];
- if (h.series == s && h.point[0] == p[0] && h.point[1] == p[1]) return i;
- }
- return -1;
- }
-
- function drawPointHighlight(series, point) {
- var x = point[0],
- y = point[1],
- axisx = series.xaxis,
- axisy = series.yaxis,
- highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString();
-
- if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) return;
-
- var pointRadius = series.points.radius + series.points.lineWidth / 2;
- octx.lineWidth = pointRadius;
- octx.strokeStyle = highlightColor;
- var radius = 1.5 * pointRadius;
- x = axisx.p2c(x);
- y = axisy.p2c(y);
-
- octx.beginPath();
- if (series.points.symbol == "circle") octx.arc(x, y, radius, 0, 2 * Math.PI, false);
- else series.points.symbol(octx, x, y, radius, false);
- octx.closePath();
- octx.stroke();
- }
-
- function drawBarHighlight(series, point) {
- var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(),
- fillStyle = highlightColor,
- barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth / 2;
-
- octx.lineWidth = series.bars.lineWidth;
- octx.strokeStyle = highlightColor;
-
- drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, 0, function() {
- return fillStyle;
- }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
- }
-
- function getColorOrGradient(spec, bottom, top, defaultColor) {
- if (typeof spec == "string") return spec;
- else {
- // assume this is a gradient spec; IE currently only
- // supports a simple vertical gradient properly, so that's
- // what we support too
- var gradient = ctx.createLinearGradient(0, top, 0, bottom);
-
- for (var i = 0, l = spec.colors.length; i < l; ++i) {
- var c = spec.colors[i];
- if (typeof c != "string") {
- var co = $.color.parse(defaultColor);
- if (c.brightness != null) co = co.scale('rgb', c.brightness);
- if (c.opacity != null) co.a *= c.opacity;
- c = co.toString();
- }
- gradient.addColorStop(i / (l - 1), c);
- }
-
- return gradient;
- }
- }
- }
-
- // Add the plot function to the top level of the jQuery object
- $.plot = function(placeholder, data, options) {
- //var t0 = new Date();
- var plot = new Plot($(placeholder), data, options, $.plot.plugins);
- //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
- return plot;
- };
-
- $.plot.version = "0.9.0-alpha";
-
- $.plot.plugins = [];
-
- // Also add the plot function as a chainable property
- $.fn.plot = function(data, options) {
- return this.each(function() {
- $.plot(this, data, options);
- });
- }
-
- // round to nearby lower multiple of base
- function floorInBase(n, base) {
- return base * Math.floor(n / base);
- }
-
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.pie.js b/src/main/webapp/static/script/jquery.flot.pie.js
deleted file mode 100644
index 6553c8e..0000000
--- a/src/main/webapp/static/script/jquery.flot.pie.js
+++ /dev/null
@@ -1,817 +0,0 @@
-/* Flot plugin for rendering pie charts.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-The plugin assumes that each series has a single data value, and that each
-value is a positive integer or zero. Negative numbers don't make sense for a
-pie chart, and have unpredictable results. The values do NOT need to be
-passed in as percentages; the plugin will calculate the total and per-slice
-percentages internally.
-
-* Created by Brian Medendorp
-
-* Updated with contributions from btburnett3, Anthony Aragues and Xavi Ivars
-
-The plugin supports these options:
-
- series: {
- pie: {
- show: true/false
- radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
- innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
- startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
- tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
- offset: {
- top: integer value to move the pie up or down
- left: integer value to move the pie left or right, or 'auto'
- },
- stroke: {
- color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
- width: integer pixel width of the stroke
- },
- label: {
- show: true/false, or 'auto'
- formatter: a user-defined function that modifies the text/style of the label text
- radius: 0-1 for percentage of fullsize, or a specified pixel length
- background: {
- color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
- opacity: 0-1
- },
- threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
- },
- combine: {
- threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
- color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
- label: any text value of what the combined slice should be labeled
- }
- highlight: {
- opacity: 0-1
- }
- }
- }
-
-More detail and specific examples can be found in the included HTML file.
-
-*/
-
-(function($) {
-
- // Maximum redraw attempts when fitting labels within the plot
-
- var REDRAW_ATTEMPTS = 10;
-
- // Factor by which to shrink the pie when fitting labels within the plot
-
- var REDRAW_SHRINK = 0.95;
-
- function init(plot) {
-
- var canvas = null,
- target = null,
- maxRadius = null,
- centerLeft = null,
- centerTop = null,
- processed = false,
- ctx = null;
-
- // interactive variables
-
- var highlights = [];
-
- // add hook to determine if pie plugin in enabled, and then perform necessary operations
-
- plot.hooks.processOptions.push(function(plot, options) {
- if (options.series.pie.show) {
-
- options.grid.show = false;
-
- // set labels.show
-
- if (options.series.pie.label.show == "auto") {
- if (options.legend.show) {
- options.series.pie.label.show = false;
- } else {
- options.series.pie.label.show = true;
- }
- }
-
- // set radius
-
- if (options.series.pie.radius == "auto") {
- if (options.series.pie.label.show) {
- options.series.pie.radius = 3/4;
- } else {
- options.series.pie.radius = 1;
- }
- }
-
- // ensure sane tilt
-
- if (options.series.pie.tilt > 1) {
- options.series.pie.tilt = 1;
- } else if (options.series.pie.tilt < 0) {
- options.series.pie.tilt = 0;
- }
- }
- });
-
- plot.hooks.bindEvents.push(function(plot, eventHolder) {
- var options = plot.getOptions();
- if (options.series.pie.show) {
- if (options.grid.hoverable) {
- eventHolder.unbind("mousemove").mousemove(onMouseMove);
- }
- if (options.grid.clickable) {
- eventHolder.unbind("click").click(onClick);
- }
- }
- });
-
- plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) {
- var options = plot.getOptions();
- if (options.series.pie.show) {
- processDatapoints(plot, series, data, datapoints);
- }
- });
-
- plot.hooks.drawOverlay.push(function(plot, octx) {
- var options = plot.getOptions();
- if (options.series.pie.show) {
- drawOverlay(plot, octx);
- }
- });
-
- plot.hooks.draw.push(function(plot, newCtx) {
- var options = plot.getOptions();
- if (options.series.pie.show) {
- draw(plot, newCtx);
- }
- });
-
- function processDatapoints(plot, series, datapoints) {
- if (!processed) {
- processed = true;
- canvas = plot.getCanvas();
- target = $(canvas).parent();
- options = plot.getOptions();
- plot.setData(combine(plot.getData()));
- }
- }
-
- function combine(data) {
-
- var total = 0,
- combined = 0,
- numCombined = 0,
- color = options.series.pie.combine.color,
- newdata = [];
-
- // Fix up the raw data from Flot, ensuring the data is numeric
-
- for (var i = 0; i < data.length; ++i) {
-
- var value = data[i].data;
-
- // If the data is an array, we'll assume that it's a standard
- // Flot x-y pair, and are concerned only with the second value.
-
- // Note how we use the original array, rather than creating a
- // new one; this is more efficient and preserves any extra data
- // that the user may have stored in higher indexes.
-
- if ($.isArray(value) && value.length == 1) {
- value = value[0];
- }
-
- if ($.isArray(value)) {
- // Equivalent to $.isNumeric() but compatible with jQuery < 1.7
- if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) {
- value[1] = +value[1];
- } else {
- value[1] = 0;
- }
- } else if (!isNaN(parseFloat(value)) && isFinite(value)) {
- value = [1, +value];
- } else {
- value = [1, 0];
- }
-
- data[i].data = [value];
- }
-
- // Sum up all the slices, so we can calculate percentages for each
-
- for (var i = 0; i < data.length; ++i) {
- total += data[i].data[0][1];
- }
-
- // Count the number of slices with percentages below the combine
- // threshold; if it turns out to be just one, we won't combine.
-
- for (var i = 0; i < data.length; ++i) {
- var value = data[i].data[0][1];
- if (value / total <= options.series.pie.combine.threshold) {
- combined += value;
- numCombined++;
- if (!color) {
- color = data[i].color;
- }
- }
- }
-
- for (var i = 0; i < data.length; ++i) {
- var value = data[i].data[0][1];
- if (numCombined < 2 || value / total > options.series.pie.combine.threshold) {
- newdata.push({
- data: [[1, value]],
- color: data[i].color,
- label: data[i].label,
- angle: value * Math.PI * 2 / total,
- percent: value / (total / 100)
- });
- }
- }
-
- if (numCombined > 1) {
- newdata.push({
- data: [[1, combined]],
- color: color,
- label: options.series.pie.combine.label,
- angle: combined * Math.PI * 2 / total,
- percent: combined / (total / 100)
- });
- }
-
- return newdata;
- }
-
- function draw(plot, newCtx) {
-
- if (!target) {
- return; // if no series were passed
- }
-
- var canvasWidth = plot.getPlaceholder().width(),
- canvasHeight = plot.getPlaceholder().height(),
- legendWidth = target.children().filter(".legend").children().width() || 0;
-
- ctx = newCtx;
-
- // WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE!
-
- // When combining smaller slices into an 'other' slice, we need to
- // add a new series. Since Flot gives plugins no way to modify the
- // list of series, the pie plugin uses a hack where the first call
- // to processDatapoints results in a call to setData with the new
- // list of series, then subsequent processDatapoints do nothing.
-
- // The plugin-global 'processed' flag is used to control this hack;
- // it starts out false, and is set to true after the first call to
- // processDatapoints.
-
- // Unfortunately this turns future setData calls into no-ops; they
- // call processDatapoints, the flag is true, and nothing happens.
-
- // To fix this we'll set the flag back to false here in draw, when
- // all series have been processed, so the next sequence of calls to
- // processDatapoints once again starts out with a slice-combine.
- // This is really a hack; in 0.9 we need to give plugins a proper
- // way to modify series before any processing begins.
-
- processed = false;
-
- // calculate maximum radius and center point
-
- maxRadius = Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2;
- centerTop = canvasHeight / 2 + options.series.pie.offset.top;
- centerLeft = canvasWidth / 2;
-
- if (options.series.pie.offset.left == "auto") {
- if (options.legend.position.match("w")) {
- centerLeft += legendWidth / 2;
- } else {
- centerLeft -= legendWidth / 2;
- }
- } else {
- centerLeft += options.series.pie.offset.left;
- }
-
- if (centerLeft < maxRadius) {
- centerLeft = maxRadius;
- } else if (centerLeft > canvasWidth - maxRadius) {
- centerLeft = canvasWidth - maxRadius;
- }
-
- var slices = plot.getData(),
- attempts = 0;
-
- // Keep shrinking the pie's radius until drawPie returns true,
- // indicating that all the labels fit, or we try too many times.
-
- do {
- if (attempts > 0) {
- maxRadius *= REDRAW_SHRINK;
- }
- attempts += 1;
- clear();
- if (options.series.pie.tilt <= 0.8) {
- drawShadow();
- }
- } while (!drawPie() && attempts < REDRAW_ATTEMPTS)
-
- if (attempts >= REDRAW_ATTEMPTS) {
- clear();
- target.prepend("Could not draw pie with labels contained inside canvas
");
- }
-
- if (plot.setSeries && plot.insertLegend) {
- plot.setSeries(slices);
- plot.insertLegend();
- }
-
- // we're actually done at this point, just defining internal functions at this point
-
- function clear() {
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
- target.children().filter(".pieLabel, .pieLabelBackground").remove();
- }
-
- function drawShadow() {
-
- var shadowLeft = options.series.pie.shadow.left;
- var shadowTop = options.series.pie.shadow.top;
- var edge = 10;
- var alpha = options.series.pie.shadow.alpha;
- var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
-
- if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) {
- return; // shadow would be outside canvas, so don't draw it
- }
-
- ctx.save();
- ctx.translate(shadowLeft,shadowTop);
- ctx.globalAlpha = alpha;
- ctx.fillStyle = "#000";
-
- // center and rotate to starting position
-
- ctx.translate(centerLeft,centerTop);
- ctx.scale(1, options.series.pie.tilt);
-
- //radius -= edge;
-
- for (var i = 1; i <= edge; i++) {
- ctx.beginPath();
- ctx.arc(0, 0, radius, 0, Math.PI * 2, false);
- ctx.fill();
- radius -= i;
- }
-
- ctx.restore();
- }
-
- function drawPie() {
-
- var startAngle = Math.PI * options.series.pie.startAngle;
- var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
-
- // center and rotate to starting position
-
- ctx.save();
- ctx.translate(centerLeft,centerTop);
- ctx.scale(1, options.series.pie.tilt);
- //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
-
- // draw slices
-
- ctx.save();
- var currentAngle = startAngle;
- for (var i = 0; i < slices.length; ++i) {
- slices[i].startAngle = currentAngle;
- drawSlice(slices[i].angle, slices[i].color, true);
- }
- ctx.restore();
-
- // draw slice outlines
-
- if (options.series.pie.stroke.width > 0) {
- ctx.save();
- ctx.lineWidth = options.series.pie.stroke.width;
- currentAngle = startAngle;
- for (var i = 0; i < slices.length; ++i) {
- drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
- }
- ctx.restore();
- }
-
- // draw donut hole
-
- drawDonutHole(ctx);
-
- ctx.restore();
-
- // Draw the labels, returning true if they fit within the plot
-
- if (options.series.pie.label.show) {
- return drawLabels();
- } else return true;
-
- function drawSlice(angle, color, fill) {
-
- if (angle <= 0 || isNaN(angle)) {
- return;
- }
-
- if (fill) {
- ctx.fillStyle = color;
- } else {
- ctx.strokeStyle = color;
- ctx.lineJoin = "round";
- }
-
- ctx.beginPath();
- if (Math.abs(angle - Math.PI * 2) > 0.000000001) {
- ctx.moveTo(0, 0); // Center of the pie
- }
-
- //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera
- ctx.arc(0, 0, radius,currentAngle, currentAngle + angle / 2, false);
- ctx.arc(0, 0, radius,currentAngle + angle / 2, currentAngle + angle, false);
- ctx.closePath();
- //ctx.rotate(angle); // This doesn't work properly in Opera
- currentAngle += angle;
-
- if (fill) {
- ctx.fill();
- } else {
- ctx.stroke();
- }
- }
-
- function drawLabels() {
-
- var currentAngle = startAngle;
- var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius;
-
- for (var i = 0; i < slices.length; ++i) {
- if (slices[i].percent >= options.series.pie.label.threshold * 100) {
- if (!drawLabel(slices[i], currentAngle, i)) {
- return false;
- }
- }
- currentAngle += slices[i].angle;
- }
-
- return true;
-
- function drawLabel(slice, startAngle, index) {
-
- if (slice.data[0][1] == 0) {
- return true;
- }
-
- // format label text
-
- var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
-
- if (lf) {
- text = lf(slice.label, slice);
- } else {
- text = slice.label;
- }
-
- if (plf) {
- text = plf(text, slice);
- }
-
- var halfAngle = ((startAngle + slice.angle) + startAngle) / 2;
- var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
- var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
-
- var html = "" + text + " ";
- target.append(html);
-
- var label = target.children("#pieLabel" + index);
- var labelTop = (y - label.height() / 2);
- var labelLeft = (x - label.width() / 2);
-
- label.css("top", labelTop);
- label.css("left", labelLeft);
-
- // check to make sure that the label is not outside the canvas
-
- if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) {
- return false;
- }
-
- if (options.series.pie.label.background.opacity != 0) {
-
- // put in the transparent background separately to avoid blended labels and label boxes
-
- var c = options.series.pie.label.background.color;
-
- if (c == null) {
- c = slice.color;
- }
-
- var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;";
- $("
")
- .css("opacity", options.series.pie.label.background.opacity)
- .insertBefore(label);
- }
-
- return true;
- } // end individual label function
- } // end drawLabels function
- } // end drawPie function
- } // end draw function
-
- // Placed here because it needs to be accessed from multiple locations
-
- function drawDonutHole(layer) {
- if (options.series.pie.innerRadius > 0) {
-
- // subtract the center
-
- layer.save();
- var innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
- layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color
- layer.beginPath();
- layer.fillStyle = options.series.pie.stroke.color;
- layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
- layer.fill();
- layer.closePath();
- layer.restore();
-
- // add inner stroke
-
- layer.save();
- layer.beginPath();
- layer.strokeStyle = options.series.pie.stroke.color;
- layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
- layer.stroke();
- layer.closePath();
- layer.restore();
-
- // TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
- }
- }
-
- //-- Additional Interactive related functions --
-
- function isPointInPoly(poly, pt) {
- for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
- ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
- && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
- && (c = !c);
- return c;
- }
-
- function findNearbySlice(mouseX, mouseY) {
-
- var slices = plot.getData(),
- options = plot.getOptions(),
- radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius,
- x, y;
-
- for (var i = 0; i < slices.length; ++i) {
-
- var s = slices[i];
-
- if (s.pie.show) {
-
- ctx.save();
- ctx.beginPath();
- ctx.moveTo(0, 0); // Center of the pie
- //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
- ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle / 2, false);
- ctx.arc(0, 0, radius, s.startAngle + s.angle / 2, s.startAngle + s.angle, false);
- ctx.closePath();
- x = mouseX - centerLeft;
- y = mouseY - centerTop;
-
- if (ctx.isPointInPath) {
- if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) {
- ctx.restore();
- return {
- datapoint: [s.percent, s.data],
- dataIndex: 0,
- series: s,
- seriesIndex: i
- };
- }
- } else {
-
- // excanvas for IE doesn;t support isPointInPath, this is a workaround.
-
- var p1X = radius * Math.cos(s.startAngle),
- p1Y = radius * Math.sin(s.startAngle),
- p2X = radius * Math.cos(s.startAngle + s.angle / 4),
- p2Y = radius * Math.sin(s.startAngle + s.angle / 4),
- p3X = radius * Math.cos(s.startAngle + s.angle / 2),
- p3Y = radius * Math.sin(s.startAngle + s.angle / 2),
- p4X = radius * Math.cos(s.startAngle + s.angle / 1.5),
- p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5),
- p5X = radius * Math.cos(s.startAngle + s.angle),
- p5Y = radius * Math.sin(s.startAngle + s.angle),
- arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]],
- arrPoint = [x, y];
-
- // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
-
- if (isPointInPoly(arrPoly, arrPoint)) {
- ctx.restore();
- return {
- datapoint: [s.percent, s.data],
- dataIndex: 0,
- series: s,
- seriesIndex: i
- };
- }
- }
-
- ctx.restore();
- }
- }
-
- return null;
- }
-
- function onMouseMove(e) {
- triggerClickHoverEvent("plothover", e);
- }
-
- function onClick(e) {
- triggerClickHoverEvent("plotclick", e);
- }
-
- // trigger click or hover event (they send the same parameters so we share their code)
-
- function triggerClickHoverEvent(eventname, e) {
-
- var offset = plot.offset();
- var canvasX = parseInt(e.pageX - offset.left);
- var canvasY = parseInt(e.pageY - offset.top);
- var item = findNearbySlice(canvasX, canvasY);
-
- if (options.grid.autoHighlight) {
-
- // clear auto-highlights
-
- for (var i = 0; i < highlights.length; ++i) {
- var h = highlights[i];
- if (h.auto == eventname && !(item && h.series == item.series)) {
- unhighlight(h.series);
- }
- }
- }
-
- // highlight the slice
-
- if (item) {
- highlight(item.series, eventname);
- }
-
- // trigger any hover bind events
-
- var pos = { pageX: e.pageX, pageY: e.pageY };
- target.trigger(eventname, [pos, item]);
- }
-
- function highlight(s, auto) {
- //if (typeof s == "number") {
- // s = series[s];
- //}
-
- var i = indexOfHighlight(s);
-
- if (i == -1) {
- highlights.push({ series: s, auto: auto });
- plot.triggerRedrawOverlay();
- } else if (!auto) {
- highlights[i].auto = false;
- }
- }
-
- function unhighlight(s) {
- if (s == null) {
- highlights = [];
- plot.triggerRedrawOverlay();
- }
-
- //if (typeof s == "number") {
- // s = series[s];
- //}
-
- var i = indexOfHighlight(s);
-
- if (i != -1) {
- highlights.splice(i, 1);
- plot.triggerRedrawOverlay();
- }
- }
-
- function indexOfHighlight(s) {
- for (var i = 0; i < highlights.length; ++i) {
- var h = highlights[i];
- if (h.series == s)
- return i;
- }
- return -1;
- }
-
- function drawOverlay(plot, octx) {
-
- var options = plot.getOptions();
-
- var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
-
- octx.save();
- octx.translate(centerLeft, centerTop);
- octx.scale(1, options.series.pie.tilt);
-
- for (var i = 0; i < highlights.length; ++i) {
- drawHighlight(highlights[i].series);
- }
-
- drawDonutHole(octx);
-
- octx.restore();
-
- function drawHighlight(series) {
-
- if (series.angle <= 0 || isNaN(series.angle)) {
- return;
- }
-
- //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
- octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor
- octx.beginPath();
- if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) {
- octx.moveTo(0, 0); // Center of the pie
- }
- octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle / 2, false);
- octx.arc(0, 0, radius, series.startAngle + series.angle / 2, series.startAngle + series.angle, false);
- octx.closePath();
- octx.fill();
- }
- }
- } // end init (plugin body)
-
- // define pie specific options and their default values
-
- var options = {
- series: {
- pie: {
- show: false,
- radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
- innerRadius: 0, /* for donut */
- startAngle: 3/2,
- tilt: 1,
- shadow: {
- left: 5, // shadow left offset
- top: 15, // shadow top offset
- alpha: 0.02 // shadow alpha
- },
- offset: {
- top: 0,
- left: "auto"
- },
- stroke: {
- color: "#fff",
- width: 1
- },
- label: {
- show: "auto",
- formatter: function(label, slice) {
- return "" + label + " " + Math.round(slice.percent) + "%
";
- }, // formatter function
- radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
- background: {
- color: null,
- opacity: 0
- },
- threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow)
- },
- combine: {
- threshold: -1, // percentage at which to combine little slices into one larger slice
- color: null, // color to give the new slice (auto-generated if null)
- label: "Other" // label to give the new slice
- },
- highlight: {
- //color: "#fff", // will add this functionality once parseColor is available
- opacity: 0.5
- }
- }
- }
- };
-
- $.plot.plugins.push({
- init: init,
- options: options,
- name: "pie",
- version: "1.1"
- });
-
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.resize.js b/src/main/webapp/static/script/jquery.flot.resize.js
deleted file mode 100644
index f9d5d4e..0000000
--- a/src/main/webapp/static/script/jquery.flot.resize.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Flot plugin for automatically redrawing plots as the placeholder resizes.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-It works by listening for changes on the placeholder div (through the jQuery
-resize event plugin) - if the size changes, it will redraw the plot.
-
-There are no options. If you need to disable the plugin for some plots, you
-can just fix the size of their placeholders.
-
-Modified by Avi Kohn
-
-*/
-
-/* Inline dependency:
- * jQuery resize event - v1.1 - 3/14/2010
- * http://benalman.com/projects/jquery-resize-plugin/
- *
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-
-(function($,t,n){function p(){for(var n=r.length-1;n>=0;n--){var o=$(r[n]);if(o[0]==t||o.is(":visible")){var h=o.width(),d=o.height(),v=o.data(a);!v||h===v.w&&d===v.h?i[f]=i[l]:(i[f]=i[c],o.trigger(u,[v.w=h,v.h=d]))}else v=o.data(a),v.w=0,v.h=0}s!==null&&(s=t.requestAnimationFrame(p))}var r=[],i=$.resize=$.extend($.resize,{}),s,o="setTimeout",u="resize",a=u+"-special-event",f="delay",l="pendingDelay",c="activeDelay",h="throttleWindow";i[l]=250,i[c]=20,i[f]=i[l],i[h]=!0,$.event.special[u]={setup:function(){if(!i[h]&&this[o])return!1;var t=$(this);r.push(this),t.data(a,{w:t.width(),h:t.height()}),r.length===1&&(s=n,p())},teardown:function(){if(!i[h]&&this[o])return!1;var t=$(this);for(var n=r.length-1;n>=0;n--)if(r[n]==this){r.splice(n,1);break}t.removeData(a),r.length||(cancelAnimationFrame(s),s=null)},add:function(t){function s(t,i,s){var o=$(this),u=o.data(a);u.w=i!==n?i:o.width(),u.h=s!==n?s:o.height(),r.apply(this,arguments)}if(!i[h]&&this[o])return!1;var r;if($.isFunction(t))return r=t,s;r=t.handler,t.handler=s}},t.requestAnimationFrame||(t.requestAnimationFrame=function(){return t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||t.msRequestAnimationFrame||function(e,n){return t.setTimeout(e,i[f])}}()),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(){return t.webkitCancelRequestAnimationFrame||t.mozCancelRequestAnimationFrame||t.oCancelRequestAnimationFrame||t.msCancelRequestAnimationFrame||clearTimeout}())})(jQuery,this);
-
-(function ($) {
- var options = { }; // no options
-
- function init(plot) {
- function onResize() {
- var placeholder = plot.getPlaceholder();
-
- if (placeholder.width() == 0 || placeholder.height() == 0)
- return;
-
- placeholder.trigger("resizestart");
-
- plot.resize();
- plot.setupGrid();
- plot.draw();
-
- placeholder.trigger("resizeend");
- }
-
- function bindEvents(plot, eventHolder) {
- plot.getPlaceholder().resize(onResize);
- }
-
- function shutdown(plot, eventHolder) {
- plot.getPlaceholder().unbind("resize", onResize);
- }
-
- plot.hooks.bindEvents.push(bindEvents);
- plot.hooks.shutdown.push(shutdown);
- }
-
- $.plot.plugins.push({
- init: init,
- options: options,
- name: 'resize',
- version: '1.0'
- });
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.spline.js b/src/main/webapp/static/script/jquery.flot.spline.js
deleted file mode 100644
index 3ae0521..0000000
--- a/src/main/webapp/static/script/jquery.flot.spline.js
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- * Flot plugin that provides spline interpolation for line graphs
- * author: Alex Bardas < alex.bardas@gmail.com >
- * modified by: Avi Kohn https://github.com/AMKohn
- * based on the spline interpolation described at:
- * http://scaledinnovation.com/analytics/splines/aboutSplines.html
- *
- * Example usage: (add in plot options series object)
- * for linespline:
- * series: {
- * ...
- * lines: {
- * show: false
- * },
- * splines: {
- * show: true,
- * tension: x, (float between 0 and 1, defaults to 0.5),
- * lineWidth: y (number, defaults to 2),
- * fill: z (float between 0 .. 1 or false, as in flot documentation)
- * },
- * ...
- * }
- * areaspline:
- * series: {
- * ...
- * lines: {
- * show: true,
- * lineWidth: 0, (line drawing will not execute)
- * fill: x, (float between 0 .. 1, as in flot documentation)
- * ...
- * },
- * splines: {
- * show: true,
- * tension: 0.5 (float between 0 and 1)
- * },
- * ...
- * }
- *
- */
-
-(function($) {
- 'use strict'
-
- /**
- * @param {Number} x0, y0, x1, y1: coordinates of the end (knot) points of the segment
- * @param {Number} x2, y2: the next knot (not connected, but needed to calculate p2)
- * @param {Number} tension: control how far the control points spread
- * @return {Array}: p1 -> control point, from x1 back toward x0
- * p2 -> the next control point, returned to become the next segment's p1
- *
- * @api private
- */
- function getControlPoints(x0, y0, x1, y1, x2, y2, tension) {
-
- var pow = Math.pow,
- sqrt = Math.sqrt,
- d01, d12, fa, fb, p1x, p1y, p2x, p2y;
-
- // Scaling factors: distances from this knot to the previous and following knots.
- d01 = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2));
- d12 = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
-
- fa = tension * d01 / (d01 + d12);
- fb = tension - fa;
-
- p1x = x1 + fa * (x0 - x2);
- p1y = y1 + fa * (y0 - y2);
-
- p2x = x1 - fb * (x0 - x2);
- p2y = y1 - fb * (y0 - y2);
-
- return [p1x, p1y, p2x, p2y];
- }
-
- var line = [];
-
- function drawLine(points, ctx, height, fill, seriesColor) {
- var c = $.color.parse(seriesColor);
-
- c.a = typeof fill == "number" ? fill : .3;
- c.normalize();
- c = c.toString();
-
- ctx.beginPath();
- ctx.moveTo(points[0][0], points[0][1]);
-
- var plength = points.length;
-
- for (var i = 0; i < plength; i++) {
- ctx[points[i][3]].apply(ctx, points[i][2]);
- }
-
- ctx.stroke();
-
- ctx.lineWidth = 0;
- ctx.lineTo(points[plength - 1][0], height);
- ctx.lineTo(points[0][0], height);
-
- ctx.closePath();
-
- if (fill !== false) {
- ctx.fillStyle = c;
- ctx.fill();
- }
- }
-
- /**
- * @param {Object} ctx: canvas context
- * @param {String} type: accepted strings: 'bezier' or 'quadratic' (defaults to quadratic)
- * @param {Array} points: 2 points for which to draw the interpolation
- * @param {Array} cpoints: control points for those segment points
- *
- * @api private
- */
- function queue(ctx, type, points, cpoints) {
- if (type === void 0 || (type !== 'bezier' && type !== 'quadratic')) {
- type = 'quadratic';
- }
- type = type + 'CurveTo';
-
- if (line.length == 0) line.push([points[0], points[1], cpoints.concat(points.slice(2)), type]);
- else if (type == "quadraticCurveTo" && points.length == 2) {
- cpoints = cpoints.slice(0, 2).concat(points);
-
- line.push([points[0], points[1], cpoints, type]);
- }
- else line.push([points[2], points[3], cpoints.concat(points.slice(2)), type]);
- }
-
- /**
- * @param {Object} plot
- * @param {Object} ctx: canvas context
- * @param {Object} series
- *
- * @api private
- */
-
- function drawSpline(plot, ctx, series) {
- // Not interested if spline is not requested
- if (series.splines.show !== true) {
- return;
- }
-
- var cp = [],
- // array of control points
- tension = series.splines.tension || 0.5,
- idx, x, y, points = series.datapoints.points,
- ps = series.datapoints.pointsize,
- plotOffset = plot.getPlotOffset(),
- len = points.length,
- pts = [];
-
- line = [];
-
- // Cannot display a linespline/areaspline if there are less than 3 points
- if (len / ps < 4) {
- $.extend(series.lines, series.splines);
- return;
- }
-
- for (idx = 0; idx < len; idx += ps) {
- x = points[idx];
- y = points[idx + 1];
- if (x == null || x < series.xaxis.min || x > series.xaxis.max || y < series.yaxis.min || y > series.yaxis.max) {
- continue;
- }
-
- pts.push(series.xaxis.p2c(x) + plotOffset.left, series.yaxis.p2c(y) + plotOffset.top);
- }
-
- len = pts.length;
-
- // Draw an open curve, not connected at the ends
- for (idx = 0; idx < len - 2; idx += 2) {
- cp = cp.concat(getControlPoints.apply(this, pts.slice(idx, idx + 6).concat([tension])));
- }
-
- ctx.save();
- ctx.strokeStyle = series.color;
- ctx.lineWidth = series.splines.lineWidth;
-
- queue(ctx, 'quadratic', pts.slice(0, 4), cp.slice(0, 2));
-
- for (idx = 2; idx < len - 3; idx += 2) {
- queue(ctx, 'bezier', pts.slice(idx, idx + 4), cp.slice(2 * idx - 2, 2 * idx + 2));
- }
-
- queue(ctx, 'quadratic', pts.slice(len - 2, len), [cp[2 * len - 10], cp[2 * len - 9], pts[len - 4], pts[len - 3]]);
-
- drawLine(line, ctx, plot.height() + 10, series.splines.fill, series.color);
-
- ctx.restore();
- }
-
- $.plot.plugins.push({
- init: function(plot) {
- plot.hooks.drawSeries.push(drawSpline);
- },
- options: {
- series: {
- splines: {
- show: false,
- lineWidth: 2,
- tension: 0.5,
- fill: false
- }
- }
- },
- name: 'spline',
- version: '0.8.2'
- });
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.stack.js b/src/main/webapp/static/script/jquery.flot.stack.js
deleted file mode 100644
index c01de67..0000000
--- a/src/main/webapp/static/script/jquery.flot.stack.js
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Flot plugin for stacking data sets rather than overlyaing them.
-
-Copyright (c) 2007-2013 IOLA and Ole Laursen.
-Licensed under the MIT license.
-
-The plugin assumes the data is sorted on x (or y if stacking horizontally).
-For line charts, it is assumed that if a line has an undefined gap (from a
-null point), then the line above it should have the same gap - insert zeros
-instead of "null" if you want another behaviour. This also holds for the start
-and end of the chart. Note that stacking a mix of positive and negative values
-in most instances doesn't make sense (so it looks weird).
-
-Two or more series are stacked when their "stack" attribute is set to the same
-key (which can be any number or string or just "true"). To specify the default
-stack, you can set the stack option like this:
-
- series: {
- stack: null/false, true, or a key (number/string)
- }
-
-You can also specify it for a single series, like this:
-
- $.plot( $("#placeholder"), [{
- data: [ ... ],
- stack: true
- }])
-
-The stacking order is determined by the order of the data series in the array
-(later series end up on top of the previous).
-
-Internally, the plugin modifies the datapoints in each series, adding an
-offset to the y value. For line series, extra data points are inserted through
-interpolation. If there's a second y value, it's also adjusted (e.g for bar
-charts or filled areas).
-
-*/
-
-(function ($) {
- var options = {
- series: { stack: null } // or number/string
- };
-
- function init(plot) {
- function findMatchingSeries(s, allseries) {
- var res = null;
- for (var i = 0; i < allseries.length; ++i) {
- if (s == allseries[i])
- break;
-
- if (allseries[i].stack == s.stack)
- res = allseries[i];
- }
-
- return res;
- }
-
- function stackData(plot, s, datapoints) {
- if (s.stack == null || s.stack === false)
- return;
-
- var other = findMatchingSeries(s, plot.getData());
- if (!other)
- return;
-
- var ps = datapoints.pointsize,
- points = datapoints.points,
- otherps = other.datapoints.pointsize,
- otherpoints = other.datapoints.points,
- newpoints = [],
- px, py, intery, qx, qy, bottom,
- withlines = s.lines.show,
- horizontal = s.bars.horizontal,
- withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
- withsteps = withlines && s.lines.steps,
- fromgap = true,
- keyOffset = horizontal ? 1 : 0,
- accumulateOffset = horizontal ? 0 : 1,
- i = 0, j = 0, l, m;
-
- while (true) {
- if (i >= points.length)
- break;
-
- l = newpoints.length;
-
- if (points[i] == null) {
- // copy gaps
- for (m = 0; m < ps; ++m)
- newpoints.push(points[i + m]);
- i += ps;
- }
- else if (j >= otherpoints.length) {
- // for lines, we can't use the rest of the points
- if (!withlines) {
- for (m = 0; m < ps; ++m)
- newpoints.push(points[i + m]);
- }
- i += ps;
- }
- else if (otherpoints[j] == null) {
- // oops, got a gap
- for (m = 0; m < ps; ++m)
- newpoints.push(null);
- fromgap = true;
- j += otherps;
- }
- else {
- // cases where we actually got two points
- px = points[i + keyOffset];
- py = points[i + accumulateOffset];
- qx = otherpoints[j + keyOffset];
- qy = otherpoints[j + accumulateOffset];
- bottom = 0;
-
- if (px == qx) {
- for (m = 0; m < ps; ++m)
- newpoints.push(points[i + m]);
-
- newpoints[l + accumulateOffset] += qy;
- bottom = qy;
-
- i += ps;
- j += otherps;
- }
- else if (px > qx) {
- // we got past point below, might need to
- // insert interpolated extra point
- if (withlines && i > 0 && points[i - ps] != null) {
- intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
- newpoints.push(qx);
- newpoints.push(intery + qy);
- for (m = 2; m < ps; ++m)
- newpoints.push(points[i + m]);
- bottom = qy;
- }
-
- j += otherps;
- }
- else { // px < qx
- if (fromgap && withlines) {
- // if we come from a gap, we just skip this point
- i += ps;
- continue;
- }
-
- for (m = 0; m < ps; ++m)
- newpoints.push(points[i + m]);
-
- // we might be able to interpolate a point below,
- // this can give us a better y
- if (withlines && j > 0 && otherpoints[j - otherps] != null)
- bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);
-
- newpoints[l + accumulateOffset] += bottom;
-
- i += ps;
- }
-
- fromgap = false;
-
- if (l != newpoints.length && withbottom)
- newpoints[l + 2] += bottom;
- }
-
- // maintain the line steps invariant
- if (withsteps && l != newpoints.length && l > 0
- && newpoints[l] != null
- && newpoints[l] != newpoints[l - ps]
- && newpoints[l + 1] != newpoints[l - ps + 1]) {
- for (m = 0; m < ps; ++m)
- newpoints[l + ps + m] = newpoints[l + m];
- newpoints[l + 1] = newpoints[l - ps + 1];
- }
- }
-
- datapoints.points = newpoints;
- }
-
- plot.hooks.processDatapoints.push(stackData);
- }
-
- $.plot.plugins.push({
- init: init,
- options: options,
- name: 'stack',
- version: '1.2'
- });
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.flot.tooltip.js b/src/main/webapp/static/script/jquery.flot.tooltip.js
deleted file mode 100644
index d8345eb..0000000
--- a/src/main/webapp/static/script/jquery.flot.tooltip.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * jquery.flot.tooltip
- *
- * description: easy-to-use tooltips for Flot charts
- * version: 0.6.7
- * author: Krzysztof Urbas @krzysu [myviews.pl]
- * website: https://github.com/krzysu/flot.tooltip
- *
- * build on 2014-03-14
- * released under MIT License, 2012
-*/
-(function ($) {
-
- // plugin options, default values
- var defaultOptions = {
- tooltip: false,
- tooltipOpts: {
- 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,
-
- // callbacks
- onHover: function(flotItem, $tooltipEl) {}
- }
- };
-
- // 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;
-
- // 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;
- that.updateTooltipPosition(pos);
- }
-
- function plothover(event, pos, item) {
- var $tip = that.getDomElement();
- if (item) {
- var tipText;
-
- // convert tooltip content template to real tipText
- tipText = that.stringFormat(that.tooltipOptions.content, item);
-
- $tip.html( tipText );
- that.updateTooltipPosition({ x: pos.pageX, y: pos.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(item, $tip);
- }
- }
- else {
- $tip.hide().html('');
- }
- }
- };
-
- /**
- * get or create tooltip DOM element
- * @return jQuery object
- */
- FlotTooltip.prototype.getDomElement = function() {
- var $tip;
-
- if( $('#flotTip').length > 0 ){
- $tip = $('#flotTip');
- }
- else {
- $tip = $('
').attr('id', 'flotTip');
- $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;
- };
-
- // as the name says
- FlotTooltip.prototype.updateTooltipPosition = function(pos) {
- var totalTipWidth = $("#flotTip").outerWidth() + this.tooltipOptions.shifts.x;
- var totalTipHeight = $("#flotTip").outerHeight() + this.tooltipOptions.shifts.y;
- if ((pos.x - $(window).scrollLeft()) > ($(window).innerWidth() - totalTipWidth)) {
- pos.x -= totalTipWidth;
- }
- if ((pos.y - $(window).scrollTop()) > ($(window).innerHeight() - totalTipHeight)) {
- pos.y -= totalTipHeight;
- }
- this.tipPosition.x = pos.x;
- this.tipPosition.y = pos.y;
- };
-
- /**
- * 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 x, y;
-
- // 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];
- } else {
- x = item.series.data[item.dataIndex][0];
- y = item.series.data[item.dataIndex][1];
- }
-
- // 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
- if( typeof (item.series.percent) !== 'undefined' ) {
- content = this.adjustValPrecision(percentPattern, content, item.series.percent);
- }
-
- // 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));
- }
-
- if(this.isTimeMode('yaxis', item) && this.isYDateFormat(item)) {
- content = content.replace(yPattern, this.timestampToDate(y, this.tooltipOptions.yDateFormat));
- }
-
- // 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))
- 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 value = (this.isCategoriesMode('yaxis', item)) ? item.series.yaxis.ticks[index].label : item.series.yaxis.ticks[index].v;
- if (value === 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, '$$'));
- }
-
- 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) {
- var theDate = new Date(tmst*1);
- 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 (this.plotPlugins.indexOf('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 ($.grep($.plot.plugins, function(p){ return p.name === "tickRotor"; }).length === 1 && 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.6.7'
- });
-
-})(jQuery);
diff --git a/src/main/webapp/static/script/jquery.menu.js b/src/main/webapp/static/script/jquery.menu.js
deleted file mode 100644
index ab4a0a3..0000000
--- a/src/main/webapp/static/script/jquery.menu.js
+++ /dev/null
@@ -1,57 +0,0 @@
-$(function () {
- var flag;
- if($('body').hasClass('sidebar-colors')){
- flag = true;
- } else{
- flag = false;
- }
- $('#menu-toggle').toggle(
- function() {
- if($('#wrapper').hasClass('right-sidebar')) {
- $('body').addClass('right-side-collapsed')
- $('#sidebar .slimScrollDiv').css('overflow', 'initial');
- $('#sidebar .menu-scroll').css('overflow', 'initial');
- } else{
- $('body').addClass('left-side-collapsed').removeClass('sidebar-colors');
- $('#sidebar .slimScrollDiv').css('overflow', 'initial');
- $('#sidebar .menu-scroll').css('overflow', 'initial');
- }
- }, function() {
- if($('#wrapper').hasClass('right-sidebar')) {
- $('body').removeClass('right-side-collapsed');
- $('#sidebar .slimScrollDiv').css('overflow', 'hidden');
- $('#sidebar .menu-scroll').css('overflow', 'hidden');
- } else{
- $('body').removeClass('left-side-collapsed')
- if(flag == true){
- $('body').addClass('sidebar-colors');
- }
- $('#sidebar .slimScrollDiv').css('overflow', 'hidden');
- $('#sidebar .menu-scroll').css('overflow', 'hidden');
- }
- }
- );
-
- if($('#wrapper').hasClass('right-sidebar')) {
- $('ul#side-menu li').hover(function () {
- if ($('body').hasClass('right-side-collapsed')) {
- $(this).addClass('nav-hover');
- }
- }, function () {
- if ($('body').hasClass('right-side-collapsed')) {
- $(this).removeClass('nav-hover');
- }
- });
- } else{
- $('ul#side-menu li').hover(function () {
- if ($('body').hasClass('left-side-collapsed')) {
- $(this).addClass('nav-hover');
- }
- }, function () {
- if ($('body').hasClass('left-side-collapsed')) {
- $(this).removeClass('nav-hover');
- }
- });
- }
-
-});
\ No newline at end of file
diff --git a/src/main/webapp/static/script/jquery.metisMenu.js b/src/main/webapp/static/script/jquery.metisMenu.js
deleted file mode 100644
index a28523c..0000000
--- a/src/main/webapp/static/script/jquery.metisMenu.js
+++ /dev/null
@@ -1,48 +0,0 @@
-;(function ($, window, document, undefined) {
-
- var pluginName = "metisMenu",
- defaults = {
- toggle: true
- };
-
- function Plugin(element, options) {
- this.element = element;
- this.settings = $.extend({}, defaults, options);
- this._defaults = defaults;
- this._name = pluginName;
- this.init();
- }
-
- Plugin.prototype = {
- init: function () {
-
- var $this = $(this.element),
- $toggle = this.settings.toggle;
-
- $this.find('li.active').has('ul').children('ul').addClass('collapse in');
- $this.find('li').not('.active').has('ul').children('ul').addClass('collapse');
-
- $this.find('li').has('ul').children('a').on('click', function (e) {
- e.preventDefault();
-
- $(this).parent('li').toggleClass('active').children('ul').collapse('toggle');
-
- if ($toggle) {
- $(this).parent('li').siblings().removeClass('active').children('ul.in').collapse('hide');
- }
-/*
- $this.find('li.active').has('ul').children('ul').addClass('collapse in');
- $this.find('li').not('.active').has('ul').children('ul').addClass('collapse');*/
- });
- }
- };
-
- $.fn[ pluginName ] = function (options) {
- return this.each(function () {
- if (!$.data(this, "plugin_" + pluginName)) {
- $.data(this, "plugin_" + pluginName, new Plugin(this, options));
- }
- });
- };
-
-})(jQuery, window, document);
diff --git a/src/main/webapp/static/script/jquery.nestable.js b/src/main/webapp/static/script/jquery.nestable.js
deleted file mode 100644
index 0405cf1..0000000
--- a/src/main/webapp/static/script/jquery.nestable.js
+++ /dev/null
@@ -1,485 +0,0 @@
-/*!
- * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
- * Dual-licensed under the BSD or MIT licenses
- */
-;(function($, window, document, undefined)
-{
- var hasTouch = 'ontouchstart' in window;
-
- /**
- * Detect CSS pointer-events property
- * events are normally disabled on the dragging element to avoid conflicts
- * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
- */
- var hasPointerEvents = (function()
- {
- var el = document.createElement('div'),
- docEl = document.documentElement;
- if (!('pointerEvents' in el.style)) {
- return false;
- }
- el.style.pointerEvents = 'auto';
- el.style.pointerEvents = 'x';
- docEl.appendChild(el);
- var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
- docEl.removeChild(el);
- return !!supports;
- })();
-
- var eStart = hasTouch ? 'touchstart' : 'mousedown',
- eMove = hasTouch ? 'touchmove' : 'mousemove',
- eEnd = hasTouch ? 'touchend' : 'mouseup';
- eCancel = hasTouch ? 'touchcancel' : 'mouseup';
-
- var defaults = {
- listNodeName : 'ol',
- itemNodeName : 'li',
- rootClass : 'dd',
- listClass : 'dd-list',
- itemClass : 'dd-item',
- dragClass : 'dd-dragel',
- handleClass : 'dd-handle',
- collapsedClass : 'dd-collapsed',
- placeClass : 'dd-placeholder',
- noDragClass : 'dd-nodrag',
- emptyClass : 'dd-empty',
- expandBtnHTML : 'Expand ',
- collapseBtnHTML : 'Collapse ',
- group : 0,
- maxDepth : 5,
- threshold : 20
- };
-
- function Plugin(element, options)
- {
- this.w = $(window);
- this.el = $(element);
- this.options = $.extend({}, defaults, options);
- this.init();
- }
-
- Plugin.prototype = {
-
- init: function()
- {
- var list = this;
-
- list.reset();
-
- list.el.data('nestable-group', this.options.group);
-
- list.placeEl = $('
');
-
- $.each(this.el.find(list.options.itemNodeName), function(k, el) {
- list.setParent($(el));
- });
-
- list.el.on('click', 'button', function(e) {
- if (list.dragEl || (!hasTouch && e.button !== 0)) {
- return;
- }
- var target = $(e.currentTarget),
- action = target.data('action'),
- item = target.parent(list.options.itemNodeName);
- if (action === 'collapse') {
- list.collapseItem(item);
- }
- if (action === 'expand') {
- list.expandItem(item);
- }
- });
-
- var onStartEvent = function(e)
- {
- var handle = $(e.target);
- if (!handle.hasClass(list.options.handleClass)) {
- if (handle.closest('.' + list.options.noDragClass).length) {
- return;
- }
- handle = handle.closest('.' + list.options.handleClass);
- }
- if (!handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) {
- return;
- }
- e.preventDefault();
- list.dragStart(hasTouch ? e.touches[0] : e);
- };
-
- var onMoveEvent = function(e)
- {
- if (list.dragEl) {
- e.preventDefault();
- list.dragMove(hasTouch ? e.touches[0] : e);
- }
- };
-
- var onEndEvent = function(e)
- {
- if (list.dragEl) {
- e.preventDefault();
- list.dragStop(hasTouch ? e.touches[0] : e);
- }
- };
-
- if (hasTouch) {
- list.el[0].addEventListener(eStart, onStartEvent, false);
- window.addEventListener(eMove, onMoveEvent, false);
- window.addEventListener(eEnd, onEndEvent, false);
- window.addEventListener(eCancel, onEndEvent, false);
- } else {
- list.el.on(eStart, onStartEvent);
- list.w.on(eMove, onMoveEvent);
- list.w.on(eEnd, onEndEvent);
- }
-
- },
-
- serialize: function()
- {
- var data,
- depth = 0,
- list = this;
- step = function(level, depth)
- {
- var array = [ ],
- items = level.children(list.options.itemNodeName);
- items.each(function()
- {
- var li = $(this),
- item = $.extend({}, li.data()),
- sub = li.children(list.options.listNodeName);
- if (sub.length) {
- item.children = step(sub, depth + 1);
- }
- array.push(item);
- });
- return array;
- };
- data = step(list.el.find(list.options.listNodeName).first(), depth);
- return data;
- },
-
- serialise: function()
- {
- return this.serialize();
- },
-
- reset: function()
- {
- this.mouse = {
- offsetX : 0,
- offsetY : 0,
- startX : 0,
- startY : 0,
- lastX : 0,
- lastY : 0,
- nowX : 0,
- nowY : 0,
- distX : 0,
- distY : 0,
- dirAx : 0,
- dirX : 0,
- dirY : 0,
- lastDirX : 0,
- lastDirY : 0,
- distAxX : 0,
- distAxY : 0
- };
- this.moving = false;
- this.dragEl = null;
- this.dragRootEl = null;
- this.dragDepth = 0;
- this.hasNewRoot = false;
- this.pointEl = null;
- },
-
- expandItem: function(li)
- {
- li.removeClass(this.options.collapsedClass);
- li.children('[data-action="expand"]').hide();
- li.children('[data-action="collapse"]').show();
- li.children(this.options.listNodeName).show();
- },
-
- collapseItem: function(li)
- {
- var lists = li.children(this.options.listNodeName);
- if (lists.length) {
- li.addClass(this.options.collapsedClass);
- li.children('[data-action="collapse"]').hide();
- li.children('[data-action="expand"]').show();
- li.children(this.options.listNodeName).hide();
- }
- },
-
- expandAll: function()
- {
- var list = this;
- list.el.find(list.options.itemNodeName).each(function() {
- list.expandItem($(this));
- });
- },
-
- collapseAll: function()
- {
- var list = this;
- list.el.find(list.options.itemNodeName).each(function() {
- list.collapseItem($(this));
- });
- },
-
- setParent: function(li)
- {
- if (li.children(this.options.listNodeName).length) {
- li.prepend($(this.options.expandBtnHTML));
- li.prepend($(this.options.collapseBtnHTML));
- }
- li.children('[data-action="expand"]').hide();
- },
-
- unsetParent: function(li)
- {
- li.removeClass(this.options.collapsedClass);
- li.children('[data-action]').remove();
- li.children(this.options.listNodeName).remove();
- },
-
- dragStart: function(e)
- {
- var mouse = this.mouse,
- target = $(e.target),
- dragItem = target.closest(this.options.itemNodeName);
-
- this.placeEl.css('height', dragItem.height());
-
- mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
- mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
- mouse.startX = mouse.lastX = e.pageX;
- mouse.startY = mouse.lastY = e.pageY;
-
- this.dragRootEl = this.el;
-
- this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
- this.dragEl.css('width', dragItem.width());
-
- // fix for zepto.js
- //dragItem.after(this.placeEl).detach().appendTo(this.dragEl);
- dragItem.after(this.placeEl);
- dragItem[0].parentNode.removeChild(dragItem[0]);
- dragItem.appendTo(this.dragEl);
-
- $(document.body).append(this.dragEl);
- this.dragEl.css({
- 'left' : e.pageX - mouse.offsetX,
- 'top' : e.pageY - mouse.offsetY
- });
- // total depth of dragging item
- var i, depth,
- items = this.dragEl.find(this.options.itemNodeName);
- for (i = 0; i < items.length; i++) {
- depth = $(items[i]).parents(this.options.listNodeName).length;
- if (depth > this.dragDepth) {
- this.dragDepth = depth;
- }
- }
- },
-
- dragStop: function(e)
- {
- // fix for zepto.js
- //this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach());
- var el = this.dragEl.children(this.options.itemNodeName).first();
- el[0].parentNode.removeChild(el[0]);
- this.placeEl.replaceWith(el);
-
- this.dragEl.remove();
- this.el.trigger('change');
- if (this.hasNewRoot) {
- this.dragRootEl.trigger('change');
- }
- this.reset();
- },
-
- dragMove: function(e)
- {
- var list, parent, prev, next, depth,
- opt = this.options,
- mouse = this.mouse;
-
- this.dragEl.css({
- 'left' : e.pageX - mouse.offsetX,
- 'top' : e.pageY - mouse.offsetY
- });
-
- // mouse position last events
- mouse.lastX = mouse.nowX;
- mouse.lastY = mouse.nowY;
- // mouse position this events
- mouse.nowX = e.pageX;
- mouse.nowY = e.pageY;
- // distance mouse moved between events
- mouse.distX = mouse.nowX - mouse.lastX;
- mouse.distY = mouse.nowY - mouse.lastY;
- // direction mouse was moving
- mouse.lastDirX = mouse.dirX;
- mouse.lastDirY = mouse.dirY;
- // direction mouse is now moving (on both axis)
- mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
- mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
- // axis mouse is now moving on
- var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
-
- // do nothing on first move
- if (!mouse.moving) {
- mouse.dirAx = newAx;
- mouse.moving = true;
- return;
- }
-
- // calc distance moved on this axis (and direction)
- if (mouse.dirAx !== newAx) {
- mouse.distAxX = 0;
- mouse.distAxY = 0;
- } else {
- mouse.distAxX += Math.abs(mouse.distX);
- if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
- mouse.distAxX = 0;
- }
- mouse.distAxY += Math.abs(mouse.distY);
- if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
- mouse.distAxY = 0;
- }
- }
- mouse.dirAx = newAx;
-
- /**
- * move horizontal
- */
- if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
- // reset move distance on x-axis for new phase
- mouse.distAxX = 0;
- prev = this.placeEl.prev(opt.itemNodeName);
- // increase horizontal level if previous sibling exists and is not collapsed
- if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
- // cannot increase level when item above is collapsed
- list = prev.find(opt.listNodeName).last();
- // check if depth limit has reached
- depth = this.placeEl.parents(opt.listNodeName).length;
- if (depth + this.dragDepth <= opt.maxDepth) {
- // create new sub-level if one doesn't exist
- if (!list.length) {
- list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
- list.append(this.placeEl);
- prev.append(list);
- this.setParent(prev);
- } else {
- // else append to next level up
- list = prev.children(opt.listNodeName).last();
- list.append(this.placeEl);
- }
- }
- }
- // decrease horizontal level
- if (mouse.distX < 0) {
- // we can't decrease a level if an item preceeds the current one
- next = this.placeEl.next(opt.itemNodeName);
- if (!next.length) {
- parent = this.placeEl.parent();
- this.placeEl.closest(opt.itemNodeName).after(this.placeEl);
- if (!parent.children().length) {
- this.unsetParent(parent.parent());
- }
- }
- }
- }
-
- var isEmpty = false;
-
- // find list item under cursor
- if (!hasPointerEvents) {
- this.dragEl[0].style.visibility = 'hidden';
- }
- this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));
- if (!hasPointerEvents) {
- this.dragEl[0].style.visibility = 'visible';
- }
- if (this.pointEl.hasClass(opt.handleClass)) {
- this.pointEl = this.pointEl.parent(opt.itemNodeName);
- }
- if (this.pointEl.hasClass(opt.emptyClass)) {
- isEmpty = true;
- }
- else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
- return;
- }
-
- // find parent list of item under cursor
- var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
- isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
-
- /**
- * move vertical
- */
- if (!mouse.dirAx || isNewRoot || isEmpty) {
- // check if groups match if dragging over new root
- if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
- return;
- }
- // check depth limit
- depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
- if (depth > opt.maxDepth) {
- return;
- }
- var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
- parent = this.placeEl.parent();
- // if empty create new list to replace empty placeholder
- if (isEmpty) {
- list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
- list.append(this.placeEl);
- this.pointEl.replaceWith(list);
- }
- else if (before) {
- this.pointEl.before(this.placeEl);
- }
- else {
- this.pointEl.after(this.placeEl);
- }
- if (!parent.children().length) {
- this.unsetParent(parent.parent());
- }
- if (!this.dragRootEl.find(opt.itemNodeName).length) {
- this.dragRootEl.append('
');
- }
- // parent root list has changed
- if (isNewRoot) {
- this.dragRootEl = pointElRoot;
- this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
- }
- }
- }
-
- };
-
- $.fn.nestable = function(params)
- {
- var lists = this,
- retval = this;
-
- lists.each(function()
- {
- var plugin = $(this).data("nestable");
-
- if (!plugin) {
- $(this).data("nestable", new Plugin(this, params));
- $(this).data("nestable-id", new Date().getTime());
- } else {
- if (typeof params === 'string' && typeof plugin[params] === 'function') {
- retval = plugin[params]();
- }
- }
- });
-
- return retval || lists;
- };
-
-})(window.jQuery || window.Zepto, window, document);
diff --git a/src/main/webapp/static/script/jquery.news-ticker.js b/src/main/webapp/static/script/jquery.news-ticker.js
deleted file mode 100644
index f83647c..0000000
--- a/src/main/webapp/static/script/jquery.news-ticker.js
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- jQuery News Ticker is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, version 2 of the License.
-
- jQuery News Ticker is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with jQuery News Ticker. If not, see .
- */
-(function($){
- $.fn.ticker = function(options) {
- // Extend our default options with those provided.
- // Note that the first arg to extend is an empty object -
- // this is to keep from overriding our "defaults" object.
- var opts = $.extend({}, $.fn.ticker.defaults, options);
-
- // check that the passed element is actually in the DOM
- if ($(this).length == 0) {
- if (window.console && window.console.log) {
- window.console.log('Element does not exist in DOM!');
- }
- else {
- alert('Element does not exist in DOM!');
- }
- return false;
- }
-
- /* Get the id of the UL to get our news content from */
- var newsID = '#' + $(this).attr('id');
-
- /* Get the tag type - we will check this later to makde sure it is a UL tag */
- var tagType = $(this).get(0).tagName;
-
- return this.each(function() {
- // get a unique id for this ticker
- var uniqID = getUniqID();
-
- /* Internal vars */
- var settings = {
- position: 0,
- time: 0,
- distance: 0,
- newsArr: {},
- play: true,
- paused: false,
- contentLoaded: false,
- dom: {
- contentID: '#ticker-content-' + uniqID,
- titleID: '#ticker-title-' + uniqID,
- titleElem: '#ticker-title-' + uniqID + ' SPAN',
- tickerID : '#ticker-' + uniqID,
- wrapperID: '#ticker-wrapper-' + uniqID,
- revealID: '#ticker-swipe-' + uniqID,
- revealElem: '#ticker-swipe-' + uniqID + ' SPAN',
- controlsID: '#ticker-controls-' + uniqID,
- prevID: '#prev-' + uniqID,
- nextID: '#next-' + uniqID,
- playPauseID: '#play-pause-' + uniqID
- }
- };
-
- // if we are not using a UL, display an error message and stop any further execution
- if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {
- debugError('Cannot use <' + tagType.toLowerCase() + '> type of element for this plugin - must of type or ');
- return false;
- }
-
- // set the ticker direction
- opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';
-
- // lets go...
- initialisePage();
- /* Function to get the size of an Object*/
- function countSize(obj) {
- var size = 0, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) size++;
- }
- return size;
- };
-
- function getUniqID() {
- var newDate = new Date;
- return newDate.getTime();
- }
-
- /* Function for handling debug and error messages */
- function debugError(obj) {
- if (opts.debugMode) {
- if (window.console && window.console.log) {
- window.console.log(obj);
- }
- else {
- alert(obj);
- }
- }
- }
-
- /* Function to setup the page */
- function initialisePage() {
- // process the content for this ticker
- processContent();
-
- // add our HTML structure for the ticker to the DOM
- $(newsID).wrap('
');
-
- // remove any current content inside this ticker
- $(settings.dom.wrapperID).children().remove();
-
- $(settings.dom.wrapperID).append('');
- $(settings.dom.wrapperID).removeClass('no-js').addClass('ticker-wrapper has-js ' + opts.direction);
- // hide the ticker
- $(settings.dom.tickerElem + ',' + settings.dom.contentID).hide();
- // add the controls to the DOM if required
- if (opts.controls) {
- // add related events - set functions to run on given event
- $(settings.dom.controlsID).live('click mouseover mousedown mouseout mouseup', function (e) {
- var button = e.target.id;
- if (e.type == 'click') {
- switch (button) {
- case settings.dom.prevID.replace('#', ''):
- // show previous item
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- manualChangeContent('prev');
- break;
- case settings.dom.nextID.replace('#', ''):
- // show next item
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- manualChangeContent('next');
- break;
- case settings.dom.playPauseID.replace('#', ''):
- // play or pause the ticker
- if (settings.play == true) {
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- pauseTicker();
- }
- else {
- settings.paused = false;
- $(settings.dom.playPauseID).removeClass('paused');
- restartTicker();
- }
- break;
- }
- }
- else if (e.type == 'mouseover' && $('#' + button).hasClass('controls')) {
- $('#' + button).addClass('over');
- }
- else if (e.type == 'mousedown' && $('#' + button).hasClass('controls')) {
- $('#' + button).addClass('down');
- }
- else if (e.type == 'mouseup' && $('#' + button).hasClass('controls')) {
- $('#' + button).removeClass('down');
- }
- else if (e.type == 'mouseout' && $('#' + button).hasClass('controls')) {
- $('#' + button).removeClass('over');
- }
- });
- // add controls HTML to DOM
- $(settings.dom.wrapperID).append('');
- }
- if (opts.displayType != 'fade') {
- // add mouse over on the content
- $(settings.dom.contentID).mouseover(function () {
- if (settings.paused == false) {
- pauseTicker();
- }
- }).mouseout(function () {
- if (settings.paused == false) {
- restartTicker();
- }
- });
- }
- // we may have to wait for the ajax call to finish here
- if (!opts.ajaxFeed) {
- setupContentAndTriggerDisplay();
- }
- }
-
- /* Start to process the content for this ticker */
- function processContent() {
- // check to see if we need to load content
- if (settings.contentLoaded == false) {
- // construct content
- if (opts.ajaxFeed) {
- if (opts.feedType == 'xml') {
- $.ajax({
- url: opts.feedUrl,
- cache: false,
- dataType: opts.feedType,
- async: true,
- success: function(data){
- count = 0;
- // get the 'root' node
- for (var a = 0; a < data.childNodes.length; a++) {
- if (data.childNodes[a].nodeName == 'rss') {
- xmlContent = data.childNodes[a];
- }
- }
- // find the channel node
- for (var i = 0; i < xmlContent.childNodes.length; i++) {
- if (xmlContent.childNodes[i].nodeName == 'channel') {
- xmlChannel = xmlContent.childNodes[i];
- }
- }
- // for each item create a link and add the article title as the link text
- for (var x = 0; x < xmlChannel.childNodes.length; x++) {
- if (xmlChannel.childNodes[x].nodeName == 'item') {
- xmlItems = xmlChannel.childNodes[x];
- var title, link = false;
- for (var y = 0; y < xmlItems.childNodes.length; y++) {
- if (xmlItems.childNodes[y].nodeName == 'title') {
- title = xmlItems.childNodes[y].lastChild.nodeValue;
- }
- else if (xmlItems.childNodes[y].nodeName == 'link') {
- link = xmlItems.childNodes[y].lastChild.nodeValue;
- }
- if ((title !== false && title != '') && link !== false) {
- settings.newsArr['item-' + count] = { type: opts.titleText, content: '' + title + ' ' }; count++; title = false; link = false;
- }
- }
- }
- }
- // quick check here to see if we actually have any content - log error if not
- if (countSize(settings.newsArr) < 1) {
- debugError('Couldn\'t find any content from the XML feed for the ticker to use!');
- return false;
- }
- settings.contentLoaded = true;
- setupContentAndTriggerDisplay();
- }
- });
- }
- else {
- debugError('Code Me!');
- }
- }
- else if (opts.htmlFeed) {
- if($(newsID + ' LI').length > 0) {
- $(newsID + ' LI').each(function (i) {
- // maybe this could be one whole object and not an array of objects?
- settings.newsArr['item-' + i] = { type: opts.titleText, content: $(this).html()};
- });
- }
- else {
- debugError('Couldn\'t find HTML any content for the ticker to use!');
- return false;
- }
- }
- else {
- debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');
- return false;
- }
- }
- }
-
- function setupContentAndTriggerDisplay() {
-
- settings.contentLoaded = true;
-
- // update the ticker content with the correct item
- // insert news content into DOM
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
-
- // set the next content item to be used - loop round if we are at the end of the content
- if (settings.position == (countSize(settings.newsArr) -1)) {
- settings.position = 0;
- }
- else {
- settings.position++;
- }
-
- // get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)
- distance = $(settings.dom.contentID).width();
- time = distance / opts.speed;
-
- // start the ticker animation
- revealContent();
- }
-
- // slide back cover or fade in content
- function revealContent() {
- $(settings.dom.contentID).css('opacity', '1');
- if(settings.play) {
- // get the width of the title element to offset the content and reveal
- var offset = $(settings.dom.titleID).width() + 20;
-
- $(settings.dom.revealID).css(opts.direction, offset + 'px');
- // show the reveal element and start the animation
- if (opts.displayType == 'fade') {
- // fade in effect ticker
- $(settings.dom.revealID).hide(0, function () {
- $(settings.dom.contentID).css(opts.direction, offset + 'px').fadeIn(opts.fadeInSpeed, postReveal);
- });
- }
- else if (opts.displayType == 'scroll') {
- // to code
- }
- else {
- // default bbc scroll effect
- $(settings.dom.revealElem).show(0, function () {
- $(settings.dom.contentID).css(opts.direction, offset + 'px').show();
- // set our animation direction
- contentWindowSize = $(settings.dom.tickerID).width() - $(settings.dom.titleID).width() -20;
- if($(settings.dom.contentID).width() <= contentWindowSize) {
- animationAction = opts.direction == 'right' ? { marginRight: distance + 'px'} : { marginLeft: distance + 'px' };
- $(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);
-
- } else {
- delay_scroll = contentWindowSize / opts.speed;
- time_scroll = ($(settings.dom.contentID).width() / opts.speed) - delay_scroll;
-
- animationAction = opts.direction == 'right' ? { marginRight: (contentWindowSize-7) + 'px'} : { marginLeft: (contentWindowSize-7) + 'px' };
- $(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, delay_scroll, 'linear');
-
- //don't forget to add position: relative;z-index: 10; to your .ticker-title class
- scrollSize = $(settings.dom.titleID).width() + 20 - $(settings.dom.contentID).width() + contentWindowSize;
- animationAction_scroll = opts.direction == 'right' ? { right: scrollSize + 'px'} : { left: scrollSize + 'px' };
- $(settings.dom.contentID).delay(delay_scroll).animate(animationAction_scroll, time_scroll, 'linear',postReveal);
- }
- });
- }
- }
- else {
- return false;
- }
- };
-
- // here we hide the current content and reset the ticker elements to a default state ready for the next ticker item
- function postReveal() {
- if(settings.play) {
- // we have to separately fade the content out here to get around an IE bug - needs further investigation
- $(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);
- // deal with the rest of the content, prepare the DOM and trigger the next ticker
- if (opts.displayType == 'fade') {
- $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
- $(settings.dom.wrapperID)
- .find(settings.dom.revealElem + ',' + settings.dom.contentID)
- .hide()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .show()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .removeAttr('style');
- setupContentAndTriggerDisplay();
- });
- }
- else {
- $(settings.dom.revealID).hide(0, function () {
- $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
- $(settings.dom.wrapperID)
- .find(settings.dom.revealElem + ',' + settings.dom.contentID)
- .hide()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .show()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .removeAttr('style');
- setupContentAndTriggerDisplay();
- });
- });
- }
- }
- else {
- $(settings.dom.revealElem).hide();
- }
- }
-
- // pause ticker
- function pauseTicker() {
- settings.play = false;
- // stop animation and show content - must pass "true, true" to the stop function, or we can get some funky behaviour
- $(settings.dom.tickerID + ',' + settings.dom.revealID + ',' + settings.dom.titleID + ',' + settings.dom.titleElem + ',' + settings.dom.revealElem + ',' + settings.dom.contentID).stop(true, true);
- $(settings.dom.revealID + ',' + settings.dom.revealElem).hide();
- $(settings.dom.wrapperID)
- .find(settings.dom.titleID + ',' + settings.dom.titleElem).show()
- .end().find(settings.dom.contentID).show();
- }
-
- // play ticker
- function restartTicker() {
- settings.play = true;
- settings.paused = false;
- // start the ticker again
- postReveal();
- }
-
- // change the content on user input
- function manualChangeContent(direction) {
- pauseTicker();
- switch (direction) {
- case 'prev':
- if (settings.position == 0) {
- settings.position = countSize(settings.newsArr) -2;
- }
- else if (settings.position == 1) {
- settings.position = countSize(settings.newsArr) -1;
- }
- else {
- settings.position = settings.position - 2;
- }
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
- break;
- case 'next':
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
- break;
- }
- // set the next content item to be used - loop round if we are at the end of the content
- if (settings.position == (countSize(settings.newsArr) -1)) {
- settings.position = 0;
- }
- else {
- settings.position++;
- }
- }
- });
- };
-
- // plugin defaults - added as a property on our plugin function
- $.fn.ticker.defaults = {
- speed: 0.10,
- ajaxFeed: false,
- feedUrl: '',
- feedType: 'xml',
- displayType: 'reveal',
- htmlFeed: true,
- debugMode: true,
- controls: false,
- titleText: '',
- direction: 'ltr',
- pauseOnItems: 3000,
- fadeInSpeed: 600,
- fadeOutSpeed: 300
- };
- $('#sample').ticker();
-})(jQuery);
\ No newline at end of file
diff --git a/src/main/webapp/static/script/jquery.slimscroll.js b/src/main/webapp/static/script/jquery.slimscroll.js
deleted file mode 100644
index 8f813ee..0000000
--- a/src/main/webapp/static/script/jquery.slimscroll.js
+++ /dev/null
@@ -1,463 +0,0 @@
-/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
- * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
- * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
- *
- * Version: 1.3.2
- *
- */
-(function($) {
-
- jQuery.fn.extend({
- slimScroll: function(options) {
-
- var defaults = {
-
- // width in pixels of the visible scroll area
- width : 'auto',
-
- // height in pixels of the visible scroll area
- height : '250px',
-
- // width in pixels of the scrollbar and rail
- size : '7px',
-
- // scrollbar color, accepts any hex/color value
- color: '#000',
-
- // scrollbar position - left/right
- position : 'right',
-
- // distance in pixels between the side edge and the scrollbar
- distance : '1px',
-
- // default scroll position on load - top / bottom / $('selector')
- start : 'top',
-
- // sets scrollbar opacity
- opacity : .4,
-
- // enables always-on mode for the scrollbar
- alwaysVisible : false,
-
- // check if we should hide the scrollbar when user is hovering over
- disableFadeOut : false,
-
- // sets visibility of the rail
- railVisible : false,
-
- // sets rail color
- railColor : '#333',
-
- // sets rail opacity
- railOpacity : .2,
-
- // whether we should use jQuery UI Draggable to enable bar dragging
- railDraggable : true,
-
- // defautlt CSS class of the slimscroll rail
- railClass : 'slimScrollRail',
-
- // defautlt CSS class of the slimscroll bar
- barClass : 'slimScrollBar',
-
- // defautlt CSS class of the slimscroll wrapper
- wrapperClass : 'slimScrollDiv',
-
- // check if mousewheel should scroll the window if we reach top/bottom
- allowPageScroll : false,
-
- // scroll amount applied to each mouse wheel step
- wheelStep : 20,
-
- // scroll amount applied when user is using gestures
- touchScrollStep : 200,
-
- // sets border radius
- borderRadius: '7px',
-
- // sets border radius of the rail
- railBorderRadius : '7px'
- };
-
- var o = $.extend(defaults, options);
-
- // do it for every element that matches selector
- this.each(function(){
-
- var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
- barHeight, percentScroll, lastScroll,
- divS = '
',
- minBarHeight = 30,
- releaseScroll = false;
-
- // used in event handlers and for better minification
- var me = $(this);
-
- // ensure we are not binding it again
- if (me.parent().hasClass(o.wrapperClass))
- {
- // start from last bar position
- var offset = me.scrollTop();
-
- // find bar and rail
- bar = me.parent().find('.' + o.barClass);
- rail = me.parent().find('.' + o.railClass);
-
- getBarHeight();
-
- // check if we should scroll existing instance
- if ($.isPlainObject(options))
- {
- // Pass height: auto to an existing slimscroll object to force a resize after contents have changed
- if ( 'height' in options && options.height == 'auto' ) {
- me.parent().css('height', 'auto');
- me.css('height', 'auto');
- var height = me.parent().parent().height();
- me.parent().css('height', height);
- me.css('height', height);
- }
-
- if ('scrollTo' in options)
- {
- // jump to a static point
- offset = parseInt(o.scrollTo);
- }
- else if ('scrollBy' in options)
- {
- // jump by value pixels
- offset += parseInt(o.scrollBy);
- }
- else if ('destroy' in options)
- {
- // remove slimscroll elements
- bar.remove();
- rail.remove();
- me.unwrap();
- return;
- }
-
- // scroll content by the given offset
- scrollContent(offset, false, true);
- }
-
- return;
- }
-
- // optionally set height to the parent's height
- o.height = (options.height == 'auto') ? me.parent().height() : options.height;
-
- // wrap content
- var wrapper = $(divS)
- .addClass(o.wrapperClass)
- .css({
- position: 'relative',
- overflow: 'hidden',
- width: o.width,
- height: o.height
- });
-
- // update style for the div
- me.css({
- overflow: 'hidden',
- width: o.width,
- height: o.height
- });
-
- // create scrollbar rail
- var rail = $(divS)
- .addClass(o.railClass)
- .css({
- width: o.size,
- height: '100%',
- position: 'absolute',
- top: 0,
- display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
- 'border-radius': o.railBorderRadius,
- background: o.railColor,
- opacity: o.railOpacity,
- zIndex: 90
- });
-
- // create scrollbar
- var bar = $(divS)
- .addClass(o.barClass)
- .css({
- background: o.color,
- width: o.size,
- position: 'absolute',
- top: 0,
- opacity: o.opacity,
- display: o.alwaysVisible ? 'block' : 'none',
- 'border-radius' : o.borderRadius,
- BorderRadius: o.borderRadius,
- MozBorderRadius: o.borderRadius,
- WebkitBorderRadius: o.borderRadius,
- zIndex: 99
- });
-
- // set position
- var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance };
- rail.css(posCss);
- bar.css(posCss);
-
- // wrap it
- me.wrap(wrapper);
-
- // append to parent div
- me.parent().append(bar);
- me.parent().append(rail);
-
- // make it draggable and no longer dependent on the jqueryUI
- if (o.railDraggable){
- bar.bind("mousedown", function(e) {
- var $doc = $(document);
- isDragg = true;
- t = parseFloat(bar.css('top'));
- pageY = e.pageY;
-
- $doc.bind("mousemove.slimscroll", function(e){
- currTop = t + e.pageY - pageY;
- bar.css('top', currTop);
- scrollContent(0, bar.position().top, false);// scroll content
- });
-
- $doc.bind("mouseup.slimscroll", function(e) {
- isDragg = false;hideBar();
- $doc.unbind('.slimscroll');
- });
- return false;
- }).bind("selectstart.slimscroll", function(e){
- e.stopPropagation();
- e.preventDefault();
- return false;
- });
- }
-
- // on rail over
- rail.hover(function(){
- showBar();
- }, function(){
- hideBar();
- });
-
- // on bar over
- bar.hover(function(){
- isOverBar = true;
- }, function(){
- isOverBar = false;
- });
-
- // show on parent mouseover
- me.hover(function(){
- isOverPanel = true;
- showBar();
- hideBar();
- }, function(){
- isOverPanel = false;
- hideBar();
- });
-
- // support for mobile
- me.bind('touchstart', function(e,b){
- if (e.originalEvent.touches.length)
- {
- // record where touch started
- touchDif = e.originalEvent.touches[0].pageY;
- }
- });
-
- me.bind('touchmove', function(e){
- // prevent scrolling the page if necessary
- if(!releaseScroll)
- {
- e.originalEvent.preventDefault();
- }
- if (e.originalEvent.touches.length)
- {
- // see how far user swiped
- var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
- // scroll content
- scrollContent(diff, true);
- touchDif = e.originalEvent.touches[0].pageY;
- }
- });
-
- // set up initial height
- getBarHeight();
-
- // check start position
- if (o.start === 'bottom')
- {
- // scroll content to bottom
- bar.css({ top: me.outerHeight() - bar.outerHeight() });
- scrollContent(0, true);
- }
- else if (o.start !== 'top')
- {
- // assume jQuery selector
- scrollContent($(o.start).position().top, null, true);
-
- // make sure bar stays hidden
- if (!o.alwaysVisible) { bar.hide(); }
- }
-
- // attach scroll events
- attachWheel();
-
- function _onWheel(e)
- {
- // use mouse wheel only when mouse is over
- if (!isOverPanel) { return; }
-
- var e = e || window.event;
-
- var delta = 0;
- if (e.wheelDelta) { delta = -e.wheelDelta/120; }
- if (e.detail) { delta = e.detail / 3; }
-
- var target = e.target || e.srcTarget || e.srcElement;
- if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
- // scroll content
- scrollContent(delta, true);
- }
-
- // stop window scroll
- if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
- if (!releaseScroll) { e.returnValue = false; }
- }
-
- function scrollContent(y, isWheel, isJump)
- {
- releaseScroll = false;
- var delta = y;
- var maxTop = me.outerHeight() - bar.outerHeight();
-
- if (isWheel)
- {
- // move bar with mouse wheel
- delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
-
- // move bar, make sure it doesn't go out
- delta = Math.min(Math.max(delta, 0), maxTop);
-
- // if scrolling down, make sure a fractional change to the
- // scroll position isn't rounded away when the scrollbar's CSS is set
- // this flooring of delta would happened automatically when
- // bar.css is set below, but we floor here for clarity
- delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
-
- // scroll the scrollbar
- bar.css({ top: delta + 'px' });
- }
-
- // calculate actual scroll amount
- percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
- delta = percentScroll * (me[0].scrollHeight - me.outerHeight());
-
- if (isJump)
- {
- delta = y;
- var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
- offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
- bar.css({ top: offsetTop + 'px' });
- }
-
- // scroll content
- me.scrollTop(delta);
-
- // fire scrolling event
- me.trigger('slimscrolling', ~~delta);
-
- // ensure bar is visible
- showBar();
-
- // trigger hide when scroll is stopped
- hideBar();
- }
-
- function attachWheel()
- {
- if (window.addEventListener)
- {
- this.addEventListener('DOMMouseScroll', _onWheel, false );
- this.addEventListener('mousewheel', _onWheel, false );
- }
- else
- {
- document.attachEvent("onmousewheel", _onWheel)
- }
- }
-
- function getBarHeight()
- {
- // calculate scrollbar height and make sure it is not too small
- barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
- bar.css({ height: barHeight + 'px' });
-
- // hide scrollbar if content is not long enough
- var display = barHeight == me.outerHeight() ? 'none' : 'block';
- bar.css({ display: display });
- }
-
- function showBar()
- {
- // recalculate bar height
- getBarHeight();
- clearTimeout(queueHide);
-
- // when bar reached top or bottom
- if (percentScroll == ~~percentScroll)
- {
- //release wheel
- releaseScroll = o.allowPageScroll;
-
- // publish approporiate event
- if (lastScroll != percentScroll)
- {
- var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
- me.trigger('slimscroll', msg);
- }
- }
- else
- {
- releaseScroll = false;
- }
- lastScroll = percentScroll;
-
- // show only when required
- if(barHeight >= me.outerHeight()) {
- //allow window scroll
- releaseScroll = true;
- return;
- }
- bar.stop(true,true).fadeIn('fast');
- if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); }
- }
-
- function hideBar()
- {
- // only hide when options allow it
- if (!o.alwaysVisible)
- {
- queueHide = setTimeout(function(){
- if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
- {
- bar.fadeOut('slow');
- rail.fadeOut('slow');
- }
- }, 1000);
- }
- }
-
- });
-
- // maintain chainability
- return this;
- }
- });
-
- jQuery.fn.extend({
- slimscroll: jQuery.fn.slimScroll
- });
-
-})(jQuery);
diff --git a/src/main/webapp/static/script/main.js b/src/main/webapp/static/script/main.js
deleted file mode 100644
index 6957683..0000000
--- a/src/main/webapp/static/script/main.js
+++ /dev/null
@@ -1,340 +0,0 @@
-$(function () {
- //BEGIN MENU SIDEBAR
- $('#sidebar').css('min-height', '100%');
- $('#side-menu').metisMenu();
-
- $(window).bind("load resize", function () {
- if ($(this).width() < 768) {
- $('div.sidebar-collapse').addClass('collapse');
- } else {
- $('div.sidebar-collapse').removeClass('collapse');
- $('div.sidebar-collapse').css('height', 'auto');
- }
- if($('body').hasClass('sidebar-icons')){
- $('#menu-toggle').hide();
- } else{
- $('#menu-toggle').show();
- }
- });
- //END MENU SIDEBAR
-
- //BEGIN TOPBAR DROPDOWN
- $('.dropdown-slimscroll').slimScroll({
- "height": '250px',
- "wheelStep": 5
- });
- //END TOPBAR DROPDOWN
-
- //BEGIN CHECKBOX & RADIO
- if($('#demo-checkbox-radio').length <= 0){
- $('input[type="checkbox"]:not(".switch")').iCheck({
- checkboxClass: 'icheckbox_minimal-grey',
- increaseArea: '20%' // optional
- });
- $('input[type="radio"]:not(".switch")').iCheck({
- radioClass: 'iradio_minimal-grey',
- increaseArea: '20%' // optional
- });
- }
- //END CHECKBOX & RADIO
-
- //BEGIN TOOTLIP
- $("[data-toggle='tooltip'], [data-hover='tooltip']").tooltip();
- //END TOOLTIP
-
- //BEGIN POPOVER
- $("[data-toggle='popover'], [data-hover='popover']").popover();
- //END POPOVER
-
- //BEGIN THEME SETTING
- $('#theme-setting > a.btn-theme-setting').click(function(){
- if($('#theme-setting').css('right') < '0'){
- $('#theme-setting').css('right', '0');
- } else {
- $('#theme-setting').css('right', '-250px');
- }
- });
-
- // Begin Change Theme Color
- var list_style = $('#theme-setting > .content-theme-setting > select#list-style');
- var list_color = $('#theme-setting > .content-theme-setting > ul#list-color > li');
- // FUNCTION CHANGE URL STYLE ON HEAD TAG
- var setTheme = function (style, color) {
- $.cookie('style',style);
- $.cookie('color',color);
- $('#theme-change').attr('href', 'css/themes/'+ style + '/' + color + '.css');
- }
- // INITIALIZE THEME FROM COOKIE
- // HAVE TO SET VALUE FOR STYLE&COLOR BEFORE AND AFTER ACTIVE THEME
- if ($.cookie('style')) {
- list_style.find('option').each(function(){
- if($(this).attr('value') == $.cookie('style')) {
- $(this).attr('selected', 'selected');
- }
- });
- list_color.removeClass("active");
- list_color.each(function(){
- if($(this).attr('data-color') == $.cookie('color')){
- $(this).addClass('active');
- }
- });
- setTheme($.cookie('style'), $.cookie('color'));
- };
- // SELECT EVENT
- list_style.on('change', function() {
- list_color.each(function() {
- if($(this).hasClass('active')){
- color_active = $(this).attr('data-color');
- }
- });
- setTheme($(this).val(), color_active);
- });
- // LI CLICK EVENT
- list_color.on('click', function() {
- list_color.removeClass('active');
- $(this).addClass('active');
- setTheme(list_style.val(), $(this).attr('data-color'));
- });
- // End Change Theme Color
- //END THEME SETTING
-
- //BEGIN FULL SCREEN
- $('.btn-fullscreen').click(function() {
-
- if (!document.fullscreenElement && // alternative standard method
- !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) { // current working methods
- if (document.documentElement.requestFullscreen) {
- document.documentElement.requestFullscreen();
- } else if (document.documentElement.msRequestFullscreen) {
- document.documentElement.msRequestFullscreen();
- } else if (document.documentElement.mozRequestFullScreen) {
- document.documentElement.mozRequestFullScreen();
- } else if (document.documentElement.webkitRequestFullscreen) {
- document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
- }
- } else {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.msExitFullscreen) {
- document.msExitFullscreen();
- } else if (document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) {
- document.webkitExitFullscreen();
- }
- }
- });
- //END FULL SCREEN
-
- // BEGIN FORM CHAT
- $('.btn-chat').click(function () {
- if($('#chat-box').is(':visible')){
- $('#chat-form').toggle('slide', {
- direction: 'right'
- }, 500);
- $('#chat-box').hide();
- } else{
- $('#chat-form').toggle('slide', {
- direction: 'right'
- }, 500);
- }
- });
- $('.chat-box-close').click(function(){
- $('#chat-box').hide();
- $('#chat-form .chat-group a').removeClass('active');
- });
- $('.chat-form-close').click(function(){
- $('#chat-form').toggle('slide', {
- direction: 'right'
- }, 500);
- $('#chat-box').hide();
- });
-
- $('#chat-form .chat-group a').unbind('*').click(function(){
- $('#chat-box').hide();
- $('#chat-form .chat-group a').removeClass('active');
- $(this).addClass('active');
- var strUserName = $('> small', this).text();
- $('.display-name', '#chat-box').html(strUserName);
- var userStatus = $(this).find('span.user-status').attr('class');
- $('#chat-box > .chat-box-header > span.user-status').removeClass().addClass(userStatus);
- var chatBoxStatus = $('span.user-status', '#chat-box');
- var chatBoxStatusShow = $('#chat-box > .chat-box-header > small');
- if(chatBoxStatus.hasClass('is-online')){
- chatBoxStatusShow.html('Online');
- } else if(chatBoxStatus.hasClass('is-offline')){
- chatBoxStatusShow.html('Offline');
- } else if(chatBoxStatus.hasClass('is-busy')){
- chatBoxStatusShow.html('Busy');
- } else if(chatBoxStatus.hasClass('is-idle')){
- chatBoxStatusShow.html('Idle');
- }
-
-
- var offset = $(this).offset();
- var h_main = $('#chat-form').height();
- var h_title = $("#chat-box > .chat-box-header").height();
- var top = ($('#chat-box').is(':visible') ? (offset.top - h_title - 40) : (offset.top + h_title - 20));
-
- if((top + $('#chat-box').height()) > h_main){
- top = h_main - $('#chat-box').height();
- }
-
- $('#chat-box').css({'top': top});
-
- if(!$('#chat-box').is(':visible')){
- $('#chat-box').toggle('slide',{
- direction: 'right'
- }, 500);
- }
- // FOCUS INPUT TExT WHEN CLICK
- $('ul.chat-box-body').scrollTop(500);
- $("#chat-box .chat-textarea input").focus();
- });
- // Add content to form
- $('.chat-textarea input').on("keypress", function(e){
-
- var $obj = $(this);
- var $me = $obj.parent().parent().find('ul.chat-box-body');
- var $my_avt = 'https://s3.amazonaws.com/uifaces/faces/twitter/kolage/128.jpg';
- var $your_avt = 'https://s3.amazonaws.com/uifaces/faces/twitter/alagoon/48.jpg';
- if (e.which == 13) {
- var $content = $obj.val();
-
- if ($content !== "") {
- var d = new Date();
- var h = d.getHours();
- var m = d.getMinutes();
- if (m < 10) m = "0" + m;
- $obj.val(""); // CLEAR TEXT ON TEXTAREA
-
- var $element = "";
- $element += "";
- $element += "";
- $element += " ";
- $element += "John Doe ";
- $element += "" + h + ":" + m + " ";
- $element += "
";
- $element = $element + "" + $content + "
";
- $element += " ";
-
- $me.append($element);
- var height = 0;
- $me.find('li').each(function(i, value){
- height += parseInt($(this).height());
- });
-
- height += '';
- //alert(height);
- $me.scrollTop(height); // add more 400px for #chat-box position
-
- // RANDOM RESPOND CHAT
-
- var $res = "";
- $res += "";
- $res += "";
- $res += " ";
- $res += "Swlabs ";
- $res += "" + h + ":" + m + " ";
- $res += "
";
- $res = $res + "" + "Yep! It's so funny :)" + "
";
- $res += " ";
- setTimeout(function(){
- $me.append($res);
- $me.scrollTop(height+100); // add more 500px for #chat-box position
- }, 1000);
- }
- }
- });
- // END FORM CHAT
-
- //BEGIN PORTLET
- $(".portlet").each(function(index, element) {
- var me = $(this);
- $(">.portlet-header>.tools>i", me).click(function(e){
- if($(this).hasClass('fa-chevron-up')){
- $(">.portlet-body", me).slideUp('fast');
- $(this).removeClass('fa-chevron-up').addClass('fa-chevron-down');
- }
- else if($(this).hasClass('fa-chevron-down')){
- $(">.portlet-body", me).slideDown('fast');
- $(this).removeClass('fa-chevron-down').addClass('fa-chevron-up');
- }
- else if($(this).hasClass('fa-cog')){
- //Show modal
- }
- else if($(this).hasClass('fa-refresh')){
- //$(">.portlet-body", me).hide();
- $(">.portlet-body", me).addClass('wait');
-
- setTimeout(function(){
- //$(">.portlet-body>div", me).show();
- $(">.portlet-body", me).removeClass('wait');
- }, 1000);
- }
- else if($(this).hasClass('fa-times')){
- me.remove();
- }
- });
- });
- //END PORTLET
-
- //BEGIN BACK TO TOP
- $(window).scroll(function(){
- if ($(this).scrollTop() < 200) {
- $('#totop') .fadeOut();
- } else {
- $('#totop') .fadeIn();
- }
- });
- $('#totop').on('click', function(){
- $('html, body').animate({scrollTop:0}, 'fast');
- return false;
- });
- //END BACK TO TOP
-
- //BEGIN CHECKBOX TABLE
- $('.checkall').on('ifChecked ifUnchecked', function(event) {
- if (event.type == 'ifChecked') {
- $(this).closest('table').find('input[type=checkbox]').iCheck('check');
- } else {
- $(this).closest('table').find('input[type=checkbox]').iCheck('uncheck');
- }
- });
- //END CHECKBOX TABLE
-
- //BEGIN JQUERY NEWS UPDATE
- $('#news-update').ticker({
- controls: false,
- titleText: ''
- });
- //END JQUERY NEWS UPDATE
-
- $('.option-demo').hover(function() {
- $(this).append(" Demo
");
- }, function() {
- $('.demo-layout').remove();
- });
- $('#header-topbar-page .demo-layout').live('click', function() {
- var HtmlOption = $(this).parent().detach();
- $('#header-topbar-option-demo').html(HtmlOption).addClass('animated flash').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
- $(this).removeClass('animated flash');
- });
- $('#header-topbar-option-demo').find('.demo-layout').remove();
- return false;
- });
- $('#title-breadcrumb-page .demo-layout').live('click', function() {
- var HtmlOption = $(this).parent().html();
- $('#title-breadcrumb-option-demo').html(HtmlOption).addClass('animated flash').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
- $(this).removeClass('animated flash');
- });
- $('#title-breadcrumb-option-demo').find('.demo-layout').remove();
- return false;
- });
- // CALL FUNCTION RESPONSIVE TABS
- fakewaffle.responsiveTabs(['xs', 'sm']);
-
-});
-
-
-
diff --git a/src/main/webapp/static/script/modernizr.min.js b/src/main/webapp/static/script/modernizr.min.js
deleted file mode 100644
index f65d479..0000000
--- a/src/main/webapp/static/script/modernizr.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
- * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
- */
-;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML=" ",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;fb;b++)if(b in this&&this[b]===a)return b;return-1};for(t={catchupTime:500,initialRate:.03,minTime:500,ghostTime:500,maxProgressPerFrame:10,easeFactor:1.25,startOnPageLoad:!0,restartOnPushState:!0,restartOnRequestAfter:500,target:"body",elements:{checkInterval:100,selectors:["body"]},eventLag:{minSamples:10,sampleCount:3,lagThreshold:3},ajax:{trackMethods:["GET"],trackWebSockets:!1}},B=function(){var a;return null!=(a="undefined"!=typeof performance&&null!==performance?"function"==typeof performance.now?performance.now():void 0:void 0)?a:+new Date},D=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,s=window.cancelAnimationFrame||window.mozCancelAnimationFrame,null==D&&(D=function(a){return setTimeout(a,50)},s=function(a){return clearTimeout(a)}),F=function(a){var b,c;return b=B(),(c=function(){var d;return d=B()-b,d>=33?(b=B(),a(d,function(){return D(c)})):setTimeout(c,33-d)})()},E=function(){var a,b,c;return c=arguments[0],b=arguments[1],a=3<=arguments.length?V.call(arguments,2):[],"function"==typeof c[b]?c[b].apply(c,a):c[b]},u=function(){var a,b,c,d,e,f,g;for(b=arguments[0],d=2<=arguments.length?V.call(arguments,1):[],f=0,g=d.length;g>f;f++)if(c=d[f])for(a in c)W.call(c,a)&&(e=c[a],null!=b[a]&&"object"==typeof b[a]&&null!=e&&"object"==typeof e?u(b[a],e):b[a]=e);return b},p=function(a){var b,c,d,e,f;for(c=b=0,e=0,f=a.length;f>e;e++)d=a[e],c+=Math.abs(d),b++;return c/b},w=function(a,b){var c,d,e;if(null==a&&(a="options"),null==b&&(b=!0),e=document.querySelector("[data-pace-"+a+"]")){if(c=e.getAttribute("data-pace-"+a),!b)return c;try{return JSON.parse(c)}catch(f){return d=f,"undefined"!=typeof console&&null!==console?console.error("Error parsing inline pace options",d):void 0}}},g=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];cO;O++)I=S[O],C[I]===!0&&(C[I]=t[I]);i=function(a){function b(){return T=b.__super__.constructor.apply(this,arguments)}return X(b,a),b}(Error),b=function(){function a(){this.progress=0}return a.prototype.getElement=function(){var a;if(null==this.el){if(a=document.querySelector(C.target),!a)throw new i;this.el=document.createElement("div"),this.el.className="pace pace-active",document.body.className=document.body.className.replace("pace-done",""),document.body.className+=" pace-running",this.el.innerHTML='\n
',null!=a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el)}return this.el},a.prototype.finish=function(){var a;return a=this.getElement(),a.className=a.className.replace("pace-active",""),a.className+=" pace-inactive",document.body.className=document.body.className.replace("pace-running",""),document.body.className+=" pace-done"},a.prototype.update=function(a){return this.progress=a,this.render()},a.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(a){i=a}return this.el=void 0},a.prototype.render=function(){var a,b;return null==document.querySelector(C.target)?!1:(a=this.getElement(),a.children[0].style.width=""+this.progress+"%",(!this.lastRenderedProgress||this.lastRenderedProgress|0!==this.progress|0)&&(a.children[0].setAttribute("data-progress-text",""+(0|this.progress)+"%"),this.progress>=100?b="99":(b=this.progress<10?"0":"",b+=0|this.progress),a.children[0].setAttribute("data-progress",""+b)),this.lastRenderedProgress=this.progress)},a.prototype.done=function(){return this.progress>=100},a}(),h=function(){function a(){this.bindings={}}return a.prototype.trigger=function(a,b){var c,d,e,f,g;if(null!=this.bindings[a]){for(f=this.bindings[a],g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.call(this,b));return g}},a.prototype.on=function(a,b){var c;return null==(c=this.bindings)[a]&&(c[a]=[]),this.bindings[a].push(b)},a}(),N=window.XMLHttpRequest,M=window.XDomainRequest,L=window.WebSocket,v=function(a,b){var c,d,e,f;f=[];for(d in b.prototype)try{e=b.prototype[d],null==a[d]&&"function"!=typeof e?f.push(a[d]=e):f.push(void 0)}catch(g){c=g}return f},z=[],Pace.ignore=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?V.call(arguments,1):[],z.unshift("ignore"),c=b.apply(null,a),z.shift(),c},Pace.track=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?V.call(arguments,1):[],z.unshift("track"),c=b.apply(null,a),z.shift(),c},H=function(a){var b;if(null==a&&(a="GET"),"track"===z[0])return"force";if(!z.length&&C.ajax){if("socket"===a&&C.ajax.trackWebSockets)return!0;if(b=a.toUpperCase(),Y.call(C.ajax.trackMethods,b)>=0)return!0}return!1},j=function(a){function b(){var a,c=this;b.__super__.constructor.apply(this,arguments),a=function(a){var b;return b=a.open,a.open=function(d,e){return H(d)&&c.trigger("request",{type:d,url:e,request:a}),b.apply(a,arguments)}},window.XMLHttpRequest=function(b){var c;return c=new N(b),a(c),c},v(window.XMLHttpRequest,N),null!=M&&(window.XDomainRequest=function(){var b;return b=new M,a(b),b},v(window.XDomainRequest,M)),null!=L&&C.ajax.trackWebSockets&&(window.WebSocket=function(a,b){var d;return d=new L(a,b),H("socket")&&c.trigger("request",{type:"socket",url:a,protocols:b,request:d}),d},v(window.WebSocket,L))}return X(b,a),b}(h),P=null,x=function(){return null==P&&(P=new j),P},x().on("request",function(b){var c,d,e,f;return f=b.type,e=b.request,Pace.running||C.restartOnRequestAfter===!1&&"force"!==H(f)?void 0:(d=arguments,c=C.restartOnRequestAfter||0,"boolean"==typeof c&&(c=0),setTimeout(function(){var b,c,g,h,i,j;if(b="socket"===f?e.readyState<2:0<(h=e.readyState)&&4>h){for(Pace.restart(),i=Pace.sources,j=[],c=0,g=i.length;g>c;c++){if(I=i[c],I instanceof a){I.watch.apply(I,d);break}j.push(void 0)}return j}},c))}),a=function(){function a(){var a=this;this.elements=[],x().on("request",function(){return a.watch.apply(a,arguments)})}return a.prototype.watch=function(a){var b,c,d;return d=a.type,b=a.request,c="socket"===d?new m(b):new n(b),this.elements.push(c)},a}(),n=function(){function a(a){var b,c,d,e,f,g,h=this;if(this.progress=0,null!=window.ProgressEvent)for(c=null,a.addEventListener("progress",function(a){return h.progress=a.lengthComputable?100*a.loaded/a.total:h.progress+(100-h.progress)/2}),g=["load","abort","timeout","error"],d=0,e=g.length;e>d;d++)b=g[d],a.addEventListener(b,function(){return h.progress=100});else f=a.onreadystatechange,a.onreadystatechange=function(){var b;return 0===(b=a.readyState)||4===b?h.progress=100:3===a.readyState&&(h.progress=50),"function"==typeof f?f.apply(null,arguments):void 0}}return a}(),m=function(){function a(a){var b,c,d,e,f=this;for(this.progress=0,e=["error","open"],c=0,d=e.length;d>c;c++)b=e[c],a.addEventListener(b,function(){return f.progress=100})}return a}(),d=function(){function a(a){var b,c,d,f;for(null==a&&(a={}),this.elements=[],null==a.selectors&&(a.selectors=[]),f=a.selectors,c=0,d=f.length;d>c;c++)b=f[c],this.elements.push(new e(b))}return a}(),e=function(){function a(a){this.selector=a,this.progress=0,this.check()}return a.prototype.check=function(){var a=this;return document.querySelector(this.selector)?this.done():setTimeout(function(){return a.check()},C.elements.checkInterval)},a.prototype.done=function(){return this.progress=100},a}(),c=function(){function a(){var a,b,c=this;this.progress=null!=(b=this.states[document.readyState])?b:100,a=document.onreadystatechange,document.onreadystatechange=function(){return null!=c.states[document.readyState]&&(c.progress=c.states[document.readyState]),"function"==typeof a?a.apply(null,arguments):void 0}}return a.prototype.states={loading:0,interactive:50,complete:100},a}(),f=function(){function a(){var a,b,c,d,e,f=this;this.progress=0,a=0,e=[],d=0,c=B(),b=setInterval(function(){var g;return g=B()-c-50,c=B(),e.push(g),e.length>C.eventLag.sampleCount&&e.shift(),a=p(e),++d>=C.eventLag.minSamples&&a=100&&(this.done=!0),b===this.last?this.sinceLastUpdate+=a:(this.sinceLastUpdate&&(this.rate=(b-this.last)/this.sinceLastUpdate),this.catchup=(b-this.progress)/C.catchupTime,this.sinceLastUpdate=0,this.last=b),b>this.progress&&(this.progress+=this.catchup*a),c=1-Math.pow(this.progress/100,C.easeFactor),this.progress+=c*this.rate*a,this.progress=Math.min(this.lastProgress+C.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},a}(),J=null,G=null,q=null,K=null,o=null,r=null,Pace.running=!1,y=function(){return C.restartOnPushState?Pace.restart():void 0},null!=window.history.pushState&&(R=window.history.pushState,window.history.pushState=function(){return y(),R.apply(window.history,arguments)}),null!=window.history.replaceState&&(U=window.history.replaceState,window.history.replaceState=function(){return y(),U.apply(window.history,arguments)}),k={ajax:a,elements:d,document:c,eventLag:f},(A=function(){var a,c,d,e,f,g,h,i;for(Pace.sources=J=[],g=["ajax","elements","document","eventLag"],c=0,e=g.length;e>c;c++)a=g[c],C[a]!==!1&&J.push(new k[a](C[a]));for(i=null!=(h=C.extraSources)?h:[],d=0,f=i.length;f>d;d++)I=i[d],J.push(new I(C));return Pace.bar=q=new b,G=[],K=new l})(),Pace.stop=function(){return Pace.trigger("stop"),Pace.running=!1,q.destroy(),r=!0,null!=o&&("function"==typeof s&&s(o),o=null),A()},Pace.restart=function(){return Pace.trigger("restart"),Pace.stop(),Pace.start()},Pace.go=function(){return Pace.running=!0,q.render(),r=!1,o=F(function(a,b){var c,d,e,f,g,h,i,j,k,m,n,o,p,s,t,u,v;for(j=100-q.progress,d=o=0,e=!0,h=p=0,t=J.length;t>p;h=++p)for(I=J[h],m=null!=G[h]?G[h]:G[h]=[],g=null!=(v=I.elements)?v:[I],i=s=0,u=g.length;u>s;i=++s)f=g[i],k=null!=m[i]?m[i]:m[i]=new l(f),e&=k.done,k.done||(d++,o+=k.tick(a));return c=o/d,q.update(K.tick(a,c)),n=B(),q.done()||e||r?(q.update(100),Pace.trigger("done"),setTimeout(function(){return q.finish(),Pace.running=!1,Pace.trigger("hide")},Math.max(C.ghostTime,Math.min(C.minTime,B()-n)))):b()})},Pace.start=function(a){u(C,a),Pace.running=!0;try{q.render()}catch(b){i=b}return document.querySelector(".pace")?(Pace.trigger("start"),Pace.go()):setTimeout(Pace.start,50)},"function"==typeof define&&define.amd?define(function(){return Pace}):"object"==typeof exports?module.exports=Pace:C.startOnPageLoad&&Pace.start()}).call(this);
\ No newline at end of file
diff --git a/src/main/webapp/static/script/respond.min.js b/src/main/webapp/static/script/respond.min.js
deleted file mode 100644
index e3dc2c0..0000000
--- a/src/main/webapp/static/script/respond.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
-/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
-window.matchMedia=window.matchMedia||function(a){"use strict";var c,d=a.documentElement,e=d.firstElementChild||d.firstChild,f=a.createElement("body"),g=a.createElement("div");return g.id="mq-test-1",g.style.cssText="position:absolute;top:-100em",f.style.background="none",f.appendChild(g),function(a){return g.innerHTML='',d.insertBefore(f,e),c=42===g.offsetWidth,d.removeChild(f),{matches:c,media:a}}}(document);
-
-/*! Respond.js v1.3.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
-(function(a){"use strict";function x(){u(!0)}var b={};if(a.respond=b,b.update=function(){},b.mediaQueriesSupported=a.matchMedia&&a.matchMedia("only all").matches,!b.mediaQueriesSupported){var q,r,t,c=a.document,d=c.documentElement,e=[],f=[],g=[],h={},i=30,j=c.getElementsByTagName("head")[0]||d,k=c.getElementsByTagName("base")[0],l=j.getElementsByTagName("link"),m=[],n=function(){for(var b=0;l.length>b;b++){var c=l[b],d=c.href,e=c.media,f=c.rel&&"stylesheet"===c.rel.toLowerCase();d&&f&&!h[d]&&(c.styleSheet&&c.styleSheet.rawCssText?(p(c.styleSheet.rawCssText,d,e),h[d]=!0):(!/^([a-zA-Z:]*\/\/)/.test(d)&&!k||d.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&m.push({href:d,media:e}))}o()},o=function(){if(m.length){var b=m.shift();v(b.href,function(c){p(c,b.href,b.media),h[b.href]=!0,a.setTimeout(function(){o()},0)})}},p=function(a,b,c){var d=a.match(/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi),g=d&&d.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+b+"$2$3")},i=!g&&c;b.length&&(b+="/"),i&&(g=1);for(var j=0;g>j;j++){var k,l,m,n;i?(k=c,f.push(h(a))):(k=d[j].match(/@media *([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1,f.push(RegExp.$2&&h(RegExp.$2))),m=k.split(","),n=m.length;for(var o=0;n>o;o++)l=m[o],e.push({media:l.split("(")[0].match(/(only\s+)?([a-zA-Z]+)\s?/)&&RegExp.$2||"all",rules:f.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},s=function(){var a,b=c.createElement("div"),e=c.body,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",e||(e=f=c.createElement("body"),e.style.background="none"),e.appendChild(b),d.insertBefore(e,d.firstChild),a=b.offsetWidth,f?d.removeChild(e):e.removeChild(b),a=t=parseFloat(a)},u=function(b){var h="clientWidth",k=d[h],m="CSS1Compat"===c.compatMode&&k||c.body[h]||k,n={},o=l[l.length-1],p=(new Date).getTime();if(b&&q&&i>p-q)return a.clearTimeout(r),r=a.setTimeout(u,i),void 0;q=p;for(var v in e)if(e.hasOwnProperty(v)){var w=e[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?t||s():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?t||s():1)),w.hasquery&&(z&&A||!(z||m>=x)||!(A||y>=m))||(n[w.media]||(n[w.media]=[]),n[w.media].push(f[w.rules]))}for(var C in g)g.hasOwnProperty(C)&&g[C]&&g[C].parentNode===j&&j.removeChild(g[C]);for(var D in n)if(n.hasOwnProperty(D)){var E=c.createElement("style"),F=n[D].join("\n");E.type="text/css",E.media=D,j.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(c.createTextNode(F)),g.push(E)}},v=function(a,b){var c=w();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},w=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}();n(),b.update=n,a.addEventListener?a.addEventListener("resize",x,!1):a.attachEvent&&a.attachEvent("onresize",x)}})(this);
diff --git a/src/main/webapp/static/script/responsive-tabs.js b/src/main/webapp/static/script/responsive-tabs.js
deleted file mode 100644
index 53c1d88..0000000
--- a/src/main/webapp/static/script/responsive-tabs.js
+++ /dev/null
@@ -1,146 +0,0 @@
-var fakewaffle = (function ($, fakewaffle) {
- "use strict";
-
-fakewaffle.responsiveTabs = function (collapseDisplayed) {
-
- fakewaffle.currentPosition = 'tabs';
-
- var tabGroups = $('.nav-tabs.responsive'),
- hidden = '',
- visible = '';
-
- if (collapseDisplayed === undefined) {
- collapseDisplayed = ['xs', 'sm'];
- }
-
- $.each(collapseDisplayed, function () {
- hidden += ' hidden-' + this;
- visible += ' visible-' + this;
- });
-
- $.each(tabGroups, function () {
- var $tabGroup = $(this),
- tabs = $tabGroup.find('li a'),
- collapseDiv = $("
", {
- "class" : "panel-group responsive" + visible,
- "id" : 'collapse-' + $tabGroup.attr('id')
- });
-
- $.each(tabs, function () {
- var $this = $(this),
- active = '',
- oldLinkClass = $this.attr('class') === undefined ? '' : $this.attr('class'),
- newLinkClass = 'accordion-toggle',
- oldParentClass = $this.parent().attr('class') === undefined ? '' : $this.parent().attr('class'),
- newParentClass = 'panel panel-default';
-
- if (oldLinkClass.length > 0) {
- newLinkClass += ' ' + oldLinkClass;
- };
-
- if (oldParentClass.length > 0) {
- oldParentClass = oldParentClass.replace(/\bactive\b/g, '');
- newParentClass += ' ' + oldParentClass;
- newParentClass = newParentClass.replace(/\s{2,}/g, ' ');
- newParentClass = newParentClass.replace(/^\s+|\s+$/g, '');
- };
-
- if ($this.parent().hasClass('active')) {
- active = ' in';
- }
-
- collapseDiv.append(
- $('').attr('class', newParentClass).html(
- $('
').attr('class', 'panel-heading').html(
- $('