fine-uploader resubmit parameters but not file - callback

I'm using fine-uploader to take multiple (large) files and pass the filename along with an additional user-input parameter. I do that by creating a text input box (called 'allele_freq') next to each file and I pass the filename and the allele_freq parameter to my cgi script.
What happens next (or what will happen next) is that I analyse the data in the file, using the allele_freq parameter and then some images are returned to the page for the user to look at.
If the user wants to re-analyse the data with a new allele_freq, all I want to do is to pass the filename along with the new allele_freq, i.e. I don't want to have to upload the file again.
I've pasted my working code below (it uploads multiple files along with user input for each file) and then the code that I can't get to work (it produces a 'resubmit' button, but doesn't appear to do anything), along with some comments/musings within the code.
Any information on how I would do this will be gratefully received. I'm very new to both fine-uploader and Javascript (as you can probably tell), so please feel free to criticise (constructively of course!) any of my code.
Many thanks,
Graham
<link href="fineuploader/fineuploader-3.6.4.css" rel="stylesheet">
<script src="fineuploader/jquery-2.0.1.js"></script>
<script src="fineuploader/jquery.fineuploader-3.6.4.js"></script>
<div id="multiFineUploader"></div>
<div id="triggeredUpload" class="btn btn-primary" style="margin-top: 10px;">
<i class="icon-upload icon-white"></i> Upload now
</div>
<script>
$('#multiFineUploader').fineUploader({
request: {
endpoint: 'src/lib/upload.cgi'
},
autoUpload: false,
text: {
uploadButton: '<i class="icon-plus icon-white"></i> Select Files'
}
})
.on('submitted', function(event, id, name) {
var fileItemContainer = $(this).fineUploader('getItemByFileId', id);
$(fileItemContainer)
.append('<input type="text" name="allele_freq">');
})
.on('upload', function(event, id, name) {
var fileItemContainer = $(this).fineUploader('getItemByFileId', id),
enteredAlleleFreq = $(fileItemContainer).find('INPUT[name="allele_freq"]').val();
$(this).fineUploader('setParams', {allele_freq: enteredAlleleFreq}, id);
});
$('#triggeredUpload').click(function() {
$('#multiFineUploader').fineUploader('uploadStoredFiles');
});
</script>
above code works fine
code below doesn't
<div id="resubmitFreqs"></div>
<div id="retry" class="btn btn-success" style="margin-top: 10px;">
<i class="icon-upload icon-white"></i> Resubmit
</div>
<script>
$('#resubmitFreqs').fineUploader({
request: {
//use a different script as shouldn't need to handle all the upload stuff
endpoint: 'src/lib/resubmit.cgi'
}
)}
//get the information from the allele_freq box. Should it still be in scope?? If not, how do I get at it?
.on('upload', function(event, id, name) {
var fileItemContainer = $(this).fineUploader('getItemByFileId', id),
enteredAlleleFreq = $(fileItemContainer).find('INPUT[name="allele_freq"]').val();
$(this).fineUploader('setParams', {allele_freq: enteredAlleleFreq}, id);
});
$('#retry').click(function() {
//I presumably don't want to use 'uploadStoredFiles', but I'm not sure how to post my new parameters into the resubmit.cgi server-side script
$('#resubmitFreqs').fineUploader('uploadStoredFiles');
});
</script>

It seems like you are trying to bend Fine Uploader into something that it is not. Fine Uploader should probably not be involved with this step of your process, as its job is to upload files to your server. It is not meant to be an all-in-one web application. If you want to send additional data to your server at some point in time after the file has been sent, simply send a POST request with that data via XHR.

Related

Google Apps Script HTMLService display confirmation page after form submit

I created a web app form using Google Apps Script and the HTMLService.
It is a one-page form with a submit button at the bottom.
When submitted, the form validates whether the data input into the form is valid, and if valid, it logs the form data to a spreadsheet.
That all works so far.
I now need the user to be sent to a confirmation page, and the confirmation page needs to be able to have parameters passed to it (to display certain information on the confirmation page).
main.gs:
function doGet(e) {
var template = HtmlService.createTemplateFromFile('form');
return template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function processFormSubmission(formData) {
Logger.log('starting processPoRequest');
Logger.log('po: ' + JSON.stringify(formData, null, 2));
// code for appending data to sheet here
}
form.html:
<!DOCTYPE html>
<form id="form1" name="form1">
<label for="info" id="info_label">Info</label>
<input id="info" name="info" type="text">
<input class="btn" id="button" onclick="onClickFunctions(document.getElementById('form1'))" type="submit" value="Submit">
</form>
<script>
function onClickFunctions(formData) {
console.log('starting onClickFunctions');
var allDataValid = validateForm(formData);
if (allDataValid === true) {
google.script.run.withSuccessHandler().processFormSubmission(formData);
}
}
function validateForm(form) {
console.log('starting validateForm');
var errors = 0;
var element = document.getElementById('info');
if (!form.info) { element.classList.add("validation_error"); errors++; if (errors === 1) element.focus(); }
else element.classList.remove("validation_error");
if (errors > 0) return false;
else return true;
}
</script>
confirmation.html:
<!DOCTYPE html>
<?!= confirmationMessage ?>
I don't know what to put in .withSuccessHandler() to make it so that the user is brought to the confirmation page.
I've Googled this extensively and found these results on Stack Overflow, and each one suggests a different solution, but none of them actually include complete working code for a solution:
Possible solutions using doPost:
Send form by email and track responses in spreadsheet
HtmlService doPost With Google Docs Form
HtmlService doPost
I messed around with doPost but I couldn't figure out how to get it to be invoked, and I couldn't find any official documentation in the HTMLService docs.
Possible solution using the link to the web app in an a href:
href in HtmlService
If my button was a link that looked like a button, I'm not sure how I would execute the form validation function when the link is clicked.
I have done this two different ways.
had a hidden statement that gets shown, and the form gets hidden.
or
use .withSuccessHandler(google.script.host.close()), but have the processFormSubmission function open a new dialogue.

Cancel a file upload in ng-file-upload

I have ng-file-upload with form submit running. I would like to add a button to cancel the upload after the user selects a file.
I have tried:
<button class= "btn btn-warning btn-cancel" ng-disabled="!myForm.$valid"
ng-click="cancelPic(picFile)">Cancel</button>
and in the controller:
$scope.cancelPic = function() {
myForm.reset();
file: '';
}
The form does seem to reset as I get a "please select a file" message but the image remains - in the dev tools Elements:
<img ng-show="myForm.file.$valid" ngf-src="!picFile.$error && picFile" class="thumb" src="blob:http%3A//localhost%3A3000/85f1b27c-a92e-447d-b760-8cfe17bbd6b7" style="">
Obviously I'm barking up the wrong tree here. Can anyone help?
Ok I found what I sought at:
https://github.com/danialfarid/ng-file-upload/issues/12
The code that works is:
$scope.cancelPic = function(file) {
myForm.reset();
$scope.picFile = undefined;
}
Now I need to apply this to individual images so a user can choose which to cancel and not reset the whole form. That's for another day.

DOM elements not accessible after onsen pageinit in ons.ready

I am using the Onsen framework with jQuery and jQuery mobile, it appears that there is no way to catch the event that fires once the new page is loaded.
My current code, which executes in the index.html file (the master page)
<script src="scripts/jQuery.js"></script>
<script src="scripts/jquery.mobile.custom.min.js"></script>
<script src="scripts/app.js"></script>
<script>
ons.bootstrap();
ons.ready(function() {
$(document.body).on('pageinit', '#recentPage', function() {
initRecentPage();
});
});
in app.js is the following code
function initRecentPage() {
$("#yourReports").on("tap", ".showReport", recentShowReport);
var content = document.getElementById("yourReports");
ons.compile(content);
}
and the HTML:
<ons-page id="recentPage">
<ons-toolbar id="myToolbar">
<div id="toolBarTitle" class="center">Recent Checks</div>
<div class="right">
<ons-toolbar-button ng-click="mySlidingMenu.toggleMenu()">
<ons-icon icon="bars"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
<ons-scroller>
<h3 class="headingTitle"> Checks</h3>
<div id="Free" class="tabArea">
<ons-list id="yourReports">
</ons-list>
<ons-button id="clearFreeRecentButton">
<span id="clearRecentText" class="bold">Clear Recent Checks</span>
</ons-button>
</div>
</ons-scroller>
</ons-page>
in this instance the variable 'content' is always null. I've debuged significantly, and the element I am trying to get is not present when this event fires. It is loaded later.
So, the question is, how do I ensure that all of the content is present before using a selector. It feels like this is an onsen specific issue.
In the end I could only find one reliable way of making this work.
Essentially I had to wait, using setTimeout 300 milliseconds for the DOM elements to be ready. It feels like a hack, but honestly there is no other reliable way of making this behave. The app is in the app store and works well, so even though it seems like a hack, it works:
$(document).on('pageinit', '#homePage', function() {
initHomePage();
});
function initHomePage() {
setTimeout(function() {
setUpHomePage();
}, 300);
}
Move your $(document.body).on('pageinit', '#recentPage', function() { outside of ons.ready block.
JS
ons.bootstrap();
ons.ready(function() {
console.log("ready");
});
$(document.body).on('pageinit', '#recentPage', function() {
initRecentPage();
});
function initRecentPage() {
//$("#yourReports").on("tap", ".showReport", recentShowReport);
var content = document.getElementById("yourReports");
alert(content)
ons.compile(content);
}
I commented out a line because I do not have access to that "recentShowReport"
You can see how it works here: 'http://codepen.io/vnguyen972/pen/xCqDe'
The alert will show that 'content' is not NULL.
Hope this helps.

Uploading file using Google Apps Script using HtmlService

How can I upload files to google drive?
I want to create a web app using google app script - htmlservice.
I don't know how to point form in html to existing google app script.
I am having hard time to find a right example in google documentation.
I found hundreds of examples using UI but according to https://developers.google.com/apps-script/sunset it will be deprecated soon.
Thank you in advance!
Janusz
<html>
<body>
<form>
<input type="file"/>
<input type="button">
</form>
</body>
</html>
Script
function doGet() {
return HtmlService.createHtmlOutputFromFile('myPage');
}
function fileUploadTest()
{
var fileBlob = e.parameter.upload;
var adoc = DocsList.createFile(fileBlob);
return adoc.getUrl();
}
Have the button run the server side function using google.script.run, passing in the entire form as the only parameter. (Inside the button's onClick, 'this' is the button, so 'this.parentNode' is the form.) Make sure to give the file input a name.
<html>
<body>
<form>
<input type="file" name="theFile">
<input type="hidden" name="anExample">
<input type="button" onclick="google.script.run.serverFunc(this.parentNode)">
</form>
</body>
</html>
On the server, have your form handling function take one parameter - the form itself. The HTML form from the client code will be transformed into an equivalent JavaScript object where all named fields are string properties, except for files which will be blobs.
function doGet() {
return HtmlService.createHtmlOutputFromFile('myPage');
}
function serverFunc(theForm) {
var anExampleText = theForm.anExample; // This is a string
var fileBlob = theForm.theFile; // This is a Blob.
var adoc = DocsList.createFile(fileBlob);
return adoc.getUrl();
}
If you actually want to use that URL you are generating and returning, be sure to add a success handler to the google.script call. You can modify it like this:
// Defined somewhere before the form
function handler(url) {
// Do something with the url.
}
<input type="button" onclick=
"google.script.run.withSuccessHandler(handler).serverFunc(this.parentNode)">
try: return HtmlService.createTemplateFromFile('myPage').evaluate();
More: html service reference
I found an answer for my question.
Submit a Form using Google App Script's HtmlService
The code in the Google App Script link below is:
function doGet(e) {
var template = HtmlService.createTemplateFromFile('Form.html');
template.action = ScriptApp.getService().getUrl();
return template.evaluate();
}
function doPost(e) {
var template = HtmlService.createTemplateFromFile('Thanks.html');
template.name = e.parameter.name;
template.comment = e.parameter.comment;
template.screenshot = e.parameter.screenshot;
return template.evaluate();
}
https://script.google.com/d/1i65oG_ymE1lreHtB6WBGaPHi3oLD_-wPd5Ter1nsN7maFAWgUA9DbE4C/edit
Thanks!

How to get clicked elelment in <fb:visible-to-connection>-context?

It seems FB have removed the possibility to get the the clicked element (i.e. this) in the context of <fb:visible-to-connection>.
I.e:
<a onclick="doSomething(this);">test</a>
<script>
function doSomething(this) {
console.log(this);
}
<script>
Will give the following in Firebug:
Object { PRIV_obj=a, appendChild=function(), insertBefore=function(), more...}
Whereas
<fb:visible-to-connection>
<a onclick="doSomething(this);">test</a>
<fb:else>
</fb:else>
<a onclick="doSomething(this);">test</a>
</fb:visible-to-connection>
<script type="text/javascript">
function doSomething(element) {
console.log(element);
}
</script>
Will give:
null
Is this a temporary bug in FBJS or due to some new feature?
How do I get hold of "this" in the second example?
This was changed for security reasons, you can't access HTML elements inside FMBL elements any more - the initial bug report (which was closed as a 'by design') was about using getElementById but I believe this is the same cause