How to export kendoui dataviz chart to (.png) or (.jpg) image format by poping up Save-As window? - charts

I am using kendoui dataviz charts, and I need to export those charts into (.png) or (.jpg) image format.
Basically kendoui dataviz chart has a built-in method called 'svg()'.
'svg()' Returns the SVG representation of the current chart. The returned string is a self-contained SVG document.
Example
var chart = $("#chart").data("kendoChart");
var svgText = chart.svg();
Now svgText contains details of chart image..can anybody tell me how to convert these data to actual image format and pop up a Save As prompt ???
code example: I tried this, but it doesn't prompt any 'SaveAs' popup
<div id="example" class="k-content">
<div class="chart-wrapper">
<div id="chart"></div>
<center>
<div>
<input type="button" value="click" onclick="disp();" />
</div>
</center>
<div>
<canvas id="canvas"></canvas>
</div>
</div>
</div>
<script type="text/javascript">
function disp() {
var chart = $("#chart").data("kendoChart");
var svgText = chart.svg();
var c = document.getElementById('canvas');
canvg(c,svgText);
var img = c.toDataURL("image/png");
document.write('<img src="' + img + '"/>');
window.win = open(imgOrURL);
setTimeout('win.document.execCommand("SaveAs")', 100);
}
function createChart() {
$("#chart").kendoChart({
theme: $(document).data("kendoSkin") || "default",
title: {
text: "Internet Users"
},
legend: {
position: "bottom"
},
chartArea: {
background: ""
},
seriesDefaults: {
type: "bar"
},
series: [{
name: "World",
data: [15.7, 16.7, 20, 23.5, 26.6]
}, {
name: "United States",
data: [67.96, 68.93, 75, 74, 78]
}],
valueAxis: {
labels: {
format: "{0}%"
}
},
categoryAxis: {
categories: [2005, 2006, 2007, 2008, 2009]
},
tooltip: {
visible: true,
format: "{0}%"
}
});
}
$(document).ready(function () {
setTimeout(function () {
createChart();
},100);
$(document).bind("kendo:skinChange", function (e) {
createChart();
});
});
<script>

UPDATE 2
The Chart now includes various export options - PNG, SVG and a vector PDF. See the Export demo for reference.
UPDATE
The Chart now has built-in method for obtaining the exported image (base64 encoded):
var img = chart.imageDataURL();
I'm not aware of a cross-browser way to display a "Save As" dialog.
See also: API Reference
Original response follows:
Exporting the Chart image in-browser is not possible. We have prepared a demo that shows how to convert the SVG document to PNG/PDF on the server using Inkscape.
The demo application is implemented in ASP.NET MVC, but does not depend on any of its features and can be ported to other frameworks.
You can find the demo on GitHub:
https://github.com/telerik/kendo-examples-asp-net/tree/master/chart-inkscape-export

U can do like this.
For this approach u need svg.dll
U can download from this link.
http://svg.codeplex.com/releases/view/18884
Javascript:
var chart = $("#chart").data("kendoChart");
var svgString = escape(chart.svg());
$.ajax({
url: "/MyController/Sample",
data: { svg: svgString },
async: false,
type: 'Post',
success: function (data) {
window.location = "/MyController/getPdf";
}
});
Controller:
[HttpPost]
[ValidateInput(false)]
public void Sample(string svg)
{
var svgText = System.Web.HttpUtility.UrlDecode(svg);
Session["chrtData"] = svgText;
}
public void getPdf()
{
string svgText = Session["chrtData"].ToString();
var byteArray = Encoding.ASCII.GetBytes(svgText);
using (var stream = new MemoryStream(byteArray))
{
var svgDocument = Svg.SvgDocument.Open(stream);
//First Way
var bitmap = svgDocument.Draw();
MemoryStream docMemStream = new MemoryStream();
bitmap.Save("D:\\hi.png", System.Drawing.Imaging.ImageFormat.Png);
}
}

Related

