I can't get JSignature canvas data in code behind from hidden field - html

I'm using jSignature to capture the users signature, after that I would like to put it into a database, I have the signature panel showing and when I send the data into an alert box I can see it, also I have a asp.net hidden field in the page were I'm storing the data, the problem is that I can't get the data into my code behind so I can store it in the database.
<telerik:RadCodeBlock runat="server">
<script src="../Scripts/JSignature/jquery-1.9.0.min.js"></script>
<script src="../Scripts/JSignature/jSignature.min.js"></script>
<script type="text/javascript">
function SaveCanvasImage() {
var image = $('#signature').jSignature('getData', 'base30');
var hdnField = $('#<%= hdnSignature.ClientID %>');
$('#<%=btnHidden.ClientID %>').click();
return false;
}
</script>
<script>
function pageLoad() {
InitSignaturePanel(); //this is a function in a global js file.
}
</script>
</telerik:RadCodeBlock>
<!--[if lt IE 9]>
<script type="text/javascript" src="../Scripts/JSignature/flashcanvas.js"></script>
<![endif]-->
<telerik:RadScriptManager runat="server"></telerik:RadScriptManager>
<div class="width400">
<telerik:RadAjaxPanel runat="server"> <asp:Label runat="server" ID="lblHidden" />
<asp:HiddenField runat="server" ID="hdnSignature" />
<div id="signature" class="trueMargin signaturePanel"></div>
</telerik:RadAjaxPanel>
<div class="textAlignCenter">
<br />
<input type="button" id="clearCanvas" value="Reset" onclick="$('#signature').jSignature('clear')" />
<asp:Button id="btnCaptureCanvas" runat="server" Text="Save and Close" OnClientClick="SaveCanvasImage()" />
<asp:Button runat="server" ID="btnHidden" OnClick="btnHidden_Click" />
</div>
</div>
And in the code behind I have:
protected void btnHidden_Click(object sender, EventArgs e)
{
lblHidden.Text = hdnSignature.Value;
}

Suspect this happens because you actually don't put the signature into the hidden field.
I think you mean to have this:
function SaveCanvasImage() {
var image = $('#signature').jSignature('getData', 'base30');
var hdnField = $('#<%= hdnSignature.ClientID %>').val('data:' + image.join(',')); // <-- note the addition
$('#<%=btnHidden.ClientID %>').click(); // <- what is this for by the way?
return false;
}

Related

Capturing input from a text input field in Google Aps script

