X-Git-Url: https://git.sesse.net/?p=remoteglot;a=blobdiff_plain;f=www%2Fjs%2Fjquery.sparkline.js;h=0758e0d346436060dade33d1d956e855ae408dd5;hp=10618cde7e1af416f81975c0f41114a368f71b62;hb=ed756fd94f3bb3e155402268c562016c842c4217;hpb=548dd0edc369e924884009fcf097582e0826a860 diff --git a/www/js/jquery.sparkline.js b/www/js/jquery.sparkline.js index 10618cd..0758e0d 100644 --- a/www/js/jquery.sparkline.js +++ b/www/js/jquery.sparkline.js @@ -62,12 +62,6 @@ * By default, options should be passed in as teh second argument to the sparkline function: * $('.sparkline').sparkline([1,2,3,4], {type: 'bar'}) * -* Options can also be set by passing them on the tag itself. This feature is disabled by default though -* as there's a slight performance overhead: -* $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true}) -*

Sparkline: loading

-* Prefix all options supplied as tag attribute with "spark" (configurable by setting tagOptionPrefix) -* * Supported options: * lineColor - Color of the line used for the chart * fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart @@ -78,14 +72,7 @@ * chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax * chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied * chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied -* composite - If true then don't erase any existing chart attached to the tag, but draw -* another chart over the top - Note that width and height are ignored if an -* existing chart is detected. * tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values' -* enableTagOptions - Whether to check tags for sparkline options -* tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark' -* disableHiddenCheck - If set to true, then the plugin will assume that charts will never be drawn into a -* hidden dom element, avoding a browser reflow * disableInteraction - If set to true then all mouseover/click interaction behaviour will be disabled, * making the plugin perform much like it did in 1.x * disableTooltips - If set to true then tooltips will be disabled - Defaults to false (tooltips enabled) @@ -99,8 +86,6 @@ * tooltipFormatter - Optional callback that allows you to override the HTML displayed in the tooltip * callback is given arguments of (sparkline, options, fields) * tooltipChartTitle - If specified then the tooltip uses the string specified by this setting as a title -* tooltipFormat - A format string or SPFormat object (or an array thereof for multiple entries) -* to control the format of the tooltip * tooltipPrefix - A string to prepend to each field displayed in a tooltip * tooltipSuffix - A string to append to each field displayed in a tooltip * tooltipSkipNull - If true then null values will not have a tooltip displayed (defaults to true) @@ -119,9 +104,6 @@ * zeroColor - Color of bars with zero values * nullColor - Color of bars with null values - Defaults to omitting the bar entirely * barWidth - Width of bars in pixels -* colorMap - Optional mappnig of values to colors to override the *BarColor values above -* can be an Array of values to control the color of individual bars or a range map -* to specify colors for individual ranges of values * barSpacing - Gap between bars in pixels * zeroAxis - Centers the y-axis around zero if true * @@ -149,8 +131,8 @@ 'use strict'; var UNSET_OPTION = {}, - getDefaults, createClass, SPFormat, clipval, quartile, normalizeValue, normalizeValues, - remove, isNumber, all, sum, addCSS, ensureArray, formatNumber, RangeMap, + getDefaults, createClass, clipval, quartile, normalizeValue, normalizeValues, + remove, isNumber, all, sum, addCSS, ensureArray, formatNumber, MouseHandler, Tooltip, barHighlightMixin, bar, defaultStyles, initStyles, VShape, VCanvas_base, VCanvas_canvas, pending, shapeCount = 0; @@ -168,16 +150,12 @@ defaultPixelsPerValue: 3, width: 'auto', height: 'auto', - composite: false, tagValuesAttribute: 'values', - tagOptionsPrefix: 'spark', - enableTagOptions: false, enableHighlight: true, highlightLighten: 1.4, tooltipSkipNull: true, tooltipPrefix: '', tooltipSuffix: '', - disableHiddenCheck: false, numberFormatter: false, numberDigitGroupCount: 3, numberDigitGroupSep: ',', @@ -189,8 +167,6 @@ bar: { barColor: '#3366cc', negBarColor: '#f44', - stackedBarColor: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00', - '#dd4477', '#0099c6', '#990099'], zeroColor: undefined, nullColor: undefined, zeroAxis: true, @@ -199,8 +175,7 @@ chartRangeMax: undefined, chartRangeMin: undefined, chartRangeClip: false, - colorMap: undefined, - tooltipFormat: new SPFormat(' {{prefix}}{{value}}{{suffix}}') + tooltipFormat: '', }, }; }; @@ -257,68 +232,6 @@ return Class; }; - /** - * Wraps a format string for tooltips - * {{x}} - * {{x.2} - * {{x:months}} - */ - $.SPFormatClass = SPFormat = createClass({ - fre: /\{\{([\w.]+?)(:(.+?))?\}\}/g, - precre: /(\w+)\.(\d+)/, - - init: function (format, fclass) { - this.format = format; - this.fclass = fclass; - }, - - render: function (fieldset, lookups, options) { - var self = this, - fields = fieldset, - match, token, lookupkey, fieldvalue, prec; - return this.format.replace(this.fre, function () { - var lookup; - token = arguments[1]; - lookupkey = arguments[3]; - match = self.precre.exec(token); - if (match) { - prec = match[2]; - token = match[1]; - } else { - prec = false; - } - fieldvalue = fields[token]; - if (fieldvalue === undefined) { - return ''; - } - if (lookupkey && lookups && lookups[lookupkey]) { - lookup = lookups[lookupkey]; - if (lookup.get) { // RangeMap - return lookups[lookupkey].get(fieldvalue) || fieldvalue; - } else { - return lookups[lookupkey][fieldvalue] || fieldvalue; - } - } - if (isNumber(fieldvalue)) { - if (options.get('numberFormatter')) { - fieldvalue = options.get('numberFormatter')(fieldvalue); - } else { - fieldvalue = formatNumber(fieldvalue, prec, - options.get('numberDigitGroupCount'), - options.get('numberDigitGroupSep'), - options.get('numberDecimalMark')); - } - } - return fieldvalue; - }); - } - }); - - // convience method to avoid needing the new operator - $.spformat = function(format, fclass) { - return new SPFormat(format, fclass); - }; - clipval = function (val, min, max) { if (val < min) { return min; @@ -494,45 +407,6 @@ } }; - $.RangeMapClass = RangeMap = createClass({ - init: function (map) { - var key, range, rangelist = []; - for (key in map) { - if (map.hasOwnProperty(key) && typeof key === 'string' && key.indexOf(':') > -1) { - range = key.split(':'); - range[0] = range[0].length === 0 ? -Infinity : parseFloat(range[0]); - range[1] = range[1].length === 0 ? Infinity : parseFloat(range[1]); - range[2] = map[key]; - rangelist.push(range); - } - } - this.map = map; - this.rangelist = rangelist || false; - }, - - get: function (value) { - var rangelist = this.rangelist, - i, range, result; - if ((result = this.map[value]) !== undefined) { - return result; - } - if (rangelist) { - for (i = rangelist.length; i--;) { - range = rangelist[i]; - if (range[0] <= value && range[1] >= value) { - return range[2]; - } - } - } - return undefined; - } - }); - - // Convenience function - $.range_map = function(map) { - return new RangeMap(map); - }; - MouseHandler = createClass({ init: function (el, options) { var $el = $(el); @@ -806,7 +680,6 @@ width = options.get('width') === 'auto' ? values.length * options.get('defaultPixelsPerValue') : options.get('width'); if (options.get('height') === 'auto') { - if (!options.get('composite') || !$.data(this, '_jqs_vcanvas')) { // must be a better way to get the line height tmp = document.createElement('span'); tmp.innerHTML = 'a'; @@ -814,7 +687,6 @@ height = $(tmp).innerHeight() || $(tmp).height(); $(tmp).remove(); tmp = null; - } } else { height = options.get('height'); } @@ -824,21 +696,13 @@ if (!mhandler) { mhandler = new MouseHandler(this, options); $.data(this, '_jqs_mhandler', mhandler); - } else if (!options.get('composite')) { + } else { mhandler.reset(); } } else { mhandler = false; } - if (options.get('composite') && !$.data(this, '_jqs_vcanvas')) { - if (!$.data(this, '_jqs_errnotify')) { - alert('Attempted to attach a composite sparkline to an element with no existing sparkline'); - $.data(this, '_jqs_errnotify', true); - } - return; - } - sp = new $.fn.sparkline[options.get('type')](this, values, options, width, height); sp.render(); @@ -847,20 +711,7 @@ mhandler.registerSparkline(sp); } }; - if (($(this).html() && !options.get('disableHiddenCheck') && $(this).is(':hidden')) || !$(this).parents('body').length) { - if (!options.get('composite') && $.data(this, '_jqs_pending')) { - // remove any existing references to the element - for (i = pending.length; i; i--) { - if (pending[i - 1][0] == this) { - pending.splice(i - 1, 1); - } - } - } - pending.push([this, render]); - $.data(this, '_jqs_pending', true); - } else { - render.call(this); - } + render.call(this); }); }; @@ -872,18 +723,9 @@ var done = []; for (i = 0, pl = pending.length; i < pl; i++) { el = pending[i][0]; - if ($(el).is(':visible') && !$(el).parents().is(':hidden')) { pending[i][1].call(el); $.data(pending[i][0], '_jqs_pending', false); done.push(i); - } else if (!$(el).closest('html').length && !$.data(el, '_jqs_pending')) { - // element has been inserted and removed from the DOM - // If it was not yet inserted into the dom then the .data request - // will return true. - // removing from the dom causes the data to be removed. - $.data(pending[i][0], '_jqs_pending', false); - done.push(i); - } } for (i = done.length; i; i--) { pending.splice(done[i - 1], 1); @@ -896,62 +738,20 @@ */ $.fn.sparkline.options = createClass({ init: function (tag, userOptions) { - var extendedOptions, defaults, base, tagOptionType; + var extendedOptions, defaults, base; this.userOptions = userOptions = userOptions || {}; this.tag = tag; this.tagValCache = {}; defaults = $.fn.sparkline.defaults; base = defaults.common; - this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix); - tagOptionType = this.getTagSetting('type'); - if (tagOptionType === UNSET_OPTION) { - extendedOptions = defaults[userOptions.type || base.type]; - } else { - extendedOptions = defaults[tagOptionType]; - } + extendedOptions = defaults[userOptions.type || base.type]; this.mergedOptions = $.extend({}, base, extendedOptions, userOptions); }, - getTagSetting: function (key) { - var prefix = this.tagOptionsPrefix, - val, i, pairs, keyval; - if (prefix === false || prefix === undefined) { - return UNSET_OPTION; - } - if (this.tagValCache.hasOwnProperty(key)) { - val = this.tagValCache.key; - } else { - val = this.tag.getAttribute(prefix + key); - if (val === undefined || val === null) { - val = UNSET_OPTION; - } else if (val.substr(0, 1) === '[') { - val = val.substr(1, val.length - 2).split(','); - for (i = val.length; i--;) { - val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g, '')); - } - } else if (val.substr(0, 1) === '{') { - pairs = val.substr(1, val.length - 2).split(','); - val = {}; - for (i = pairs.length; i--;) { - keyval = pairs[i].split(':', 2); - val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, '')); - } - } else { - val = normalizeValue(val); - } - this.tagValCache.key = val; - } - return val; - }, - get: function (key, defaultval) { - var tagOption = this.getTagSetting(key), - result; - if (tagOption !== UNSET_OPTION) { - return tagOption; - } + var result; return (result = this.mergedOptions[key]) === undefined ? defaultval : result; } }); @@ -975,7 +775,7 @@ */ initTarget: function () { var interactive = !this.options.get('disableInteraction'); - if (!(this.target = this.$el.simpledraw(this.width, this.height, this.options.get('composite'), interactive))) { + if (!(this.target = this.$el.simpledraw(this.width, this.height, false, interactive))) { this.disabled = true; } else { this.canvasWidth = this.target.pixelWidth; @@ -1094,9 +894,6 @@ fieldlen = fields.length; for (i = 0; i < formatlen; i++) { format = formats[i]; - if (typeof format === 'string') { - format = new SPFormat(format); - } fclass = format.fclass || 'jqsfield'; for (j = 0; j < fieldlen; j++) { if (!fields[j].isNull || !options.get('tooltipSkipNull')) { @@ -1207,35 +1004,11 @@ chartRangeMin = options.get('chartRangeMin'), chartRangeMax = options.get('chartRangeMax'), chartRangeClip = options.get('chartRangeClip'), - stackMin = Infinity, - stackMax = -Infinity, - isStackString, groupMin, groupMax, stackRanges, + groupMin, groupMax, numValues, i, vlen, range, zeroAxis, xaxisOffset, min, max, clipMin, clipMax, - stacked, vlist, j, slen, svals, val, yoffset, yMaxCalc, canvasHeightEf; + vlist, j, slen, svals, val, yoffset, yMaxCalc, canvasHeightEf; bar._super.init.call(this, el, values, options, width, height); - // scan values to determine whether to stack bars - for (i = 0, vlen = values.length; i < vlen; i++) { - val = values[i]; - isStackString = typeof(val) === 'string' && val.indexOf(':') > -1; - if (isStackString || $.isArray(val)) { - stacked = true; - if (isStackString) { - val = values[i] = normalizeValues(val.split(':')); - } - val = remove(val, null); // min/max will treat null as zero - groupMin = Math.min.apply(Math, val); - groupMax = Math.max.apply(Math, val); - if (groupMin < stackMin) { - stackMin = groupMin; - } - if (groupMax > stackMax) { - stackMax = groupMax; - } - } - } - - this.stacked = stacked; this.regionShapes = {}; this.barWidth = barWidth; this.barSpacing = barSpacing; @@ -1250,45 +1023,15 @@ } numValues = []; - stackRanges = stacked ? [] : numValues; - var stackTotals = []; - var stackRangesNeg = []; for (i = 0, vlen = values.length; i < vlen; i++) { - if (stacked) { - vlist = values[i]; - values[i] = svals = []; - stackTotals[i] = 0; - stackRanges[i] = stackRangesNeg[i] = 0; - for (j = 0, slen = vlist.length; j < slen; j++) { - val = svals[j] = chartRangeClip ? clipval(vlist[j], clipMin, clipMax) : vlist[j]; - if (val !== null) { - if (val > 0) { - stackTotals[i] += val; - } - if (stackMin < 0 && stackMax > 0) { - if (val < 0) { - stackRangesNeg[i] += Math.abs(val); - } else { - stackRanges[i] += val; - } - } else { - stackRanges[i] += Math.abs(val - (val < 0 ? stackMax : stackMin)); - } - numValues.push(val); - } - } - } else { val = chartRangeClip ? clipval(values[i], clipMin, clipMax) : values[i]; val = values[i] = normalizeValue(val); if (val !== null) { numValues.push(val); } - } } this.max = max = Math.max.apply(Math, numValues); this.min = min = Math.min.apply(Math, numValues); - this.stackMax = stackMax = stacked ? Math.max.apply(Math, stackTotals) : max; - this.stackMin = stackMin = stacked ? Math.min.apply(Math, numValues) : min; if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < min)) { min = options.get('chartRangeMin'); @@ -1309,14 +1052,14 @@ } this.xaxisOffset = xaxisOffset; - range = stacked ? (Math.max.apply(Math, stackRanges) + Math.max.apply(Math, stackRangesNeg)) : max - min; + range = max - min; // as we plot zero/min values a single pixel line, we add a pixel to all other // values - Reduce the effective canvas size to suit this.canvasHeightEf = (zeroAxis && min < 0) ? this.canvasHeight - 2 : this.canvasHeight - 1; if (min < xaxisOffset) { - yMaxCalc = (stacked && max >= 0) ? stackMax : max; + yMaxCalc = max; yoffset = (yMaxCalc - xaxisOffset) / range * this.canvasHeight; if (yoffset !== Math.ceil(yoffset)) { this.canvasHeightEf -= 2; @@ -1327,17 +1070,6 @@ } this.yoffset = yoffset; - if ($.isArray(options.get('colorMap'))) { - this.colorMapByIndex = options.get('colorMap'); - this.colorMapByValue = null; - } else { - this.colorMapByIndex = null; - this.colorMapByValue = options.get('colorMap'); - if (this.colorMapByValue && this.colorMapByValue.get === undefined) { - this.colorMapByValue = new RangeMap(this.colorMapByValue); - } - } - this.range = range; }, @@ -1364,24 +1096,13 @@ }, calcColor: function (stacknum, value, valuenum) { - var colorMapByIndex = this.colorMapByIndex, - colorMapByValue = this.colorMapByValue, - options = this.options, - color, newColor; - if (this.stacked) { - color = options.get('stackedBarColor'); - } else { + var color, newColor, + options = this.options; color = (value < 0) ? options.get('negBarColor') : options.get('barColor'); - } if (value === 0 && options.get('zeroColor') !== undefined) { color = options.get('zeroColor'); } - if (colorMapByValue && (newColor = colorMapByValue.get(value))) { - color = newColor; - } else if (colorMapByIndex && colorMapByIndex.length > valuenum) { - color = colorMapByIndex[valuenum]; - } - return $.isArray(color) ? color[stacknum % color.length] : color; + return color; }, /** @@ -1393,7 +1114,6 @@ xaxisOffset = this.xaxisOffset, result = [], range = this.range, - stacked = this.stacked, target = this.target, x = valuenum * this.totalBarWidth, canvasHeightEf = this.canvasHeightEf, @@ -1419,13 +1139,6 @@ for (i = 0; i < valcount; i++) { val = vals[i]; - if (stacked && val === xaxisOffset) { - if (!allMin || minPlotted) { - continue; - } - minPlotted = true; - } - if (range > 0) { height = Math.floor(canvasHeightEf * ((Math.abs(val - xaxisOffset) / range))) + 1; } else { @@ -1492,14 +1205,6 @@ return this._genShape('Shape', [path, lineColor, fillColor, lineWidth]); }, - drawCircle: function (x, y, radius, lineColor, fillColor, lineWidth) { - return this._genShape('Circle', [x, y, radius, lineColor, fillColor, lineWidth]); - }, - - drawPieSlice: function (x, y, radius, startAngle, endAngle, lineColor, fillColor) { - return this._genShape('PieSlice', [x, y, radius, startAngle, endAngle, lineColor, fillColor]); - }, - drawRect: function (x, y, width, height, lineColor, fillColor) { return this._genShape('Rect', [x, y, width, height, lineColor, fillColor]); }, @@ -1658,41 +1363,6 @@ } }, - _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) { - var context = this._getContext(lineColor, fillColor, lineWidth); - context.beginPath(); - context.arc(x, y, radius, 0, 2 * Math.PI, false); - if (this.targetX !== undefined && this.targetY !== undefined && - context.isPointInPath(this.targetX, this.targetY)) { - this.currentTargetShapeId = shapeid; - } - if (lineColor !== undefined) { - context.stroke(); - } - if (fillColor !== undefined) { - context.fill(); - } - }, - - _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) { - var context = this._getContext(lineColor, fillColor); - context.beginPath(); - context.moveTo(x, y); - context.arc(x, y, radius, startAngle, endAngle, false); - context.lineTo(x, y); - context.closePath(); - if (lineColor !== undefined) { - context.stroke(); - } - if (fillColor) { - context.fill(); - } - if (this.targetX !== undefined && this.targetY !== undefined && - context.isPointInPath(this.targetX, this.targetY)) { - this.currentTargetShapeId = shapeid; - } - }, - _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) { return this._drawShape(shapeid, [[x, y], [x + width, y], [x + width, y + height], [x, y + height], [x, y]], lineColor, fillColor); },