Commits

Chris Leonello  committed 4dbfb70

Fixed many more memory leaks.

  • Participants
  • Parent commits bc8d5d7

Comments (0)

Files changed (7)

File src/jqplot.axisTickRenderer.js

         if (!this.label) {
             this.label = this.prefix + this.formatter(this.formatString, this.value);
         }
-        var style ='style="position:absolute;';
+        var style = {position: 'absolute'};
         if (Number(this.label)) {
-            style +='white-space:nowrap;';
+            style['whitSpace'] = 'nowrap';
         }
-        style += '"';
         
         // Memory Leaks patch
         if (this._elem) {
             this._elem.emptyForce();
             this._elem = null;
         }
-        this._elem = $('<div '+style+' class="jqplot-'+this.axis+'-tick">'+this.label+'</div>');
+
+
+        var elem = document.createElement('div');
+        this._elem = $(elem);
+        this._elem.addClass("jqplot-"+this.axis+"-tick");
+        this._elem.text(this.label);
+        this._elem.css(style);
+
+
+        // elem = $('<div '+style+' class="jqplot-'+this.axis+'-tick">'+this.label+'</div>');
         for (var s in this._styles) {
             this._elem.css(s, this._styles[s]);
         }
 		if (this._breakTick) {
 			this._elem.addClass('jqplot-breakTick');
 		}
+        
+        elem = null;
+        
         return this._elem;
     };
         

File src/jqplot.core.js

         // Remove any remaining nodes
         if ($.jqplot_use_excanvas) {
           elem.outerHTML = "";
-        } else {
+        }
+        else {
           while ( elem.firstChild ) {
             elem.removeChild( elem.firstChild );
           }

File src/jqplot.divTitleRenderer.js

     };
     
     $.jqplot.DivTitleRenderer.prototype.draw = function() {
+        // Memory Leaks patch
+        if (this._elem) {
+            this._elem.emptyForce();
+            this._elem = null;
+        }
+
         var r = this.renderer;
+        var elem = document.createElement('div');
+        this._elem = $(elem);
+        this._elem.addClass('jqplot-title');
+
         if (!this.text) {
             this.show = false;
-            this._elem = $('<div class="jqplot-title" style="height:0px;width:0px;"></div>');
+            this._elem.height(0);
+            this._elem.width(0);
         }
         else if (this.text) {
             var color;
             else if (this.textColor) {
                 color = this.textColor;
             }
+
             // don't trust that a stylesheet is present, set the position.
-            var styletext = 'position:absolute;top:0px;left:0px;';
-            styletext += (this._plotWidth) ? 'width:'+this._plotWidth+'px;' : '';
-            styletext += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';
-            styletext += (this.textAlign) ? 'text-align:'+this.textAlign+';' : 'text-align:center;';
-            styletext += (color) ? 'color:'+color+';' : '';
-            styletext += (this.paddingBottom) ? 'padding-bottom:'+this.paddingBottom+';' : '';
-            this._elem = $('<div class="jqplot-title" style="'+styletext+'">'+this.text+'</div>');
+            var styles = {position:'absolute', top:'0px', left:'0px'};
+
+            if (this._plotWidth) {
+                styles['width'] = this._plotWidth+'px';
+            }
+            if (this.fontSize) {
+                styles['fontSize'] = this.fontSize;
+            }
+            if (this.textAlign) {
+                styles['textAlign'] = this.textAlign;
+            }
+            if (color) {
+                styles['color'] = color;
+            }
+            if (this.paddingBottom) {
+                styles['paddingBottom'] = this.paddingBottom;
+            }
             if (this.fontFamily) {
-                this._elem.css('font-family', this.fontFamily);
+                styles['fontFamily'] = this.fontFamily;
             }
+
+            this._elem.css(styles);
+            this._elem.text(this.text);
+
+
+            // styletext += (this._plotWidth) ? 'width:'+this._plotWidth+'px;' : '';
+            // styletext += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';
+            // styletext += (this.textAlign) ? 'text-align:'+this.textAlign+';' : 'text-align:center;';
+            // styletext += (color) ? 'color:'+color+';' : '';
+            // styletext += (this.paddingBottom) ? 'padding-bottom:'+this.paddingBottom+';' : '';
+            // this._elem = $('<div class="jqplot-title" style="'+styletext+'">'+this.text+'</div>');
+            // if (this.fontFamily) {
+            //     this._elem.css('font-family', this.fontFamily);
+            // }
         }
+
+        elem = null;
         
         return this._elem;
     };