Google visualisation with Chartrangeslider and data import from Google docs spreadsheet

I have the problem, that I dont manage to implement my data from a google spread sheet when using dashboard environment with chartwrapper and controlwrapper. I used the piechart example from the google charts website (https://developers.google.com/chart/interactive/docs/gallery/controls) and tried to modify without success. Maybe somebody can provide a pointer ! Thanks in advance (link to jsfiddle : https://jsfiddle.net/Chriseif/08mk90hu/1/#&togetherjs=MHq11Kn3hl)
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript"
src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load the Visualization API and the controls package.
google.charts.load('current', {'packages':['corechart', 'controls']});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawDashboard);
// Callback that creates and populates a data table,
// instantiates a dashboard, a range slider and a pie chart,
// passes in the data and draws it.
function drawDashboard() {
var query = new
google.visualization.Query("https://docs.google.com/spreadsheets/d/
1uJNf8RgPjcjm3pUWig0VL4EEww1PG-bNL8mtcxI6SYI/edit");
query.send(response);
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' '
+ response.getDetailedMessage());
return;
}
var data1 = response.getDataTable();
}
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div'));
// Create a range slider, passing some options
var donutRangeSlider = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'filter_div',
'options': {
'filterColumnIndex ': 2
}
});
// Create a pie chart, passing some options
var pieChart = new google.visualization.ChartWrapper({
'chartType': 'LineChart',
'containerId': 'chart_div',
'options': {
'width': 900,
'height': 300,
'pieSliceText': 'value',
'legend': 'right'
}
});
// Establish dependencies, declaring that 'filter' drives
'pieChart',
// so that the pie chart will only display entries that are let
through
// given the chosen slider range.
dashboard.bind(donutRangeSlider, pieChart);
// Draw the dashboard.
dashboard.draw(data1);
}
</script>
</head>
<body>
<!--Div that will hold the dashboard-->
<div id="dashboard_div">
<!--Divs that will hold each control and chart-->
<div id="filter_div"></div>
<div id="chart_div"></div>
</div>
</body>
</html>
first, the query.send method is asynchronous, and accepts an argument for a callback function
because you need to wait for the data from the query,
all of the dashboard code should be inside the callback
else it will run before the data is returned...
// the argument should be the name of a function
query.send(handleQueryResponse);
// callback function to be called when data is ready
function handleQueryResponse(response) {
//draw dashboard here...
next, the range filter should operate on the column used for the x-axis
unless you are using a view, it will be column index 0 (zero is the first index)
var rangeSlider = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'filter_div',
options: {
filterColumnIndex: 0 // <-- x-axis column
}
});
also, when drawing charts from a spreadsheet,
you need to set a specific number format on each axis,
otherwise, it will display the word general as part of the number...
var chart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart_div',
options: {
width: 900,
height: 300,
pieSliceText: 'value',
legend: 'right',
// set number formats
hAxis: {
format: '#,##0'
},
vAxis: {
format: '#,##0'
}
}
});
see following working snippet...
google.charts.load('current', {
packages: ['corechart', 'controls']
}).then(function () {
var query = new google.visualization.Query("https://docs.google.com/spreadsheets/d/1uJNf8RgPjcjm3pUWig0VL4EEww1PG-bNL8mtcxI6SYI/edit");
query.send(handleQueryResponse);
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data1 = response.getDataTable();
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div')
);
var rangeSlider = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'filter_div',
options: {
filterColumnIndex: 0
}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart_div',
options: {
width: 900,
height: 300,
pieSliceText: 'value',
legend: 'right',
hAxis: {
format: '#,##0'
},
vAxis: {
format: '#,##0'
}
}
});
dashboard.bind(rangeSlider, chart);
dashboard.draw(data1);
}
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_div">
<div id="filter_div"></div>
<div id="chart_div"></div>
</div>

Dojo create image with link

