Export capabilities

Anonymous avatarAnonymous created an issue

Greating,

I think that it would be very useful if jqPlot could have some export capabilities like:

-- Save as a picture (jpeg, png or gif) -- Export to pdf

This is a excellent plugin for graphs! And it has a great look!

Thanks, Pedro Estácio

Comments (40)

  1. Anonymous

    Hi Chris,

    Is there a progress about this "jqlpot to image" issue.

    or

    Do you have an opinion to show the plot in email and printing it.

    Thanks.

  2. Anonymous

    here is a simple code that will replace the page with an image of the plot (which you can then save):

    var newCanvas = document.createElement("canvas");
    newCanvas.width = $("#chartDiv").width();
    newCanvas.height = $("#chartDiv").height();
    
    $("#chartDiv > canvas").each(function () {
        var position = $(this).position();
        newCanvas.getContext("2d").drawImage(this, position.left, position.top);
    });
    
    document.location.href = newCanvas.toDataURL();
    
  3. Anonymous

    even better:

    first, make sure in your options, that labels and ticks are rendered using canvases:

                axesDefaults: {
                    labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
                    tickRenderer: $.jqplot.CanvasAxisTickRenderer, 
                },
    

    then, run this code to replace your current page with an image of the plot:

    var newCanvas = document.createElement("canvas");
    newCanvas.width = $("#chartDiv").width();
    newCanvas.height = $("#chartDiv").height();
    var baseOffset = $("#chartDiv").offset();
    
    $("#chartDiv canvas").each(function () {
        var offset = $(this).offset();
        var offset = $(this).position();
        newCanvas.getContext("2d").drawImage(this,
            offset.left - baseOffset.left,
            offset.top - baseOffset.top);
    });
    
    document.location.href = newCanvas.toDataURL();
    
    
  4. Anonymous

    This works when removing the extra line

    var offset = $(this).position();

    (should be the offset, not the position!)

  5. Anonymous

    I use this (still having problems with the labels and ticks) to display the graph, a div with title without closing or changing the current url :

    function printPlot(title, chart){
    
        var WinPrint = window.open('','','left=0,top=0,toolbar=0,scrollbars=0,status=0');
        WinPrint.document.open();
    
        var links=window.document.getElementsByTagName('link');
    
        var newCanvas = document.createElement("canvas");
        newCanvas.width = $(chart).width();
        newCanvas.height = $(chart).height();
        var baseOffset = $(chart).offset();
        $(chart + " canvas").each(function () {
            var offset = $(this).offset();
            newCanvas.getContext("2d").drawImage(this,
                offset.left - baseOffset.left,
                offset.top - baseOffset.top);
        });
    
        var auxHtml = "<h1>"+ $(title).html() + "</h1>"
        + "<div><img id='newPlot' src='" +newCanvas.toDataURL() + "' alt='' /></div>";
    
        for(var i=0;i<links.length;i++){
            if(links[i].rel.toLowerCase()=='stylesheet'){
                WinPrint.document.write('<link type="text/css" rel="stylesheet" href="'+links[i].href+'"></link>');
            }
        }
        WinPrint.document.write('<div class="'+$(chart).attr("class")+'">'+auxHtml+'</div>');
        WinPrint.document.close();
        WinPrint.focus();
        WinPrint.print();
        WinPrint.close();
    
    
    
  6. Anonymous

    Hello!

    Actually i've been trying all the tips that have been posted on this forum but i've never been able to see the chart in a different window!! i only get a blank page!!

    Actually i'm trying to view 5 charts that are generated by jqplot and are drawn when i add these lines :

    <div id="chart1" style="height:400px;width:400px; "></div> <br>

    <div id="chart2" style="height:400px;width:400px; "></div><br>

    <div id="chart3" style="height:400px;width:400px; "></div><br>

    <div id="chart4" style="height:400px;width:400px; "></div><br>

    <div id="chart5" style="height:400px;width:400px; "></div><br>

    What should i change in the mutltiple codes put on this forum to export my charts?

    Thanks for anyones help.

    Elie

  7. Anonymous

    Well guys, finally I got it:

        var newCanvas = document.createElement("canvas");
        newCanvas.width = $("#chart-div").width();
        newCanvas.height = $("#chart-div").height();
        var baseOffset = $("#chart-div").offset();
        
        $("#show-curve-wrapper canvas").each(function () {
            var offset = $(this).offset();
            newCanvas.getContext("2d").drawImage(this,
                offset.left - baseOffset.left,
                offset.top - baseOffset.top);
        });
    
        blah = newCanvas.toDataURL();
        $.post('/blah.php', { picture: blah }, function(data){
            alert(data);
        });
    

    The blah.php which saves the file to the server:

    header ('Content-Type: image/png');
    $fuckingdata = $_POST['picture'];
    $dataurl = str_replace(" ", "+", $fuckingdata);
    $data = substr($dataurl, strpos($dataurl, ","));
    $file = fopen("curves/image.png", "wb");
    fwrite($file, base64_decode($data));
    fclose($file);
    

    Sorry for the names of the variables...but it was a long run! Hope this helps anybody!

  8. Anonymous

    Thanks for that Anonymous (If that's your real name!). I've replicated your code, however my version doesn't display the legend. Does yours show the legend though or is this something you could comment on?

  9. Anonymous

    I've managed to get it working with the code on #12, but ofcourse we can't get the legend on the image, because the legend is drawn using div's. <div> tag doesn't have the native function drawImage(), as the <canvas> has. I have not found a way of getting the div content to an image. Maybe someone has found a solution?

  10. Anonymous

    Sorry about the link on the last post. I didn't mean to link it to another issue. I meant the comment number 12.

  11. Anonymous

    Well, I've managed to get it working, ofcourse this isn't a beautiful solution, but it works.

            $("#chart1").children().each(function () {
                // for the div's with the X and Y axis
                if ($(this)[0].tagName.toLowerCase() == 'div') {
                    // X axis is built with canvas
                    $(this).children("canvas").each(function() {
                        var offset = $(this).offset();
                        newCanvas.getContext("2d").drawImage(this,
                            offset.left - baseOffset.left,
                            offset.top - baseOffset.top);
                        });
                    // Y axis got div inside, so we get the text and draw it on the canvas
                    $(this).children("div").each(function() {
                        var offset = $(this).offset();
                        var context = newCanvas.getContext("2d");
                        context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
                        context.fillText($(this).html(),
                            offset.left - baseOffset.left,
                            offset.top - baseOffset.top + 10);
                        });
                }
                // all other canvas from the chart
                else if($(this)[0].tagName.toLowerCase() == 'canvas') {
                    var offset = $(this).offset();
                    newCanvas.getContext("2d").drawImage(this,
                        offset.left - baseOffset.left,
                        offset.top - baseOffset.top);
                }
            });
    
            // add the colored rectangles
            $("#chart1 *").children(".jqplot-table-legend-swatch").each(function() {
                    var offset = $(this).offset();
                    var context = newCanvas.getContext("2d");
                    context.setFillColor($(this).css('background-color'));
                    context.fillRect(
                        offset.left - baseOffset.left,
                        offset.top - baseOffset.top,
                        15,15
                    );
            });
                
            // add the legend
            $("#chart1 *").children(".jqplot-table-legend td:last-child").each(function() {
                    var offset = $(this).offset();
                    var context = newCanvas.getContext("2d");
                    context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
                    context.fillText($(this).html(),
                        offset.left - baseOffset.left,
                        offset.top - baseOffset.top + 10);
            });
    
  12. Anonymous

    The code in the previous post must have the newCanvas var set, like comment number 12 said:

            var newCanvas = document.createElement("canvas");
            newCanvas.width = $("#chart1").width();
            newCanvas.height = $("#chart1").height();
            var baseOffset = $("#chart1").offset();
    
  13. Anonymous

    Now it includes the point labels as well. This isn't a beautiful solution, but it works for me. I can't delete the previous two posts, It'll be easy for you to see it all together:

            // first we draw an image with all the chart components
            var newCanvas = document.createElement("canvas");
            newCanvas.width = $("#chart1").width();
            newCanvas.height = $("#chart1").height();
            var baseOffset = $("#chart1").offset();
    
            $("#chart1").children().each(function () {
                // for the div's with the X and Y axis
                if ($(this)[0].tagName.toLowerCase() == 'div') {
                    // X axis is built with canvas
                    $(this).children("canvas").each(function() {
                        var offset = $(this).offset();
                        newCanvas.getContext("2d").drawImage(this,
                            offset.left - baseOffset.left,
                            offset.top - baseOffset.top);
                        });
                    // Y axis got div inside, so we get the text and draw it on the canvas
                    $(this).children("div").each(function() {
                        var offset = $(this).offset();
                        var context = newCanvas.getContext("2d");
                        context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
                        context.fillText($(this).html(),
                            offset.left - baseOffset.left,
                            offset.top - baseOffset.top + 10);
                        });
                }
                // all other canvas from the chart
                else if($(this)[0].tagName.toLowerCase() == 'canvas') {
                    var offset = $(this).offset();
                    newCanvas.getContext("2d").drawImage(this,
                        offset.left - baseOffset.left,
                        offset.top - baseOffset.top);
                }
            });
            
            // add the point labels
            $("#chart1").children(".jqplot-point-label").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    		context.fillText($(this).html(),
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top + 10);
            });
            
            // add the rectangles
            $("#chart1 *").children(".jqplot-table-legend-swatch").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.setFillColor($(this).css('background-color'));
    		context.fillRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			15,15
    		);
            });
    	
            // add the legend
            $("#chart1 *").children(".jqplot-table-legend td:last-child").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    		context.fillText($(this).html(),
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top + 15);
            });
            
            // then convert the image to base64 format
            picture = newCanvas.toDataURL();
    
  14. Kevin Risden

    Here is a slightly modified version that works across a bigger legend and cleans up the chart selection to one location at the top.

    var obj = $("#chart1")
    obj.children().each(function () {
    // for the div's with the X and Y axis
    	if ($(this)[0].tagName.toLowerCase() == 'div') {
    		// X axis is built with canvas
    		$(this).children("canvas").each(function() {
    			var offset = $(this).offset();
    			newCanvas.getContext("2d").drawImage(this,
    				offset.left - baseOffset.left,
    				offset.top - baseOffset.top
    			);
    		});
    		// Y axis got div inside, so we get the text and draw it on the canvas
    		$(this).children("div").each(function() {
    			var offset = $(this).offset();
    			var context = newCanvas.getContext("2d");
    			context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    			context.fillText($(this).html(),
    				offset.left - baseOffset.left,
    				offset.top - baseOffset.top + 10
    			);
    		});
    	} else if($(this)[0].tagName.toLowerCase() == 'canvas') {
    		// all other canvas from the chart
    		var offset = $(this).offset();
    		newCanvas.getContext("2d").drawImage(this,
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top
    		);
    	}
    });
            
    // add the point labels
    obj.children(".jqplot-point-label").each(function() {
    	var offset = $(this).offset();
    	var context = newCanvas.getContext("2d");
    	context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    	context.fillText($(this).html(),
    		offset.left - baseOffset.left,
    		offset.top - baseOffset.top + 10
    	);
    });
    
    // add the rectangles
    obj.find("*").children(".jqplot-table-legend-swatch").each(function() {
    	var offset = $(this).offset();
    	var context = newCanvas.getContext("2d");
    	context.fillStyle = $(this).css('background-color');
    	context.fillRect(
    		offset.left - baseOffset.left,
    		offset.top - baseOffset.top,
    		15,15
    	);
    });
    	
    // add the legend
    obj.children("table.jqplot-table-legend").each(function() {
    	var offset = $(this).offset();
    	var context = newCanvas.getContext("2d");
    	context.strokeStyle = $(this).css('border-top-color');
    	context.strokeRect(
    		offset.left - baseOffset.left,
    		offset.top - baseOffset.top,
    		$(this).width(),$(this).height()+7
    	);
    });
    
    obj.find("*").children(".jqplot-table-legend td").each(function() {
    	var offset = $(this).offset();
    	var context = newCanvas.getContext("2d");
    	context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    	context.fillText($(this).text(),
    		offset.left - baseOffset.left,
    		offset.top - baseOffset.top + 15
    	);
    });
    
    // then convert the image to base64 format
    picture = newCanvas.toDataURL();
    
  15. Kevin Risden

    This version removes most of the hardcoded values and uses sizes to fix many of the offsets. It also adds a white background to the image so if you copy and paste it doesn't have a black background. It also adds transparent background to the legend.

    function jqplotToImg(obj) {
    	var newCanvas = document.createElement("canvas");
    	newCanvas.width = obj.find("canvas.jqplot-base-canvas").width();
    	newCanvas.height = obj.find("canvas.jqplot-base-canvas").height()+10;
    	var baseOffset = obj.find("canvas.jqplot-base-canvas").offset();
    	
    	// make white background for pasting
    	var context = newCanvas.getContext("2d");
    	context.fillStyle = "rgba(255,255,255,1)";
    	context.fillRect(0, 0, newCanvas.width, newCanvas.height);
    	
    	obj.children().each(function () {
    	// for the div's with the X and Y axis
    		if ($(this)[0].tagName.toLowerCase() == 'div') {
    			// X axis is built with canvas
    			$(this).children("canvas").each(function() {
    				var offset = $(this).offset();
    				newCanvas.getContext("2d").drawImage(this,
    					offset.left - baseOffset.left,
    					offset.top - baseOffset.top
    				);
    			});
    			// Y axis got div inside, so we get the text and draw it on the canvas
    			$(this).children("div").each(function() {
    				var offset = $(this).offset();
    				var context = newCanvas.getContext("2d");
    				context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    				context.fillStyle = $(this).css('color');
    				context.fillText($(this).text(),
    					offset.left - baseOffset.left,
    					offset.top - baseOffset.top + $(this).height()
    				);
    			});
    		} else if($(this)[0].tagName.toLowerCase() == 'canvas') {
    			// all other canvas from the chart
    			var offset = $(this).offset();
    			newCanvas.getContext("2d").drawImage(this,
    				offset.left - baseOffset.left,
    				offset.top - baseOffset.top
    			);
    		}
    	});
    	
    	// add the point labels
    	obj.children(".jqplot-point-label").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    		context.fillStyle = $(this).css('color');
    		context.fillText($(this).text(),
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top + $(this).height()*3/4
    		);
    	});
    	
    	// add the title
    	obj.children("div.jqplot-title").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    		context.textAlign = $(this).css('text-align');
    		context.fillStyle = $(this).css('color');
    		context.fillText($(this).text(),
    			newCanvas.width / 2,
    			offset.top - baseOffset.top + $(this).height()
    		);
    	});
    	
    	// add the legend
    	obj.children("table.jqplot-table-legend").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.strokeStyle = $(this).css('border-top-color');
    		context.strokeRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).width(),$(this).height()
    		);
    		context.fillStyle = $(this).css('background-color');
    		context.fillRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).width(),$(this).height()
    		);
    	});
    	
    	// add the rectangles
    	obj.find("div.jqplot-table-legend-swatch").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.fillStyle = $(this).css('background-color');
    		context.fillRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).parent().width(),$(this).parent().height()
    		);
    	});
    		
    	obj.find("td.jqplot-table-legend").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = $(this).css('font-style') + " " + $(this).css('font-size') + " " + $(this).css('font-family');
    		context.fillStyle = $(this).css('color');
    		context.textAlign = $(this).css('text-align');
    		context.textBaseline = $(this).css('vertical-align');
    		context.fillText($(this).text(),
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top + $(this).height()/2 + parseInt($(this).css('padding-top').replace('px',''))
    		);
    	});
    
    	// convert the image to base64 format
    	return newCanvas.toDataURL("image/png");
    }
    // usage
    picture = jqplotToImg($('#chart1'));
    
  16. Kevin Risden

    This version works with Firefox and Chrome. It deals with background colors better and determining the size of the plot area. It refactors the code to remove some of the duplication. More will be done shortly.

    function getLineheight(obj) {
    	var lineheight;
    	if (obj.css('line-height') == 'normal') {
    		lineheight = obj.css('font-size');
    	} else {
    		lineheight = obj.css('line-height');
    	}
    	return parseInt(lineheight.replace('px',''));
    }
    
    function getTextAlign(obj) {
    	var textalign = obj.css('text-align');
    	if (textalign == '-webkit-auto') {
    		textalign = 'left';
    	}
    	return textalign;
    }
    
    function printAtWordWrap(context, text, x, y, fitWidth, lineheight) {
    	var textArr = [];
    	fitWidth = fitWidth || 0;
    
    	if (fitWidth <= 0) {
    		textArr.push(text);
    	}
    	
    	var words = text.split(' ');
    	var idx = 1;
    	while (words.length > 0 && idx <= words.length) {
    		var str = words.slice(0, idx).join(' ');
    		var w = context.measureText(str).width;
    		if (w > fitWidth) {
    			if (idx == 1) {
    				idx = 2;
    			}
    			textArr.push(words.slice(0, idx - 1).join(' '));
    			words = words.splice(idx - 1);
    			idx = 1;
    		} else {
    			idx++;
    		}
    	}
    	if (words.length && idx > 0) {
    		textArr.push(words.join(' '));
    	}
    	if (context.textAlign == 'center') {
    		x += fitWidth/2;
    	}
    	if (context.textBaseline == 'middle') {
    		y -= lineheight/2;
    	} else if(context.textBaseline == 'top') {
    		y -= lineheight;
    	}
    	for (idx = textArr.length - 1; idx >= 0; idx--) {
    		var line = textArr.pop();
    		if (context.measureText(line).width > fitWidth && context.textAlign == 'center') {
    			x -= fitWidth/2;
    			context.textAlign = 'left';
    			context.fillText(line, x, y + (idx+1) * lineheight);
    			context.textAlign = 'center';
    			x += fitWidth/2;
    		} else {
    			context.fillText(line, x, y + (idx+1) * lineheight);
    		}
    	}
    }
    
    function findPlotSize(obj) {
    	var width = obj.width();
    	var height = obj.height();
    	var legend = obj.find('.jqplot-table-legend');
    	if (legend.position()) {
    		height = legend.position().top + legend.height();
    	}
    	obj.find('*').each(function() {
    		var offset = $(this).offset();
    		tempWidth = offset.left + $(this).width()
    		tempHeight = $(this).height()
    		if(tempWidth > width) {width = tempWidth;}
    		if(tempHeight > height) {height = tempHeight;}
    	});
    	return {width: width, height: height};
    }
    
    function jqplotToImg(obj) {
    	var newCanvas = document.createElement("canvas");
    	var size = findPlotSize(obj);
    	newCanvas.width = size.width;
    	newCanvas.height = size.height;
    	
    	// check for plot error
    	var baseOffset = obj.offset();
    	if (obj.find("canvas.jqplot-base-canvas").length) {
    		baseOffset = obj.find("canvas.jqplot-base-canvas").offset();
    		baseOffset.left -= parseInt(obj.css('margin-left').replace('px', ''));
    	}
    
    	// fix background color for pasting
    	var context = newCanvas.getContext("2d");
    	var backgroundColor = "rgba(255,255,255,1)";
    	obj.children(':first-child').parents().each(function () {
    		if ($(this).css('background-color') != 'transparent') {
    			backgroundColor = $(this).css('background-color');
    			return false;
    		}
    	});
    	context.fillStyle = backgroundColor;
    	context.fillRect(0, 0, newCanvas.width, newCanvas.height);
    	
    	// add main plot area
    	obj.find('canvas').each(function () {
    		var offset = $(this).offset();
    		newCanvas.getContext("2d").drawImage(this,
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top
    		);
    	});
    	
    	obj.find(".jqplot-series-canvas > div").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.fillStyle = $(this).css('background-color');
    		context.fillRect(
    			offset.left - baseOffset.left - parseInt($(this).css('padding-left').replace('px', '')),
    			offset.top - baseOffset.top,
    			$(this).width() + parseInt($(this).css('padding-left').replace('px', '')) + parseInt($(this).css('padding-right').replace('px', '')),
    			$(this).height() + parseInt($(this).css('padding-top').replace('px', '')) + parseInt($(this).css('padding-bottom').replace('px', ''))
    		);
    		context.font = [$(this).css('font-style'), $(this).css('font-size'), $(this).css('font-family')].join(' ');
    		context.fillStyle = $(this).css('color');
    		context.textAlign = getTextAlign($(this));
    		var txt = $.trim($(this).html()).replace(/<br style="">/g, ' ');
    		var lineheight = getLineheight($(this));
    		printAtWordWrap(context, txt, offset.left-baseOffset.left, offset.top - baseOffset.top - parseInt($(this).css('padding-top').replace('px', '')), $(this).width(), lineheight);
    	});
    	
    	// add x-axis labels, y-axis labels, point labels
    	obj.find('div.jqplot-axis > div, div.jqplot-point-label, div.jqplot-error-message, .jqplot-data-label, div.jqplot-meterGauge-tick, div.jqplot-meterGauge-label').each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = [$(this).css('font-style'), $(this).css('font-size'), $(this).css('font-family')].join(' ');
    		context.fillStyle = $(this).css('color');
    		var txt = $.trim($(this).text());
    		var lineheight = getLineheight($(this));
    		printAtWordWrap(context, txt, offset.left-baseOffset.left, offset.top - baseOffset.top - 2.5, $(this).width(), lineheight);
    	});
    	
    	// add the title
    	obj.children("div.jqplot-title").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = [$(this).css('font-style'), $(this).css('font-size'), $(this).css('font-family')].join(' ');
    		context.textAlign = getTextAlign($(this));
    		context.fillStyle = $(this).css('color');
    		var txt = $.trim($(this).text());
    		var lineheight = getLineheight($(this));
    		printAtWordWrap(context, txt, offset.left-baseOffset.left, offset.top - baseOffset.top, newCanvas.width - parseInt(obj.css('margin-left').replace('px', ''))- parseInt(obj.css('margin-right').replace('px', '')), lineheight);
    	});
    	
    	// add the legend
    	obj.children("table.jqplot-table-legend").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.strokeStyle = $(this).css('border-top-color');
    		context.strokeRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).width(),$(this).height()
    		);
    		context.fillStyle = $(this).css('background-color');
    		context.fillRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).width(),$(this).height()
    		);
    	});
    	
    	// add the swatches
    	obj.find("div.jqplot-table-legend-swatch").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.fillStyle = $(this).css('border-top-color');
    		context.fillRect(
    			offset.left - baseOffset.left,
    			offset.top - baseOffset.top,
    			$(this).parent().width(),$(this).parent().height()
    		);
    	});
    		
    	obj.find("td.jqplot-table-legend").each(function() {
    		var offset = $(this).offset();
    		var context = newCanvas.getContext("2d");
    		context.font = [$(this).css('font-style'), $(this).css('font-size'), $(this).css('font-family')].join(' ');
    		context.fillStyle = $(this).css('color');
    		context.textAlign = getTextAlign($(this));
    		context.textBaseline = $(this).css('vertical-align');
    		var txt = $.trim($(this).text());
    		var lineheight = getLineheight($(this));
    		printAtWordWrap(context, txt, offset.left-baseOffset.left, offset.top - baseOffset.top + parseInt($(this).css('padding-top').replace('px','')), $(this).width(), lineheight);
    	});
    
    	// then convert the image to base64 format
    	return newCanvas.toDataURL("image/png");
    }
    // usage
    picture = jqplotToImg($('#chart1'));
    
  17. Anonymous

    Hi, I was wondering whether anybody knows why I could not stream the image through the wire. What I have done is basically POST the base64 image string generated by this "return newCanvas.toDataURL("image/png");" back to the server, and on the server side, I decode the base64 to a png image, and try to stream the image with struts2 back so that the user can download it effortlessly. Everything looks fine when I write the byteArray directly to the disc. But for some weird reason struts2 refuses to stream it. I get the following error "The image cannot be displayed because it contains errors" Any suggestion will be highly appreciated

  18. Anonymous

    Hi I am trying to export displayed graph in pdf or in a , Also I am still not able to save it as image, I tried the above mentioned code, it doesnt work with IE and save as blank image with firefox, Please let know how can I save displayed graphs as pdf/ ppt . it would be a great help, thank you

  19. Anonymous

    I just tried compuwizard123's code with various charts and it worked great. This should definitely be part of base jqplot.

  20. Anonymous

    Is the any progress in adding the image export feature in the standard jqplot codebase?

  21. Anonymous

    Thanks compu for all the hard work you've put in. I'm using it and it works very well, except for the fact that there's a large amount of padding to the right of the graph as compared to the original, and the title - which is centered on the full width - is therefore centered to the right of where it's supposed to be.

    Any ideas of what could cause your script not to calculate the width correctly? A required setting for your script to work? A jqplot option that causes it to break down?

    Thanks, Jeremy

  22. Anonymous

    Just an FYI that I found it to do with this portion of the code:

    	    obj.find('*').each(function() {
    		   var offset = $(this).offset();
    		   alert(offset.left);
    		   tempWidth = offset.left + $(this).width()
    		   tempHeight = $(this).height()
    		   if(tempWidth > width) {width = tempWidth;}
    		   if(tempHeight > height) {height = tempHeight;}
    	    });
    

    I commented it out and it works fine. Not sure what this portion is attempting to accomplish but I'm sure it has to do w/a feature. Just FYI that nothing else renders on my plot and it's width stays the same.

  23. Anonymous

    Actually, you don't have to comment out the whole chunk. This code is necessary when you have additional canvas elements in the plot canvas such as a legend.

    If you change

    var offset = $(this).offset(); to : var offset = $(this).position().

    it works properly.In Jquery $.offset() returns the 'left' attribute in respect to the window, where $.position() returns the attribute in respect to the parent element. If the parent element does not have the left attribute=0 the incorrect width is returned.

    Here it is in context:

    	    obj.find('*').each(function() {
    		   var offset = $(this).position();
    		   tempWidth = offset.left + $(this).width();
    		   tempHeight = $(this).height();
    		   if(tempWidth > width) {width = tempWidth;}
    		   if(tempHeight > height) {height = tempHeight;}
    	    });
    
  24. Kevin Risden

    Anonymous - Thanks for checking out my code and seeing how it works. I tried both .offset() and .position(). I don't remember exactly (finished up internship in September and have had class) why I used offset. I was testing the export across all graphs in the examples and offset may have been better in more cases. I know there was some spacing issues, but hopefully they are mostly resolved now. This summer I may have another chance to work on improving this great library.

  25. Anonymous

    The title did not work for me (using the code in #21 above). When I replaced 'obj.children' with 'obj.find' in the title part, it worked great. Thanks!

  26. Anonymous

    Thx for the Great Work! For version #21 i just added "div.jqplot-title" on line 138 for export title

    Great Thx

  27. Anonymous

    I tried above code for image conversion, it works fine in firefox but not in IE 8. On further investigation, I noticed

    the code blows up on newCanvas.getContext("2d"); even with excanvas.js.

    My client has requested pdf export and I'm struck now. Unfortunately, majority of the users have IE.

    Please help...

  28. Thang Pham

    Kevin Risden, your code is awesome, however, there still some spacing and format issue. Did you have anymore time to revisit your code and fix some of these spacing issue, compuwizard123? Thank you

  29. rajsharan

    I used this code to export to image.... //after creating your plot do var imgData = $('#chart1').jqplotToImageStr({}); // given the div id of your plot, get the img data var imgElem = $('<img/>').attr('src',imgData); // create an img and add the data to it $('#imgChart1').append(imgElem);​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ //

  30. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.