File src/jqplot.linearAxisRenderer.js

     
     // called with scope of axis object.
     $.jqplot.LinearAxisRenderer.prototype.init = function(options){
-		// prop: breakPoints
-		// EXPERIMENTAL!! Use at your own risk!
-		// Works only with linear axes and the default tick renderer.
-		// Array of [start, stop] points to create a broken axis.
-		// Broken axes have a "jump" in them, which is an immediate 
-		// transition from a smaller value to a larger value.
-		// Currently, axis ticks MUST be manually assigned if using breakPoints
-		// by using the axis ticks array option.
-		this.breakPoints = null;
-		// prop: breakTickLabel
-		// Label to use at the axis break if breakPoints are specified.
-		this.breakTickLabel = "&asymp;";
+        // prop: breakPoints
+        // EXPERIMENTAL!! Use at your own risk!
+        // Works only with linear axes and the default tick renderer.
+        // Array of [start, stop] points to create a broken axis.
+        // Broken axes have a "jump" in them, which is an immediate 
+        // transition from a smaller value to a larger value.
+        // Currently, axis ticks MUST be manually assigned if using breakPoints
+        // by using the axis ticks array option.
+        this.breakPoints = null;
+        // prop: breakTickLabel
+        // Label to use at the axis break if breakPoints are specified.
+        this.breakTickLabel = "&asymp;";
         // prop: forceTickAt0
         // This will ensure that there is always a tick mark at 0.
         // If data range is strictly positive or negative,
         this._autoFormatString = '';
         this._overrideFormatString = false;
         $.extend(true, this, options);
-		if (this.breakPoints) {
-			if (!$.isArray(this.breakPoints)) {
-				this.breakPoints = null;
-			}
-			else if (this.breakPoints.length < 2 || this.breakPoints[1] <= this.breakPoints[0]) {
-				this.breakPoints = null;
-			}
-		}
-		this.resetDataBounds();
+        if (this.breakPoints) {
+            if (!$.isArray(this.breakPoints)) {
+                this.breakPoints = null;
+            }
+            else if (this.breakPoints.length < 2 || this.breakPoints[1] <= this.breakPoints[0]) {
+                this.breakPoints = null;
+            }
+        }
+        this.resetDataBounds();
     };
     
     // called with scope of axis
                 // Memory Leaks patch
                 //this._elem.empty();
                 this._elem.emptyForce();
+                this._elem = null;
             }
             
-            this._elem = $('<div class="jqplot-axis jqplot-'+this.name+'" style="position:absolute;"></div>');
+            var elem = document.createElement('div');
+            this._elem = $(elem);
+            this._elem.addClass('jqplot-axis jqplot-'+this.name);
+            this._elem.css('posiiton', 'absolute');
+            elem = null;
+
             
             if (this.name == 'xaxis' || this.name == 'x2axis') {
                 this._elem.width(this._plotDimensions.width);
             // create a _label object.
             this.labelOptions.axis = this.name;
             this._label = new this.labelRenderer(this.labelOptions);
-            var elem;
             if (this._label.show) {
                 elem = this._label.draw(ctx, plot);
                 elem.appendTo(this._elem);
                     elem = tick.draw(ctx, plot);
                     elem.appendTo(this._elem);
                 }
+                tick = null;
             }