Is there a way to use dojo/dom-construct to create an image element with a link? I am looking for equivalent of the following HTML code:
<a href="test.html" target="_blank">
<img src="/pix/byron_bay_225x169.jpg" >
</a>
Yes it is possible!
Just do it like this:
var anchor= domConstruct.create('a', {
'href': 'test.html',
'target': '_blank'
});
var image= domConstruct.create('img', {
'src': '/pix/byron_bay_225x169.jpg'
});
domConstruct.place(image, anchor);
HTML:
<div data-dojo-attach-point="container"></div>
JS:
var img = domConstruct.create("img", {
src: "/path/image.png",
style: "height:16px;width:16px;",
title: "Image",
onclick: function(){
// onclick event
},
onmouseenter: function(){
// on mouse over event
},
onmouseout: function(){
// on mouse out event
}
);
domConstruct.place(img, this.container);

How to add "select" in dojo tooltipdialog content programmatically?

I want to display dojo select inside a dijit/TooltipDialog. The items of the dojo select are dynamically loaded. So I want to add this select programmaticaly. The content of TooltipDialog can be an object but select needs a domNode to be held. The code is :
<head>
<script>
require([
"dojo/parser",
"dijit/form/Select",
"dijit/TooltipDialog",
"dojo/on",
"dojo/dom",
"dojo/_base/lang",
"dijit/popup",
"dojo/data/ObjectStore",
"dojo/store/Memory",
"dojo/domReady!"
], function(parser,Select,TooltipDialog,on,dom,lang,popup, ObjectStore, Memory){
parser.parse();
var t={mySel:null};
var store = new Memory({
data: [
{ id: "foo", label: "Foo" },
{ id: "bar", label: "Bar" }
]
});
var os = new ObjectStore({ objectStore: store });
t.mySel = new Select({
store: os
}, "ttt");
var myTooltipDialog = new TooltipDialog({
content: t,
onMouseLeave: function(){
popup.close(myTooltipDialog);
}
});
on(dom.byId("mmm"),"mouseover" ,lang.hitch(this,function(e){
popup.open({
popup: myTooltipDialog,
orient: ["above-centered","above","below"],
around:dom.byId('mmm')
});
t.mySel.startup();
}));
t.mySel.on("change", function(){
console.log("my value: ", this.get("value"))
})
})
</script>
</head>
<body class="claro">
<div id="ttt" > tttt</div><br>
<div id="mmm" > tttt</div><br>
</body>
You are assignign an object t the tooltip content not a domenode
so try to make these change :
var myTooltipDialog = new TooltipDialog({
content: t.mySel.domNode,
onMouseLeave: function() {
popup.close(myTooltipDialog);
}
}

KendoUI: Unable to bind data to HTML elements from JSON file.

I am new to kendo ui and mvvm, and I'm facing this issue:
I'm having a JSON file in the follow format:
[
{
"Id":1,
"img":"shoes.png"},
{"Id":2,
"img":"books.png"}
}
]
I am reading the file using the sample mentioned online by kendo guys as follows:
var crudServiceBaseUrl = "pro.json";
var viewModel = kendo.observable({
productsSource: new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl,
dataType: "json"
},
update: {
url: crudServiceBaseUrl,
dataType: "json"
},
destroy: {
url: crudServiceBaseUrl,
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
return options;
}
},
batch: true,
schema: {
model: {
id: "Id"
}
}
})
});
kendo.bind($("#form-container"), viewModel);
I am able to bind the data from the data source to a Kendo Control such as a dropdownlist or some other Kendo Control. But when I try binding the data to an HTML Control (mostly an img tag). It stops working and gives an error saying "this.parent" is not a function.
following is the HTML which works:
Select Product: <select data-role="dropdownlist" data-value-field="Id" data-text-field="img"
data-bind="source: productsSource"></select>
However binding to a normal <img> tag does not work. In short I need to bind images based on src value to a div using kendo ui mvvm.
Kindly help me out. Thanks!!
-
Hardik
Currently Kendo MVVM cannot bind a data source to an HTML element. Only Kendo UI widgets can be bound to a kendo.data.DataSource. Using a widget e.g. the ListView would work for a DIV:
<div data-role="listview"
data-template="template"
data-bind="source: productsSource">
</div>
<script id="template" type="text/x-kendo-template">
<img data-bind="attr: { src: img }" />
</script>