I have a spreadsheet at work that contains information on various different devices we use.
The spreadsheet contains information like the Original Equipment Manufacturer, Storage capacity, format, Etc. There are a total of 10 Columns, and up to 359 rows currently; but the spreadsheet will expand from general use.
I have created a sidebar application in google sheets using Aps script and HTML, in order to make requesting support for these objects simpler. I am running in to an issue with capturing the data typed into an input field. Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div class = "Container"><!-- Begin CONTAINER div -->
<div class="row"><!-- Begin ROW div -->
<div class="col s24 "><!-- Beginning of Header div -->
<h5 class="col s24"offset-s3> Edit a Kit </h5>
<div><!-- Text input field for Kit search -->
<div class="input-field col s12">
<textarea id="textarea1" class="materialize-textarea"></textarea>
<label for="textarea1">Enter Kit Name</label>
</div>
</div><!-- end of Text Input for Kit search -->
<!-- Start of Submit btn div -->
<div class="input-field col s12">
<button class="btn waves-effect waves-light" id="search" onclick ="submitData()">Search
<i class="material-icons right">search</i>
</button>
</div><!-- End of Submit btn div -->
<div class="divider"></div>
<div><!-- beginning of kit contents div -->
<!-- Users need to enter kit names into a text input field, similar to the create kit page -->
<h5 id = "kit" class = "section"></h5>
</div><!-- end of kit contents div -->
<div class="divider"></div>
<!-- Start of the HOME PAGE button Div -->
<div class="input-field col s12">
<button class="btn waves-effect waves-light" onclick="google.script.run.withSuccessHandler(changePage).newPage('Card Request Form')">Home
<i class="material-icons right">home</i>
</button>
</div><!-- end of the HOME PAGE button div -->
</div><!-- End of Header div --->
</div><!-- End of ROW Div -->
</div><!-- End of CONTAINER Div -->
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script>
function changePage(page) {
document.write(page);
}
// function alertA() {
// alert("Your code Failed to Run");
// };
function alertB() {
alert("Success! Click 'OK' to see your results");
};
function submitData() {
var data = document.getElementById('search').value;
var outPut = document.getElementById('kit');
var display = outPut.innerHtml = "THIS IS WORKING AS EXPECTED";
// alert(display);
};
function outputCard(submitData) {
};
</script>
</body>
</html>
I am trying to access the input data from the "Submit btn div" using the function "submitData()", but have been unsuccessful in doing so. In the version i've uploaded, I am simply trying to capture that information, and print it back out to the "kit contents div" but have been unsuccessful.
For clarity, I am doing this in a Google Apps scripts, as a sidebar extension to a google sheets spreadsheet. The goal is to take that input, and parse over the information for all of the informaton referenced in the first Full paragraph; and then return any items relevantr to the users search terms in the "kit contents div". I am not able to capture the input in Google Apps script though. Here is a copy of my gs code:
//This function searches for cards by the value typed into the text input field
function cardSearch(data) {
var app = SpreadsheetApp;
var log = app.openById("My Spreadsheet's ID");
var kitContents = app.openById("My Spreadsheet's ID");
var cards = log.getRange("A3:J").getValues();
var kitType = kitContents.getRange("A3:J359").getValues();
for (i=0; i<kitType[data]; i++){
return kitType[data];
}
Logger.log(kitType[356])
// for some reason, the array literal ends at index #356, where as the spreadsheet is up to 359 rows, but stops at ID#354
};
function alert(data) {
return "received input " +data.display;
};
//This function loads the webpage content of the HTML file "Card Request Form" as a sidebar in the main spreadsheet
function showRequestForm() {
var form = HtmlService.createTemplateFromFile("Card Request Form");
var html = form.evaluate();
SpreadsheetApp.getUi().showSidebar(html);
};
//This function allows us to navigate pages that exists in the document
function newPage(page) {
return HtmlService.createHtmlOutputFromFile(page).getContent()
};
I need help understanding how to cpature the input, and pass it back to the GS (I believe it's the same as passing it to the server) in order to run the cardSearch Function with that capturted data.
Here's an example form that I've used to collect receipt information. You can display it as a sidebar, a dialog or run it as a webapp. It has a numerical input, a text input and a textarea. It also allows you to upload a file.
thehtml.hmtl:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function(){
google.script.run
.withSuccessHandler(function(rObj){
$('#dt').val(rObj.date);
})
.initForm();
});
function fileUploadJs(frmData) {
var amt=$('#amt').val();
var vndr=$('#vndr').val();
var img=$('#img').val();
if(!amt){
window.alert('No amount provided');
$('#amt').focus();
return;
}
if(!vndr) {
window.alert('No vendor provided');
$('#vndr').focus();
return;
}
if(!img) {
window.alert('No image chosen');
$('#img').focus();
}
document.getElementById('status').style.display ='inline';
google.script.run
.withSuccessHandler(function(hl){
document.getElementById('status').innerHTML=hl;
})
.uploadTheForm(frmData)
}
console.log('My Code');
</script>
<style>
input,textarea{margin:5px 5px 5px 0;}
</style>
</head>
<body>
<h3 id="main-heading">Receipt Information</h3>
<div id="formDiv">
<form id="myForm">
<br /><input type="date" name="date" id="dt"/>
<br /><input type="number" name="amount" placeholder="Amount" id="amt" />
<br /><input type="text" name="vendor" placeholder="Vendor" id="vndr"/>
<br /><textarea name="notes" cols="40" rows="2" placeholder="NOTES"></textarea>
<br/>Receipt Image
<br /><input type="file" name="receipt" id="img" />
<br /><input type="button" value="Submit" onclick="fileUploadJs(this.parentNode)" />
</form>
</div>
<div id="status" style="display: none">
<!-- div will be filled with innerHTML after form submission. -->
Uploading. Please wait...
</div>
</body>
</html>
Codge.gs:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Receipt Collection')
.addItem('Run as Dialog', 'showAsDialog')
.addItem('Run as Sidebar', 'showAsSidebar')
.addToUi();
var sh=SpreadsheetApp.getActive().getSheetByName("Sheet1");
sh.getRange(sh.getLastRow()+1,1).activate();
}
function uploadTheForm(theForm) {
var rObj={};
rObj['vendor']=theForm.vendor;
rObj['amount']=theForm.amount;
rObj['date']=theForm.date;
rObj['notes']=theForm.notes
var fileBlob=theForm.receipt;
var fldr = DriveApp.getFolderById(receiptImageFolderId);
rObj['file']=fldr.createFile(fileBlob);
rObj['filetype']=fileBlob.getContentType();
Logger.log(JSON.stringify(rObj));
var cObj=formatFileName(rObj);
Logger.log(JSON.stringify(cObj));
var ss=SpreadsheetApp.openById(SSID);
ss.getSheetByName('Sheet1').appendRow([cObj.date,cObj.vendor,cObj.amount,cObj.notes,cObj.file.getUrl()]);
var html=Utilities.formatString('<br />FileName: %s',cObj.file.getName());
return html;
}
function formatFileName(rObj) {
if(rObj) {
Logger.log(JSON.stringify(rObj));
var mA=rObj.date.split('-');
var name=Utilities.formatString('%s_%s_%s.%s',Utilities.formatDate(new Date(mA[0],mA[1]-1,mA[2]),Session.getScriptTimeZone(),"yyyyMMdd"),rObj.vendor,rObj.amount,rObj.filetype.split('/')[1]);
rObj.file.setName(name);
}else{
throw('Invalid or No File in formatFileName() upload.gs');
}
return rObj;
}
function doGet() {
var output=HtmlService.createHtmlOutputFromFile('receipts').setTitle('thehtml');
return output.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL).addMetaTag('viewport', 'width=360, initial-scale=1');
}
function showAsDialog() {
var ui=HtmlService.createHtmlOutputFromFile('thehtml');
SpreadsheetApp.getUi().showModelessDialog(ui, 'Receipts')
}
function showAsSidebar() {
var ui=HtmlService.createHtmlOutputFromFile('thehtml');
SpreadsheetApp.getUi().showSidebar(ui);
}
function initForm() {
var datestring=Utilities.formatDate(new Date(),Session.getScriptTimeZone(), "yyyy-MM-dd")
return {date:datestring};
}
globals.gs:
var receiptImageFolderId='upload file folder id';
var SSID='spreadsheet id';