+            t = null;
             elem = null;
         }
         return this._elem;
         var lshow = (this._label == null) ? false : this._label.show;
         if (this.show) {
             var t = this._ticks;
+            var tick;
             for (var i=0; i<t.length; i++) {
-                var tick = t[i];
+                tick = t[i];
                 if (!tick._breakTick && tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {
                     if (this.name == 'xaxis' || this.name == 'x2axis') {
                         temp = tick._elem.outerHeight(true);
                     }
                 }
             }
+            tick = null;
+            t = null;
             
             if (lshow) {
                 w = this._label._elem.outerWidth(true);
                 var ut = userTicks[i];
                 var t = new this.tickRenderer(this.tickOptions);
                 if (ut.constructor == Array) {
-	                t.value = ut[0];
-					if (this.breakPoints) {
-						if (ut[0] == this.breakPoints[0]) {
-							t.label = this.breakTickLabel;
-							t._breakTick = true;
-							t.showGridline = false;
-							t.showMark = false;
-						}
-						else if (ut[0] > this.breakPoints[0] && ut[0] <= this.breakPoints[1]) {
-							t.show = false;
-							t.showGridline = false;
-		                    t.label = ut[1];
-						}
-						else {
-		                    t.label = ut[1];
-						}
-					}
-					else {
-	                    t.label = ut[1];
-					}
+                    t.value = ut[0];
+                    if (this.breakPoints) {
+                        if (ut[0] == this.breakPoints[0]) {
+                            t.label = this.breakTickLabel;
+                            t._breakTick = true;
+                            t.showGridline = false;
+                            t.showMark = false;
+                        }
+                        else if (ut[0] > this.breakPoints[0] && ut[0] <= this.breakPoints[1]) {
+                            t.show = false;
+                            t.showGridline = false;
+                            t.label = ut[1];
+                        }
+                        else {
+                            t.label = ut[1];
+                        }
+                    }
+                    else {
+                        t.label = ut[1];
+                    }
                     t.setTick(ut[0], this.name);
                     this._ticks.push(t);
                 }
                 
                 else {
-	                t.value = ut;
-					if (this.breakPoints) {
-						if (ut == this.breakPoints[0]) {
-							t.label = this.breakTickLabel;
-							t._breakTick = true;
-							t.showGridline = false;
-							t.showMark = false;
-						}
-						else if (ut > this.breakPoints[0] && ut <= this.breakPoints[1]) {
-							t.show = false;
-							t.showGridline = false;
-						}
-					}
+                    t.value = ut;
+                    if (this.breakPoints) {
+                        if (ut == this.breakPoints[0]) {
+                            t.label = this.breakTickLabel;
+                            t._breakTick = true;
+                            t.showGridline = false;
+                            t.showMark = false;
+                        }
+                        else if (ut > this.breakPoints[0] && ut <= this.breakPoints[1]) {
+                            t.show = false;
+                            t.showGridline = false;
+                        }
+                    }
                     t.setTick(ut, this.name);
                     this._ticks.push(t);
                 }
 
                 t.setTick(tt, this.name);
                 this._ticks.push(t);
+                t = null;
             }
         }
+        ticks = null;
     };
