From d248f9ea7d2b6a3da2d555c8e50298b29c858e7a Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Mon, 19 Aug 2013 08:21:03 -0400 Subject: [PATCH 1/2] Update example to allow easily profiling memory usage. --- examples/many_series.html | 70 +++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/examples/many_series.html b/examples/many_series.html index e899431..1e080a1 100644 --- a/examples/many_series.html +++ b/examples/many_series.html @@ -24,39 +24,53 @@

flot.tooltip plugin example page

- + Plot From 497dc8ba857ebacc3a5233cf5b303b06251d495e Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Mon, 19 Aug 2013 08:29:53 -0400 Subject: [PATCH 2/2] Ensure that events are properly unbound on flot shutdown. This avoids leaking memory, including all of the plot options object. --- js/jquery.flot.tooltip.js | 74 ++++++++++++++++++-------------- js/jquery.flot.tooltip.min.js | 6 +-- js/jquery.flot.tooltip.source.js | 70 +++++++++++++++++------------- package.json | 2 +- 4 files changed, 84 insertions(+), 68 deletions(-) diff --git a/js/jquery.flot.tooltip.js b/js/jquery.flot.tooltip.js index b41c80c..eb6b156 100644 --- a/js/jquery.flot.tooltip.js +++ b/js/jquery.flot.tooltip.js @@ -2,11 +2,11 @@ * jquery.flot.tooltip * * description: easy-to-use tooltips for Flot charts - * version: 0.6.1 + * version: 0.6.2 * author: Krzysztof Urbas @krzysu [myviews.pl] * website: https://github.com/krzysu/flot.tooltip * - * build on 2013-07-10 + * build on 2013-08-19 * released under MIT License, 2012 */ (function ($) { @@ -64,38 +64,46 @@ var $tip = that.getDomElement(); // bind event - $( plot.getPlaceholder() ).bind("plothover", function (event, pos, item) { - 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(''); - } - }); - - eventHolder.mousemove( function(e) { - var pos = {}; - pos.x = e.pageX; - pos.y = e.pageY; - that.updateTooltipPosition(pos); - }); + $( 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(''); + } + } }; /** diff --git a/js/jquery.flot.tooltip.min.js b/js/jquery.flot.tooltip.min.js index b8513db..a992b06 100644 --- a/js/jquery.flot.tooltip.min.js +++ b/js/jquery.flot.tooltip.min.js @@ -2,11 +2,11 @@ * jquery.flot.tooltip * * description: easy-to-use tooltips for Flot charts - * version: 0.6.1 + * version: 0.6.2 * author: Krzysztof Urbas @krzysu [myviews.pl] * website: https://github.com/krzysu/flot.tooltip * - * build on 2013-07-10 + * build on 2013-08-19 * released under MIT License, 2012 */ -(function(t){var i={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},o=function(t){this.tipPosition={x:0,y:0},this.init(t)};o.prototype.init=function(i){var o=this;i.hooks.bindEvents.push(function(i,e){if(o.plotOptions=i.getOptions(),o.plotOptions.tooltip!==!1&&void 0!==o.plotOptions.tooltip){o.tooltipOptions=o.plotOptions.tooltipOpts;var s=o.getDomElement();t(i.getPlaceholder()).bind("plothover",function(t,i,e){if(e){var n;n=o.stringFormat(o.tooltipOptions.content,e),s.html(n),o.updateTooltipPosition({x:i.pageX,y:i.pageY}),s.css({left:o.tipPosition.x+o.tooltipOptions.shifts.x,top:o.tipPosition.y+o.tooltipOptions.shifts.y}).show(),"function"==typeof o.tooltipOptions.onHover&&o.tooltipOptions.onHover(e,s)}else s.hide().html("")}),e.mousemove(function(t){var i={};i.x=t.pageX,i.y=t.pageY,o.updateTooltipPosition(i)})}})},o.prototype.getDomElement=function(){var i;return t("#flotTip").length>0?i=t("#flotTip"):(i=t("
").attr("id","flotTip"),i.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&i.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"inline-block","white-space":"nowrap"})),i},o.prototype.updateTooltipPosition=function(i){var o=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;i.x-t(window).scrollLeft()>t(window).innerWidth()-o&&(i.x-=o),i.y-t(window).scrollTop()>t(window).innerHeight()-e&&(i.y-=e),this.tipPosition.x=i.x,this.tipPosition.y=i.y},o.prototype.stringFormat=function(t,i){var o=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(i.series.label,i.series.data[i.dataIndex][0],i.series.data[i.dataIndex][1])),i.series.percent!==void 0&&(t=this.adjustValPrecision(o,t,i.series.percent)),i.series.label!==void 0&&(t=t.replace(e,i.series.label)),this.isTimeMode("xaxis",i)&&this.isXDateFormat(i)&&(t=t.replace(s,this.timestampToDate(i.series.data[i.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",i)&&this.isYDateFormat(i)&&(t=t.replace(n,this.timestampToDate(i.series.data[i.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof i.series.data[i.dataIndex][0]&&(t=this.adjustValPrecision(s,t,i.series.data[i.dataIndex][0])),"number"==typeof i.series.data[i.dataIndex][1]&&(t=this.adjustValPrecision(n,t,i.series.data[i.dataIndex][1])),i.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,i.series.xaxis.tickFormatter(i.series.data[i.dataIndex][0],i.series.xaxis))),i.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,i.series.yaxis.tickFormatter(i.series.data[i.dataIndex][1],i.series.yaxis))),t},o.prototype.isTimeMode=function(t,i){return i.series[t].options.mode!==void 0&&"time"===i.series[t].options.mode},o.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},o.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},o.prototype.timestampToDate=function(i,o){var e=new Date(i);return t.plot.formatDate(e,o)},o.prototype.adjustValPrecision=function(t,i,o){var e,s=i.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,o=o.toFixed(e),i=i.replace(t,o)),i};var e=function(t){new o(t)};t.plot.plugins.push({init:e,options:i,name:"tooltip",version:"0.6.1"})})(jQuery); \ No newline at end of file +!function(a){var b={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},c=function(a){this.tipPosition={x:0,y:0},this.init(a)};c.prototype.init=function(b){function c(a){var b={};b.x=a.pageX,b.y=a.pageY,e.updateTooltipPosition(b)}function d(a,b,c){var d=e.getDomElement();if(c){var f;f=e.stringFormat(e.tooltipOptions.content,c),d.html(f),e.updateTooltipPosition({x:b.pageX,y:b.pageY}),d.css({left:e.tipPosition.x+e.tooltipOptions.shifts.x,top:e.tipPosition.y+e.tooltipOptions.shifts.y}).show(),"function"==typeof e.tooltipOptions.onHover&&e.tooltipOptions.onHover(c,d)}else d.hide().html("")}var e=this;b.hooks.bindEvents.push(function(b,f){e.plotOptions=b.getOptions(),e.plotOptions.tooltip!==!1&&"undefined"!=typeof e.plotOptions.tooltip&&(e.tooltipOptions=e.plotOptions.tooltipOpts,e.getDomElement(),a(b.getPlaceholder()).bind("plothover",d),a(f).bind("mousemove",c))}),b.hooks.shutdown.push(function(b,e){a(b.getPlaceholder()).unbind("plothover",d),a(e).unbind("mousemove",c)})},c.prototype.getDomElement=function(){var b;return a("#flotTip").length>0?b=a("#flotTip"):(b=a("
").attr("id","flotTip"),b.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&b.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"inline-block","white-space":"nowrap"})),b},c.prototype.updateTooltipPosition=function(b){var c=a("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,d=a("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;b.x-a(window).scrollLeft()>a(window).innerWidth()-c&&(b.x-=c),b.y-a(window).scrollTop()>a(window).innerHeight()-d&&(b.y-=d),this.tipPosition.x=b.x,this.tipPosition.y=b.y},c.prototype.stringFormat=function(a,b){var c=/%p\.{0,1}(\d{0,})/,d=/%s/,e=/%x\.{0,1}(?:\d{0,})/,f=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof a&&(a=a(b.series.label,b.series.data[b.dataIndex][0],b.series.data[b.dataIndex][1])),"undefined"!=typeof b.series.percent&&(a=this.adjustValPrecision(c,a,b.series.percent)),"undefined"!=typeof b.series.label&&(a=a.replace(d,b.series.label)),this.isTimeMode("xaxis",b)&&this.isXDateFormat(b)&&(a=a.replace(e,this.timestampToDate(b.series.data[b.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",b)&&this.isYDateFormat(b)&&(a=a.replace(f,this.timestampToDate(b.series.data[b.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof b.series.data[b.dataIndex][0]&&(a=this.adjustValPrecision(e,a,b.series.data[b.dataIndex][0])),"number"==typeof b.series.data[b.dataIndex][1]&&(a=this.adjustValPrecision(f,a,b.series.data[b.dataIndex][1])),"undefined"!=typeof b.series.xaxis.tickFormatter&&(a=a.replace(e,b.series.xaxis.tickFormatter(b.series.data[b.dataIndex][0],b.series.xaxis))),"undefined"!=typeof b.series.yaxis.tickFormatter&&(a=a.replace(f,b.series.yaxis.tickFormatter(b.series.data[b.dataIndex][1],b.series.yaxis))),a},c.prototype.isTimeMode=function(a,b){return"undefined"!=typeof b.series[a].options.mode&&"time"===b.series[a].options.mode},c.prototype.isXDateFormat=function(){return"undefined"!=typeof this.tooltipOptions.xDateFormat&&null!==this.tooltipOptions.xDateFormat},c.prototype.isYDateFormat=function(){return"undefined"!=typeof this.tooltipOptions.yDateFormat&&null!==this.tooltipOptions.yDateFormat},c.prototype.timestampToDate=function(b,c){var d=new Date(b);return a.plot.formatDate(d,c)},c.prototype.adjustValPrecision=function(a,b,c){var d,e=b.match(a);return null!==e&&""!==RegExp.$1&&(d=RegExp.$1,c=c.toFixed(d),b=b.replace(a,c)),b};var d=function(a){new c(a)};a.plot.plugins.push({init:d,options:b,name:"tooltip",version:"0.6.1"})}(jQuery); \ No newline at end of file diff --git a/js/jquery.flot.tooltip.source.js b/js/jquery.flot.tooltip.source.js index e37e3f1..02a19f8 100644 --- a/js/jquery.flot.tooltip.source.js +++ b/js/jquery.flot.tooltip.source.js @@ -53,38 +53,46 @@ var $tip = that.getDomElement(); // bind event - $( plot.getPlaceholder() ).bind("plothover", function (event, pos, item) { - 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(''); - } - }); - - eventHolder.mousemove( function(e) { - var pos = {}; - pos.x = e.pageX; - pos.y = e.pageY; - that.updateTooltipPosition(pos); - }); + $( 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(''); + } + } }; /** diff --git a/package.json b/package.json index 26f17b0..8dbcfbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jquery.flot.tooltip", - "version": "0.6.1", + "version": "0.6.2", "description": "easy-to-use tooltips for Flot charts", "website": "https://github.com/krzysu/flot.tooltip", "directories": {