initStyles = function() { addCSS(defaultStyles); }; $(initStyles); pending = []; $.fn.sparkline = function (userValues, userOptions) { return this.each(function () { var options = new $.fn.sparkline.options(this, userOptions), $this = $(this), render, i; render = function () { var values, width, height, tmp, mhandler, sp, vals; if (userValues === 'html' || userValues === undefined) { vals = this.getAttribute(options.get('tagValuesAttribute')); if (vals === undefined || vals === null) { vals = $this.html(); } values = vals.replace(/(^\s*\s*$)|\s+/g, '').split(','); } else { values = userValues; } 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'; $this.html(tmp); height = $(tmp).innerHeight() || $(tmp).height(); $(tmp).remove(); tmp = null; } } else { height = options.get('height'); } if (!options.get('disableInteraction')) { mhandler = $.data(this, '_jqs_mhandler'); if (!mhandler) { mhandler = new MouseHandler(this, options); $.data(this, '_jqs_mhandler', mhandler); } else if (!options.get('composite')) { 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(); if (mhandler) { 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); } }); }; $.fn.sparkline.defaults = getDefaults(); $.sparkline_display_visible = function () { var el, i, pl; 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); } }; /** * User option handler */ $.fn.sparkline.options = createClass({ init: function (tag, userOptions) { var extendedOptions, defaults, base, tagOptionType; 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]; } 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; } return (result = this.mergedOptions[key]) === undefined ? defaultval : result; } }); $.fn.sparkline._base = createClass({ disabled: false, init: function (el, values, options, width, height) { this.el = el; this.$el = $(el); this.values = values; this.options = options; this.width = width; this.height = height; this.currentRegion = undefined; }, /** * Setup the canvas */ initTarget: function () { var interactive = !this.options.get('disableInteraction'); if (!(this.target = this.$el.simpledraw(this.width, this.height, this.options.get('composite'), interactive))) { this.disabled = true; } else { this.canvasWidth = this.target.pixelWidth; this.canvasHeight = this.target.pixelHeight; } }, /** * Actually render the chart to the canvas */ render: function () { if (this.disabled) { this.el.innerHTML = ''; return false; } return true; }, /** * Return a region id for a given x/y co-ordinate */ getRegion: function (x, y) { }, /** * Highlight an item based on the moused-over x,y co-ordinate */ setRegionHighlight: function (el, x, y) { var currentRegion = this.currentRegion, highlightEnabled = !this.options.get('disableHighlight'), newRegion; if (x > this.canvasWidth || y > this.canvasHeight || x < 0 || y < 0) { return null; } newRegion = this.getRegion(el, x, y); if (currentRegion !== newRegion) { if (currentRegion !== undefined && highlightEnabled) { this.removeHighlight(); } this.currentRegion = newRegion; if (newRegion !== undefined && highlightEnabled) { this.renderHighlight(); } return true; } return false; }, /** * Reset any currently highlighted item */ clearRegionHighlight: function () { if (this.currentRegion !== undefined) { this.removeHighlight(); this.currentRegion = undefined; return true; } return false; }, renderHighlight: function () { this.changeHighlight(true); }, removeHighlight: function () { this.changeHighlight(false); }, changeHighlight: function (highlight) {}, /** * Fetch the HTML to display as a tooltip */ getCurrentRegionTooltip: function () { var options = this.options, header = '', entries = [], fields, formats, formatlen, fclass, text, i, showFields, showFieldsKey, newFields, fv, formatter, format, fieldlen, j; if (this.currentRegion === undefined) { return ''; } fields = this.getCurrentRegionFields(); formatter = options.get('tooltipFormatter'); if (formatter) { return formatter(this, options, fields); } if (options.get('tooltipChartTitle')) { header += '