-	
-	// Used to reset just the values of the ticks and then repack, which will
-	// recalculate the positioning functions.  It is assuemd that the 
-	// number of ticks is the same and the values of the new array are at the
-	// proper interval.
-	// This method needs to be called with the scope of an axis object, like:
-	//
-	// > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr);
-	//
-	$.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) {
-		if ($.isArray(opts) && opts.length == this._ticks.length) {
-			var t;
-			for (var i=0; i<opts.length; i++) {
-				t = this._ticks[i];
-				t.value = opts[i];
-				t.label = t.formatter(t.formatString, opts[i]);
-				t.label = t.prefix + t.label;
-				t._elem.html(t.label);
-			}
-			this.min = $.jqplot.arrayMin(opts);
-			this.max = $.jqplot.arrayMax(opts);
-			this.pack();
-		}
-		// Not implemented yet.
+    
+    // Used to reset just the values of the ticks and then repack, which will
+    // recalculate the positioning functions.  It is assuemd that the 
+    // number of ticks is the same and the values of the new array are at the
+    // proper interval.
+    // This method needs to be called with the scope of an axis object, like:
+    //
+    // > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr);
+    //
+    $.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) {
+        if ($.isArray(opts) && opts.length == this._ticks.length) {
+            var t;
+            for (var i=0; i<opts.length; i++) {
+                t = this._ticks[i];
+                t.value = opts[i];
+                t.label = t.formatter(t.formatString, opts[i]);
+                t.label = t.prefix + t.label;
+                t._elem.html(t.label);
+            }
+            t = null;
+            this.min = $.jqplot.arrayMin(opts);
+            this.max = $.jqplot.arrayMax(opts);
+            this.pack();
+        }
+        // Not implemented yet.
         // else if ($.isPlainObject(opts)) {
         // 
         // }
-	};
+    };
     
     // called with scope of axis
     $.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) {
-		// Add defaults for repacking from resetTickValues function.
-		pos = pos || {};
-		offsets = offsets || this._offsets;
-		
+        // Add defaults for repacking from resetTickValues function.
+        pos = pos || {};
+        offsets = offsets || this._offsets;
+        
         var ticks = this._ticks;
         var max = this.max;
         var min = this.min;
         var unitlength = max - min;
         
         // point to unit and unit to point conversions references to Plot DOM element top left corner.
-		if (this.breakPoints) {
-			unitlength = unitlength - this.breakPoints[1] + this.breakPoints[0];
-			
-	        this.p2u = function(p){
-	            return (p - offmin) * unitlength / pixellength + min;
-	        };
+        if (this.breakPoints) {
+            unitlength = unitlength - this.breakPoints[1] + this.breakPoints[0];
+            
+            this.p2u = function(p){
+                return (p - offmin) * unitlength / pixellength + min;
+            };
         
-	        this.u2p = function(u){
-				if (u > this.breakPoints[0] && u < this.breakPoints[1]){
-					u = this.breakPoints[0];
-				}
-				if (u <= this.breakPoints[0]) {
-	            	return (u - min) * pixellength / unitlength + offmin;
-				}
-				else {
-					return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength + offmin;
-				}
-	        };
+            this.u2p = function(u){
+                if (u > this.breakPoints[0] && u < this.breakPoints[1]){
+                    u = this.breakPoints[0];
+                }
+                if (u <= this.breakPoints[0]) {
+                    return (u - min) * pixellength / unitlength + offmin;
+                }
+                else {
+                    return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength + offmin;
+                }
+            };
                 
-	        if (this.name.charAt(0) == 'x'){
-	            this.series_u2p = function(u){
-					if (u > this.breakPoints[0] && u < this.breakPoints[1]){
-						u = this.breakPoints[0];
-					}
-					if (u <= this.breakPoints[0]) {
-		            	return (u - min) * pixellength / unitlength;
-					}
-					else {
-						return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength;
-					}
-	            };
-	            this.series_p2u = function(p){
-	                return p * unitlength / pixellength + min;
-	            };
-	        }
+            if (this.name.charAt(0) == 'x'){
+                this.series_u2p = function(u){
+                    if (u > this.breakPoints[0] && u < this.breakPoints[1]){
+                        u = this.breakPoints[0];
+                    }
+                    if (u <= this.breakPoints[0]) {
+                        return (u - min) * pixellength / unitlength;
+                    }
+                    else {
+                        return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength;
+                    }
+                };
+                this.series_p2u = function(p){
+                    return p * unitlength / pixellength + min;
+                };
+            }
         
-	        else {
-	            this.series_u2p = function(u){
-					if (u > this.breakPoints[0] && u < this.breakPoints[1]){
-						u = this.breakPoints[0];
-					}
-					if (u >= this.breakPoints[1]) {
-		            	return (u - max) * pixellength / unitlength;
-					}
-					else {
-						return (u + this.breakPoints[1] - this.breakPoints[0] - max) * pixellength / unitlength;
-					}
-	            };
-	            this.series_p2u = function(p){
-	                return p * unitlength / pixellength + max;
-	            };
-	        }
-		}
-		else {
-	        this.p2u = function(p){
-	            return (p - offmin) * unitlength / pixellength + min;
-	        };
+            else {
+                this.series_u2p = function(u){
+                    if (u > this.breakPoints[0] && u < this.breakPoints[1]){
+                        u = this.breakPoints[0];
+                    }
+                    if (u >= this.breakPoints[1]) {
+                        return (u - max) * pixellength / unitlength;
+                    }
+                    else {
+                        return (u + this.breakPoints[1] - this.breakPoints[0] - max) * pixellength / unitlength;
+                    }
+                };
+                this.series_p2u = function(p){
+                    return p * unitlength / pixellength + max;
+                };
+            }
+        }
+        else {
+            this.p2u = function(p){
+                return (p - offmin) * unitlength / pixellength + min;
+            };
         
-	        this.u2p = function(u){
-	            return (u - min) * pixellength / unitlength + offmin;
-	        };
+            this.u2p = function(u){
+                return (u - min) * pixellength / unitlength + offmin;
+            };
                 
-	        if (this.name == 'xaxis' || this.name == 'x2axis'){
-	            this.series_u2p = function(u){
-	                return (u - min) * pixellength / unitlength;
-	            };
-	            this.series_p2u = function(p){
-	                return p * unitlength / pixellength + min;
-	            };
-	        }
+            if (this.name == 'xaxis' || this.name == 'x2axis'){
+                this.series_u2p = function(u){
+                    return (u - min) * pixellength / unitlength;
+                };
+                this.series_p2u = function(p){
+                    return p * unitlength / pixellength + min;
+                };
+            }
         
-	        else {
-	            this.series_u2p = function(u){
-	                return (u - max) * pixellength / unitlength;
-	            };
-	            this.series_p2u = function(p){
-	                return p * unitlength / pixellength + max;
-	            };
-	        }
-		}
+            else {
+                this.series_u2p = function(u){
+                    return (u - max) * pixellength / unitlength;
+                };
+                this.series_p2u = function(p){
+                    return p * unitlength / pixellength + max;
+                };
+            }
+        }
         
         if (this.show) {
             if (this.name == 'xaxis' || this.name == 'x2axis') {
                 }
             }
         }
