Convert Canvas to image and save to disc - c#

There are many similar questions already, but for some reason they do not solve my issue.
My project is to save a dynamically created page (or part of the page). The user will have the option to drag objects on screen and leave them in any order and then for this order to be saved to disc as an image.
My own research shows that I can use Draggable from JQuery and this is easy to implement. It is the saving part where I am stuck.
I followed a few links, but the image does not appear to be saving to disc and I don't think it works in IE! However, I'm happy with FireFox and so using the toDataUrl() sounds like the best approach.
Since I couldn't get it work I decided to change tactic slightly and pass the value to the code behind (C#)
The save part of my code looks like
<script>
function SaveMe() {
var canvas = document.getElementById("mycanvas");
var image = canvas.toDataUrl();
document.getElementById("hideMe").value = image;
}
</script>
When I debug in FireBug, I never reach document.getElementById("hideMe").value = image;. I step through but can never get past var image = canvas.toDataUrl(); Is this expected behavior as I assume not but there is no error message?
The body of my HTML is
<body>
<script type="text/javascript">
$(document).ready(function () {
$('.popup_click').show(0).draggable();
});
</script>
<form id="form1" runat="server">
<div class="popup_click">
<div id="popup_title">Title</div>
</div>
<canvas id="mycanvas" class="canvas"></canvas>
<asp:HiddenField ID="hideMe" runat="server" />
<asp:Button runat="server" OnClick="ClickMe" text="Click" OnClientClick="SaveMe()"/>
</form>
</body>
What am I doing wrong? I'm working locally in debug mode, Visual Studio 2013.

Not absolutely sure, but I also had a problem with todataurl() in the past and this link helped me
Not able to get data url when using images in kinetic js

This is the function I always use when wanting to export a canvas to image, it puts the image into a popup window so the user can do what they want with it (I hope this helps):
function imageCanvas(evt){
var imageCanvas = document.createElement('canvas');
imageCanvas.width = document.documentElement.clientWidth;
imageCanvas.height = document.documentElement.clientHeight;
var imageCanvasContext = imageCanvas.getContext("2d");
imageCanvasContext.fillStyle = document.getElementById("body").style.backgroundColor;
imageCanvasContext.fillRect(0,0,imageCanvas.width,imageCanvas.height);
imageCanvasContext.drawImage(mainCanvas,0,0,imageCanvas.width,imageCanvas.height,0,0,imageCanvas.width,imageCanvas.height);
var dataURL = imageCanvas.toDataURL("image/png");
var imagePopup = window.open("","fractalLineImage","left=0,top=0,width="+(imageCanvas.width/2)+",height="+(imageCanvas.height/2)+",toolbar=0,resizable=0");
imagePopup.document.write("<title>Export Image</title>");
imagePopup.document.write("<img id='exportImage'"
+" alt=''"
+" height='"+ imageCanvas.height+"'"
+" width='"+ imageCanvas.width+"'"
+" style='position:absolute;left:0;top:0'/>");
imagePopup.document.close();
var exportImage = imagePopup.document.getElementById("exportImage");
exportImage.src = dataURL;
}

Related

Execute javascript code at the end of event handler