javascript onchange function could not be called

I'm just little bit confused on my html code.
What I want just, when user click the circle image, it will call load / take picture and then assign the picture to the circle.
In my below code, it's only call the take picture function, the on change function (pictureselected) is not being called.
When it calls directly through "srcimagefile", all function are called correctly.
Please see my below code. Please advise, what did I miss ?
<html>
<head>
</head>
<body>
<form>
<div class="col-md-12 col-xs-12" align="center">
<div class="outter">
<input type="image" id="imagefile" src="http://lorempixel.com/output/people-q-c-100-100-1.jpg" class="image-circle" onclick="takePicture()"/>
<input type="file" id="srcimagefile" onchange="pictureSelected()" />
</div>
</div>
<div class="group">
<input type="text"><span class="highlight"></span><span class="bar"></span>
<label>Username</label>
</div>
<div class="group">
<input type="password"><span class="highlight"></span><span class="bar"></span>
<label>Password</label>
</div>
<button type="button" class="button buttonBlue">Login
<div class="ripples buttonRipples"><span class="ripplesCircle"></span></div>
</button>
</form>
<link href="userlogincss.css" rel="stylesheet" type="text/css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="userloginjs.js"></script>
<script>
function takePicture() {
$("#srcimagefile").click();
}
function pictureSelected() {
fileSelectHandler();
}
// Create variables (in this scope) to hold the Jcrop API and image size
var jcrop_api, boundx, boundy;
function fileSelectHandler() {
// get selected file
var oFile = $('#srcimagefile')[0].files[0];
alert('Hello');
// hide all errors
$('.error').hide();
// check for image type (jpg and png are allowed)
var rFilter = /^(image\/jpeg|image\/png)$/i;
if (! rFilter.test(oFile.type)) {
$('.error').html('Please select a valid image file (jpg and png are allowed)').show();
return;
}
// check for file size
if (oFile.size > 250 * 1024) {
$('.error').html('You have selected too big file, please select a one smaller image file').show();
return;
}
// preview element
var oImage = document.getElementById('imagefile');
var oReader = new FileReader();
oReader.onload = function(e) {
// e.target.result contains the DataURL which we can use as a source of the image
oImage.src = e.target.result;
}
// read selected file as DataURL
oReader.readAsDataURL(oFile);
}
</script>
</body>
<html>
You are trying to call the function which will trigger on Change Event. Change your event to "onclick", then your code will execute as expected.
Check the below code change,
<input type="file" id="srcimagefile" onclick="pictureSelected()"
onclick="pictureSelected()"