+
+        ticks = null;
     };
 })(jQuery);

File src/plugins/jqplot.cursor.js

             this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this));
             c.zoomCanvas.setContext();
         }
+
+        var elem = document.createElement('div');
+        c._tooltipElem = $(elem);
+        elem = null;
+        c._tooltipElem.addClass('jqplot-cursor-tooltip');
+        c._tooltipElem.css({position:'absolute', display:'none'});
         
-        c._tooltipElem = $('<div class="jqplot-cursor-tooltip" style="position:absolute;display:none"></div>');
         
         if (c.zoomCanvas) {
             c.zoomCanvas._elem.before(c._tooltipElem);
     
     // called in context of a Legend
     $.jqplot.CursorLegendRenderer.prototype.draw = function() {
+        if (this._elem) {
+            this._elem.emptyForce();
+            this._elem = null;
+        }
         if (this.show) {
             var series = this._series, s;
             // make a table.  one line label per row.
-            this._elem = $('<table class="jqplot-legend jqplot-cursor-legend" style="position:absolute"></table>');
+            var elem = document.createElement('div');
+            this._elem = $(elem);
+            elem = null;
+            this._elem.addClass('jqplot-legend jqplot-cursor-legend');
+            this._elem.css('position', 'absolute');
         
             var pad = false;
             for (var i = 0; i< series.length; i++) {

File src/plugins/jqplot.highlighter.js

             this.plugins.highlighter.highlightCanvas = null;
         }
 
+        if (this.plugins.highlighter && this.plugins.highlighter._tooltipElem) {
+            this.plugins.highlighter._tooltipElem.emptyForce();
+            this.plugins.highlighter._tooltipElem = null;
+        }
+
         this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas();
         
         this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions, this));
         this.plugins.highlighter.highlightCanvas.setContext();
+
+        var elem = document.createElement('div');
+        this.plugins.highlighter._tooltipElem = $(elem);
+        elem = null;
+        this.plugins.highlighter._tooltipElem.addClass('jqplot-highlighter-tooltip');
+        this.plugins.highlighter._tooltipElem.css({position:'absolute', display:'none'});
         
-        var p = this.plugins.highlighter;
-        p._tooltipElem = $('<div class="jqplot-highlighter-tooltip" style="position:absolute;display:none"></div>');
-        this.eventCanvas._elem.before(p._tooltipElem);
+        this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem);
     };
     
     $.jqplot.preInitHooks.push($.jqplot.Highlighter.init);

File src/plugins/jqplot.pointLabels.js

             var pd = this._plotData;
             var xax = this._xaxis;
             var yax = this._yaxis;
+            var elem, helem;
 
-            for (var i=p._labels.length-1; i>=0; i--) {
+            for (var i=0, l=p._labels.length; i < l; i++) {
                 var label = p._labels[i];
                 
                 if (p.hideZeros && parseInt(p._labels[i], 10) == 0) {
                 if (label != null) {
                     label = p.formatter(p.formatString, label);
                 } 
-                var elem = $('<div class="jqplot-point-label jqplot-series-'+this.index+' jqplot-point-'+i+'" style="position:absolute"></div>');
+
+                helem = document.createElement('div');
+                p._elems[i] = $(helem);
+
+                elem = p._elems[i];
+
+
+                elem.addClass('jqplot-point-label jqplot-series-'+this.index+' jqplot-point-'+i);
+                elem.css('position', 'absolute');
                 elem.insertAfter(sctx.canvas);
-                p._elems.push(elem);
+
                 if (p.escapeHTML) {
                     elem.text(label);
                 }
                 }
                 elem.css('left', ell);
                 elem.css('top', elt);
-                var elr = ell + $(elem).width();
-                var elb = elt + $(elem).height();
+                var elr = ell + elem.width();
+                var elb = elt + elem.height();
                 var et = p.edgeTolerance;
                 var scl = $(sctx.canvas).position().left;
                 var sct = $(sctx.canvas).position().top;
                 var scb = sctx.canvas.height + sct;
                 // if label is outside of allowed area, remove it
                 if (ell - et < scl || elt - et < sct || elr + et > scr || elb + et > scb) {
-                    $(elem).detach();
+                    elem.remove();
                 }
+                elem = null;
+                helem = null;
             }
         }
     };