I'm building a web application on ASP.NET with C#.
On a button click I show a loading image, while the database query is being executed. Then I dynamically create an Excel file and send it to the client like this:
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + filename + ".xlsx");
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Unicode;
HttpContext.Current.Response.BinaryWrite(p.GetAsByteArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
I get the dialog box, and the loading image stays there.
I've tried placing call to a javascript function (with ClientScript.RegisterStartupScript function) before the code above, it didn't work. As I understand all javascript code is run after all the code-behind has executed, but in this case it doesn't execute at all once the file is sent to the client.
I've also tried creating a separate thread, and removing the loading image there. I put the breakpoint to trace it, code in the thread does execute, but the image still stays there.
Does anyone have an idea how this can be handled? Thank you!
You can only send or transmit 1 mime type in one request/response cycle. (My knowledge in this area is debatable).
That said, you can design a hack around this. Use an iframe on the client to "download the file". You can point its src to an ashx file that does the same.
You need to wire the iframe's onload event, so your web page has someway of knowing that download is done; thats where you can execute your logic.
Solution Update:
Well, after digging around, I've discovered my answer is half-baked!
The issue is that iframes don't trigger their onload event after they download something. The onload event will trigger iff there the url pointed to by src actually navigates to a different page. This is by design I suppose. And I learn that today!
So what then is the work-around?!
Fortunately, you can transmit cookies to the client. On the client your web page has to keep polling for the presence of this cookie. So once your web page is able to detect the presence of the cookie, it means that the browser has completed with the download request. This has been discussed in great detail in the following post:
http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx
I'll just show you some code relating to the handler file (which simulates a download), and the client (which has an iframe doing the job). This should pretty much give you the gist:
Webform1.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApp.FileDownload.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>iFrame Download</title>
<script type="text/javascript" src="Scripts/jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="Scripts/jquery.cookie.js"></script>
<script type="text/javascript">
function foo() {
console.log('foo');
//execute post-download logic here
}
$(function () {
$('input').click(function () {
//make sure we get rid of the
//cookie before download
$.removeCookie('downloaded');
var intrvl = setTimeout(function () { //this function polls for the cookie through which we track that the file has indeed been downloaded
console.log('timer');
var value = $.cookie('downloaded');
if (value == 'true') {
clearTimeout(intrvl);
foo();
}
}, 1000);
//this initiates the download
$('iframe').attr({
'src': 'download.ashx?id=' + $('#tbxRandomNumber').val()
});
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="tbxRandomNumber" runat="server"></asp:TextBox>
<input type="button" value="Download" />
<iframe src="about:blank" style="display:none"></iframe>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Next Random Number" />
</div>
</form>
</body>
</html>
I've made used of jquery cookies plugin to help me with handling cookies.
download.ashx:
using System;
using System.Web;
namespace WebApp.FileDownload
{
/// <summary>
/// Summary description for download
/// </summary>
public class download : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.SetCookie(new HttpCookie("downloaded","true")); //setting cookie in the response
string id = context.Request.QueryString["id"] == null ? "NULL" : context.Request.QueryString["id"];
string str = string.Format("Content with id {0} was generated at {1}", id, DateTime.Now.ToLongTimeString());
context.Response.AddHeader("Content-Disposition", "attachment; filename=test.txt");
context.Response.AddHeader("Content-Length", str.Length.ToString());
context.Response.Write(str);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
It looks like you have a couple of misunderstandings here. You only have one request, and one response from the server. Making new threads is something that only happens on the server, and won't create additional responses.
When you're sending the Excel file, you're using:
HttpContext.Current.Response.Clear();
By clearing the response, you're losing the JavaScript that you added previously. It will never get to the client.
If the processing is fairly trivial (always just a couple of seconds), I'd just set the loading animation to run for a couple of seconds and stop, by setting a timeout on the initial onclick event. It's not perfect, but it'll give the user some immediate feedback.
If the processing is going to take a long or very variable amount of time, then the animation is more important to get right. You can try loading your Excel file in a hidden <iframe>, and attaching an onload event to remove the loading animation.
You would need to create a separate page to handle generating the Excel file, rather than doing it in a server-side OnClick handler. However, I seem to remember that support for onload events on <iframe> can be spotty with older IE versions.
javascript run in the client when page is loading in the browser. You may have a hidden textbox, at the end of you event yo can put a value into that textbox:
txtHidden.Text = "Hola Mundo"
You have to check the value on page load:
<script type="text/javascript">
$(document).ready(function(){
if($("#txtHidden").length > 0 && $("#txtHidden").val() != '')
{
alert($("#txtHidden").val());
}
});
</script>
You can put this in a web user control.
Another solution:
<div class='button' id='btnGenerateDownload' onClick='GenerateDownload(this)'>
Click here <div id='loadingImage' class='loadingImage'></div>
</div>
JQuery:
function GenerateDownload(caller)
{
//add loading gif:
var $loagingGIF = $(caller).children('#loadingImage').eq(0);
$loagingGIF.addClass('loadingImage');
var fileGeneratorUrl = 'ghFileGenerator.ashx';
var downloadHandlerUrl = 'ghDownloadHandler.ashx';
$.post({data: "File1"}, function(response){
//remove gif
$loagingGIF.removeClass('loadingImage');
if(response != '') //file key
{
downloadHandlerUrl += '?key=' + response;
var $link = $("<a />").attr('href', downloadHandlerUrl).html('download');
$link.appendTo($(caller));
}
});
}
css:
.loadingImage{background: transparent url(images/loading.gif);}
.ashx:
string filekey = context.Current.Request.Form("key");

Youtube embedded player: Event when video has ended

I'm creating an application which plays youtube videos in C# (winform). Now i'd like to fire an event, or something like that, when the video has ended.
I'm using the webbrowser control and call a youtube video like this:
wbYoutube.Navigate("http://www.youtube.com/v/" + playString[1] + "?version=3&enablejsapi=1&autoplay=1");
playString[1] is the youtube video id (like rGJN5K2cV_8).
I've been trying to get this working a few days now, has anyone got an idea on how to achieve this? If it's even possible...
If you need more info, let me know.
Thanks
I think this is possible but you have to write the html code into the browser element by yourself
wbYoutube.DocumentText = "";
Here is the html (You have to escape it)
<html><head></head><body>
<script type='text/javascript' src='http://www.youtube.com/player_api'></script>
<iframe id="player" width="100%" height="100%" src="http://www.youtube.com/embed/VIDEO_ID?autoplay=1&controls=0&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
<script type="text/javascript">
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
videoId: 'VIDEO_ID',
events: {
'onStateChange': function(evt){
if(evt.data == 0){
window.external.Test('Video finished!!');
}
}
}
});
}
</script>
</body></html>
And have a look at Implement Two-Way Communication Between DHTML Code and Client Application Code
There you find the rest of the code.

Change the theme of Recaptcha?

I use the Following script for change recaptcha in asp.net with c# server side.But this code Didn't Work.How to change color or theme of the ReCaptcha?
<script type="text/javascript">
var RecaptchaOptions = {theme : 'White'};
</script>
I think you are just writing the name of the theme in wrong way, just try White with a small 'w'.
<script type="text/javascript">
var RecaptchaOptions = {theme : 'white'};
</script>
See this link for exact working code:
https://developers.google.com/recaptcha/docs/customization
George Siggouroglou's second method for asp.net is a charm
I couldn't seem to set the theme as instructed in https://developers.google.com/recaptcha/docs/customization - placed the js above the form containing the recaptcha control - but adding the theme attribute directly into the recaptcha code as George explained:
<recaptcha:RecaptchaControl
ID="recaptcha"
runat="server"
PublicKey="your-public-key"
PrivateKey="your-private-key"
Theme="white"
/>
works.
U used the capital W instead of small i.e. w
Try this
Change the theme and try
<script type="text/javascript">
var RecaptchaOptions = {
theme : 'white'
/*WE CAN USE FOLLOWING THEME TO CHANGE THE COLOR OF RECAPTHCA*/
/*red,white,blackglass,clean'*/
/*lang :'es';*/ //used to set the language
};
</script>
If you are using asp.net and if you are using the recapctcha for asp.net control, then if you want to change the theme (red(default),white,blackglass,clean) there is two ways.
Way no1,
To make the reCAPTCHA widget display a different theme, you first need to add the following
code in your main HTML page anywhere before the element where reCAPTCHA appears
(this will not work if placed after the main script where reCAPTCHA is first invoked):
<script type="text/javascript">
var RecaptchaOptions = {
theme : 'theme_name'
};
</script>
Way no2:
Add the property 'Theme' to the recapcha asp.net control:
<recaptcha:RecaptchaControl
ID="recaptcha"
runat="server"
PublicKey="your-public-key"
PrivateKey="your-private-key"
Theme="white"
/>

Displaying html links in a different order on page load

I have a bunch of static links currently within a div, however Im after changing the order of the links on page load.
I've considered using a literal and a loop through the links in code behind but im stumped. Maybe a repeater... I need a push in the right direction please!
Im fairly new to this so any help would be much appreciated. Thanks
(c# or vb.Net)
ok so lets say that you would store the links in a Links.txt file because there could be hundreds of links for example..
1. Create the .txt file
2. Make note of the file location.
3. Save the file with the links in them
4. use this code in your project to load the links
List<string> strUrlLinks = new List<string>(File.ReadAllLines(FilePath + FileName.txt));
in code you can then hover over strUrlLinks and you will see the Links
to access the individual links do it based on it's [Index] position
I know you asked for an answer in c# or vb.net and may have some technical restraints on this, but to create this functionality in jQuery is almost trivial considering the links are already hardcoded on the page.
See the example below which sorts in descending order on the link text.
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<div id="linksContainer">
Line 1
Line 3
Line 2
</div>
<script type='text/javascript'>
$(window).load(function(){
var orderDivLinks = function(desc) {
$('div#linksContainer').children().detach().sort(function(a,b) {
var compA = $(a).text();
var compB = $(b).text();
return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
}).appendTo(document.body);
}
orderDivLinks(0);
});
</script>
</body>
</html>

asp.net -> google maps api -> Best way to create a map from an .aspx page

Ok, I am working on a project where an end user will click on a link within a grid that will open a new window. (.aspx page) I have been researching on how to create a google map from the newly opened .aspx page with out writing a bunch of dynamic javascript in the code behind and then registering the clientscript to the page. I have done this in the past but it really isn't pretty and is really cumbersome if you ever need to come back and change things.
The initial version of this map will have a route with multiple points present, a later version of this will provide the ability to have multiple routes within the same map (just to give you an overview of what the end goal is) An example would be a route with points LA to Vegas to Austin.
So, I know this is a very general/vague question, but what I am trying to figure out is the best way to generate a google map from a .aspx page without writing dynamic sql, I am sure others have stumbled across this issue previously. Thoughts/Comments, everything is appreciated. Thanks.
There are some components floating around online, but one technique that's worked well for me is to use a hidden field to hold the address/coordinates/etc., and use the hidden field to populate the map:
<script type="text/javascript">
var map = null;
var geocoder = null;
var address = "<%=hdnMapAddress.Value%>";
showAddress = function() {
var mapContainer = $get("<%=pnlMap.ClientID%>");
if (mapContainer){
if (GBrowserIsCompatible()){
geocoder = new GClientGeocoder();
map = new GMap2(document.getElementById("<%=pnlMap.ClientID%>"));
}
if (geocoder){
geocoder.getLatLng(address,
function(point){
var marker = new GMarker(point);
if (marker){
map.setCenter(point, 12);
map.addOverlay(marker);
}
}
);
}
}
}
</script>
<asp:HiddenField ID="hdnMapAddress" runat="server" />
<asp:Panel ID="pnlMap" runat="server" Height="230">
<!-- map content -->
</asp:Panel>
Code-behind:
hdnMapAddress.Value = "123 Test St, Providence, RI 02904";

Categories

Resources