HTML onload script triggered too many times?

I created a simple ASP.Net html page. I would like to put a password check, ONLY when the page is initially loaded, I did it with a script and assigned the tag onload to the body. The problem is, that the password check is triggered every time I press a button. Why does this happens? How can I execute that password check ONLY when you open the page?
Thanks in advance.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="FotoDiClasse.aspx.cs" Inherits="FotoDiClasse" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Choose your sweatshirt</title>
<!-- password control -->
<script>
var password;
var pass1 = "1234";
var firstTime = true;
function checkPassword()
{
if (firstTime)
firstTime = false;
password = prompt("Enter password to access the site", '');
if (password != pass1) window.location = "http://www.google.com";
}
</script>
</head>
<body onload="checkPassword()">
<form id="form1" runat="server">
<div>
<asp:Button ID="CreateButton" runat="server" Text="Create" Width="240px" OnClick="CreateButton_Click" />
<asp:Button ID="SendButton" runat="server" Text="Send" Width="240px" OnClick="SendButton_Click" />
</div>
</form>
</body>
</html>
This "first time" flag doesn't work
It is called PostBack. Every time a Button is pressed the Page performs a Form Post (PostBack). That means the page is reloaded.
With the snippet below you can call a JavaScript function only when the page is first loaded.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "runScript", "alert('This is not a PostBack');", true);
}
}
It happens because every time you press a button your page is loaded and onload() method is called and hence every time that method is called.
To overcome this problem you need to set some sort of function that check whether your page is loaded first time or not to do this you can use cookie to store that session.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="FotoDiClasse.aspx.cs" Inherits="FotoDiClasse" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Choose your sweatshirt</title>
<!-- password control -->
<script>
var password;
var pass1 = "1234";
var firstTime = true;
function checkPassword()
{
if (firstTime)
firstTime = false;
password = prompt("Enter password to access the site", '');
if (password != pass1) window.location = "http://www.google.com";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="CreateButton" runat="server" Text="Create" Width="240px" OnClick="CreateButton_Click" />
<asp:Button ID="SendButton" runat="server" Text="Send" Width="240px" OnClick="SendButton_Click" onblur="checkPassword()"/>
</div>
</form>
</body>
</html>

opening code behind for input element?

everytime I try to open code behind for my
<input id="Submit1" type="submit" value="Upload" runat="server">
I get this
<script language="javascript" type="text/javascript">
// <![CDATA[
function Submit1_onclick() {
}
// ]]>
</script>
Can please anyone help me so I can go to code behind after double clicking ?

Google visualization is small inside AJAX Control Toolkit Tab Control

I'm trying to use a google visualisation, the column chart, inside an asp.net AJAX Toolkit Tab Control, but I'm having small (literally) problems.
If I add the visualisation to the tab that's displayed by default when the page loads, the bar chart displays correctly, however, if I add the same control to another tab and reload the page, when I click on the other tab, the control is displayed, but its tiny and unusable.
Here's some code for a test.aspx page that illustrates the problem:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="TestProject._Default" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', { packages: ['columnchart'] });
</script>
<script type="text/javascript">
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Name');
data.addColumn('number', 'Height');
data.addRows(3);
data.setCell(0, 0, 'Tong Ning mu');
data.setCell(1, 0, 'Huang Ang fa');
data.setCell(2, 0, 'Teng nu');
data.setCell(0, 1, 174);
data.setCell(1, 1, 523);
data.setCell(2, 1, 86);
// Create and draw the visualizations.
new google.visualization.ColumnChart(document.getElementById('visualization1')).
draw(data, null);
new google.visualization.ColumnChart(document.getElementById('visualization2')).
draw(data, null);
}
google.setOnLoadCallback(drawVisualization);
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<cc1:TabContainer ID="TabContainer1" runat="server">
<cc1:TabPanel runat="server" HeaderText="TabPanel1" ID="TabPanel1">
<ContentTemplate>
<div id="visualization1" style="width: 300px; height: 300px;">
</div>
</ContentTemplate>
</cc1:TabPanel>
<cc1:TabPanel runat="server" HeaderText="TabPanel1" ID="TabPanel2">
<ContentTemplate>
<div id="visualization2" style="width: 300px; height: 300px;">
</div>
</ContentTemplate>
</cc1:TabPanel>
</cc1:TabContainer>
</div>
</form>
</body>
</html>
Ok, I didn't get a single response to this post so here is how I worked around the problem, hope it helps someone.
I never actually got the the root of this problem but I found that if I delayed the loading of the Visualisations till the tab that contains it is clicked then the problem goes away.
In the TabControl I call a JavaScript function to load the tabs visualisation when clicked:
<cc1:TabContainer ID="TabContainer1" runat="server" OnClientActiveTabChanged="tabChanged">
<cc1:TabPanel runat="server" HeaderText="TabPanel1" ID="TabPanel1">
<ContentTemplate>
<div id="visualization1" style="width: 300px; height: 300px;"></div>
</ContentTemplate>
</cc1:TabPanel>
<cc1:TabPanel runat="server" HeaderText="TabPanel1" ID="TabPanel2">
<ContentTemplate>
<div id="visualization2" style="width: 300px; height: 300px;"></div>
</ContentTemplate>
</cc1:TabPanel>
</cc1:TabContainer>
The JavaScript function
function tabChanged(sender, args) {
var ActiveTab = sender.get_activeTabIndex();
if (sender.get_activeTabIndex() == 0) {
if (tab0Loaded != true) {
//load the visualisation
new google.visualization.ColumnChart(document.getElementById('visualization2')).draw(data, null);
tab0Loaded = true
}
}
if (sender.get_activeTabIndex() == 1) {
if (tab1Loaded != true) {
//load the visualisation
new google.visualization.ColumnChart(document.getElementById('visualization2')).draw(data, null);
tab1Loaded = true
}
}
}
During postback the active tab could change, to cope with this I have a JavaScript function that executes when the page loads, if the current active tab is one containing a visualisation then I load it.