Replacing Filepicker files after editing with Aviary

I have an Edit button next to each uploaded thumbnail on my page that summons the Aviary modal upon click. What I'd like to do is replace the original file on FP when I save the outcome of editing in Aviary.
filepicker.saveAs doesn't seem like the right solution because I don't want to save to a new file, I just want to replace the file on FP.
The "Saving Back" documentation doesn't seem to apply because it says to POST a full file to the original URL. Ideally I'd like to just have a function take the original url and the new Aviary URL and replace the contents at the original URL.
Is this possible at the moment? Thanks!!!
I've pasted my code here:
<script src='http://feather.aviary.com/js/feather.js'></script>
<script src="https://api.filepicker.io/v0/filepicker.js"></script>
<script type="text/javascript">
$(document).on('click', '.delete-image', function(e) {
var image = $(this).closest('tr').attr('data-image');
$('.modal-footer .btn-danger').remove();
$('.modal-footer').append("<button class='delete-confirmed btn btn-danger' data-image='"+image+"'>Delete</button>");
$('#myModal').modal('show');
return false;
});
$(document).on('click', '.delete-confirmed', function(e) {
e.preventDefault();
var image = $(this).attr('data-image');
var row = $("tr[data-image="+image+"]");
$('#myModal').modal('hide');
$.ajax({
url: row.attr('data-link'),
dataType: 'json',
type: 'DELETE',
success: function(data) {
if (data.success) {
row.hide();
filepicker.revokeFile(row.attr('data-fplink'), function(success, message) {
console.log(message);
});
}
}
});
return false;
});
//Setup Aviary
var featherEditor = new Aviary.Feather({
//Get an api key for Aviary at http://www.aviary.com/web-key
apiKey: '<%= AVIARY_KEY %>',
apiVersion: 2,
appendTo: ''
});
//When the user clicks the button, import a file using Filepicker.io
$(document).on('click', '.edit-image', function(e) {
var image = $(this).closest('tr').attr('data-image');
var url = $(this).closest('tr').attr('data-fplink');
$('#aviary').append("<img id='img-"+image+"'src='"+url+"'>");
//Launching the Aviary Editor
featherEditor.launch({
image: 'img-'+image,
url: url,
onSave: function(imageID, newURL) {
//Export the photo to the cloud using Filepicker.io!
//filepicker.saveAs(newURL, 'image/png');
console.log('savin it!');
}
});
});
filepicker.setKey('<%= FILEPICKER_KEY %>');
var conversions = { 'original': {},
'thumb': {
'w': 32,
'format': 'jpg'
},
};
$(document).on("click", "#upload-button", function() {
filepicker.getFile(['image/*'], { 'multiple': true,
'services': [filepicker.SERVICES.COMPUTER, filepicker.SERVICES.URL, filepicker.SERVICES.FLICKR, filepicker.SERVICES.DROPBOX, filepicker.SERVICES.IMAGE_SEARCH],
'maxsize': 10000*1024,
'conversions': conversions
},
function(images){
$.each(images, function(i, image) {
$.ajax({
url: "<%= product_images_path(#product.id) %>",
type: 'POST',
data: {image: JSON.stringify(image)},
dataType: 'json',
success: function(data) {
if (data.success) {
$('.files').append('<tr><td><img src="'+image.data.conversions.thumb.url+'"</td></tr>')
}
}
});
});
});
});
You actually can POST a url to the filepicker url as well, for example
curl -X POST -d "url=https://www.filepicker.io/static/img/watermark.png"
https://www.filepicker.io/api/file/gNw4qZUbRaKIhpy-f-b9
or in javascript
$.post(fpurl, {url: aviary_url}, function(response){console.log(response);});