How to Stop Double Clicking/Double Posting of form? - google-apps-script

Using UiApp to collect data from a form, but I have users double clicking the submit button. This runs doPost twice. Granted, they have to click mighty fast to get it to actually post twice, but it happens.
My questions is: has anyone had experience in disabling the submit button, say with an onMouseUp? Is there a better way to do this? I've been told to be wary of adding multiple onClick handlers to buttons, as it can be unstable. Any stable solutions to this?
I have to use a submit button as there is a file upload in the form.

I've faced this problem and ever since Google introduced ClientHandlers, there is a way out.
Just add a client handler to your submit button disabling it (and remember to enable it when you are done with the server handler function or doPost)
var plswait = app.createClientHandler().forEventSource().setEnabled(false).setText('Please wait...');
var btnSubmit = app.createSubmit().addMouseDownHandler(plswait);
is my favourite.

The first answer didn't work for me because the MouseDown handler didn't let the ServerHandler run. But it gave me the right direction. I just added the Client handler to disable the button before I added the Server Handler...and that seemed to work to prevent the double click. Like this:
var submitButton = myapp.createButton("Submit");
var myServerHandler = myapp.createServerClickHandler("myServerHandler");
var pleaseWait = myapp.createClientHandler().forEventSource().setEnabled(false).setText('submitting...');
submitButton.addClickHandler(pleaseWait);
submitButton.addClickHandler(myServerHandler);

I had the same problem, but to work around it I created a second "false" button that becomes visible when the submit button is clicked, at the same time the "real" submit button visibility is set to false. Here's the basic code:
var button = app.createSubmitButton('Submit').setId("button")
.setEnabled(false)
var falseButton = app.createButton('Submit').setId("falseButton")
.setEnabled(false)
.setVisible(false);
var handler = app.createClientHandler()
.forTargets(button).setVisible(false)
.forTargets(falseButton).setVisible(true);
button.addClickHandler(handler);
panel.add(app.createHorizontalPanel().add(button).add(falseButton);

Related

submit form from file input box after selecting image

I am attempting to trigger a form submit from an input [type=file] dialog box window. I'm trying to streamline the process of selecting an image and then having to click another button to submit the form to the database.
I have updated the question to include screenshots and code below to hopefully make the issue I'm having more clear.
Note:
It was asked why I don't add an id to the input button, but I can't, as the file input is invoked from the function, and as it's a windows process, I have no ability to add/change it.
Here's some code / pics to better illustrate the issue.
1 - The user clicks the change pic button to update their profile image. This button runs a shortcode [upload-user-profile-avatar].
2 - The shortcode triggers the standard input file open box window.
3 - After the user either double clicks a file, or single clicks a file and presses the open button, the form for the user profile avatar plugin is automatically submitted.
Attempts:
I originally started out using jQuery to attempt to attach to the form and submit it on click,
jQuery('input[type=file]').change(function(){
nameOfForm.submit();
});
However I read in a SO post that someone else was attempting something similar, and jQuery wouldn't submit the form, so they had to switch to javascript, which I did (since jQuery wasn't submitting the form)...and I came up with this for testing purposes.
var form = document.getElementsByClassName("update-user-profile-avatar");
var inputs = document.getElementsByTagName('input');
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].type.toLowerCase() == 'file') {
console.log(inputs[i].value);
form.submit();
}
}
So this was helpful in so much that I could see that the open dialog window is grabbing the correct filename, but still, the form isn't getting submitted and I'm getting a form.submit() is not a function error in the console.
So then I read that html form submissions can have a lot of weirdness about them, so try something along these lines.
jQuery('input[type=file]').change(function(){
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].type.toLowerCase() == 'file') {
console.log(inputs[i].value);
HTMLFormElement.prototype.submit.call(form);
}
}
});
which produced this error:
'submit' called on an object that does not implement interface HTMLFormElement.
So I think I'm spinning my wheels here. I sense this is doable, I'm just not using the right method to do it.
I think you're looking for the change event:
Demo
$('input[type=file]').change(function(){
$('form').submit()
})
Unfortunately for security purposes the browser isn't going to let you access the open window. However with the .change() method, it will trigger whatever function you'd like once the value of the input has changed. Whether they double click a file to select it, or click the file and "open" button.

How can I disable a button when I press another button

I am a beginner in app scripting and I have a question.
How can I disable a button when I press another button.
I tried many different ways, but I can't get it to work.
Can you help me?
My code is large. Should I paste it here?
in UiApp you can use clientHandler to do that very easily...
example code goes like this :
function doGet() {
var app = UiApp.createApplication();
var btn1 = app.createButton('button1');
var btn2 = app.createButton('button2');
var clientHandler = app.createClientHandler().forTargets(btn1).setEnabled(false);
btn2.addClickHandler(clientHandler);
return app.add(btn1).add(btn2);
}
Note : the comments above are right... your question was indeed too vague.
Yes, you will need to post some relevant code before anyone will be able to help you.
Broadly speaking, a good logical approach to achieving what you want to do, is to use the event that occurs, or state that is invoked by clicking the first button, to run script that will disable your second button.
This can be done many different ways. Client Side, Server Side.. it all really depends on context as to which is right for your situation.

FormPanel submit with ServerHandler validation

I want to tie a ServerHandler to a submit button so I can do validation of my form prior to submission. If the validation succeeds, then the POST of the form will be carried out. If the validation fails (due to an incomplete or incorrect field), then the POST will be stopped, and the ServerHandler can indicate the incorrect fields. The kind of thing you do in Javascript with event.preventDefault(), or returning false in the button handler for a submit.
var app = UIApp.getActiveApplication();
var form = app.createFormPanel();
var panel = app.createVerticalPanel();
// Add form elements to panel such as textboxes, radio buttons, list boxes etc.
...
...
var button = app.createSubmitButton("submit");
button.addClickHandler(app.createServerHandler("validate").addCallbackElement(panel));
panel.add(button);
form.add(panel);
app.add(form);
function validate(e) {
// Do the validation of the form
// QUESTION - How do we then disable or allow the POST?
}
So the kludge I'm currently doing is to have a validate button (normal button), which gets changed to a 'submit' button if the form validation done in the serverhandler is good. The user then has to click the button again to submit the form. I have to lock all the elements to prevent them changing any fields once the validation is good. There has to be a better way more akin to the Javascript route mentioned above, and referenced here: event.preventDefault() vs. return false
For reference, if you tie the validation ServerHandler to a submit button, it will always do a POST.

GAS: GUI Builder, File Upload, Submit Button

I already read some answers to this question on stackoverflow but I was not able to get my case working.
I have the components in GUI Builder and the code runs to function respondToSubmit after pressing Submit button, but the fileName is undefined. fileName is the content of Name in Input Fields in component File Upload. Any Ideas what is wrong?
function respondToSubmit(e) {
var app = UiApp.getActiveApplication();
var fileBlob = e.parameter.fileName;
throw(fileBlob); // fileBlob = undefined!!!
return app;
}
RECENT CODE:
function doPost(e) {
throw("doPost"); // never thrown so code does not run here!
var app = UiApp.getActiveApplication();
var fileBlob = e.parameter.FileUpload1;
return app;
}
I think you have to have your labels, text boxes, and submit buttons all in a Flow Panel, which then has to be enveloped by a Form Panel. I had this exact same problem, even the 'Unexpected Error'. I solved it by putting all of those elements into a Flow Panel.
There are two types of buttons - one is the regular button and the other is a Submit button (which can be placed only on a form panel)
Make sure you are using the Submit button and not a regular button
When you use a Submit button, there is no need to provide a handler function. Submit buttons, by default get handled by a special function called doPost(e). So, write a doPost function and you will be able to filename parameter.
The FileUpload widget documentation has a nice example of how this is done.

Google App Script WebApp, Manipulating UI

Hi and Good day to all,
Google App Script can be used in so many ways. I know cause I have tried some of them but Iam not an expert so, the situation is.
I have created an Spreadsheet
create a form using the new UI Building that comes with the script editor.
named:gtest01
UI compose of:
label, id=label_caption
button 1, id=button_hide, event-onmouseclick=hide_label
button 2, id=button_show, event-onmouseclick=show_label
button 3, id=button_message, event-onmouseclick=message_me
now, the code is:
/* This is so when I want to just deploy it as a [webapp] using the
script editor -> Publish Deploy as Web App
*/
function doGet(e) {
var app = UiApp.createApplication().setTitle("Sheet Application");
app.add(app.loadComponent("gtest01"));
Logger.log("Application UI Loaded");
return app;
}
function message_me(e) {
Browser.msgBox("my message");
}
function hide_label(e) {
var app = UiApp.getActiveApplication();
label =app.getElementById("label_caption");
label.setVisible(false);
}
function show_label(e) {
var app = UiApp.getActiveApplication();
label =app.getElementById("label_caption");
label.setVisible(true);
}
// this code is for when the spreadsheet is shared so they can access the form
function showform_() {
var app = UiApp.createApplication();
app.add(app.loadComponent("gtest01"));
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Show Form", functionName: "showform_"});
ss.addMenu("e-Test", menuEntries);
}
First scenario is that when spreadsheet is shared
when menu is clicked the form will load - thats good
when show and hide button nothing happens - why and how can i fixed
this?
when message button is click - message will show but the form will
close, how can I display a message without closing the form?
Second scenario is that when publish as Webapp.
When Developer Link is Access the UI is always updated - ok
When URL Link is Access the UI is always updated its like it is
cache, how can I fixed this?
on dev link: when show and hide button nothing happens - why and how
can i fixed this?
on dev link: when message button is click - will generate an error,
how can I display an alert message on WebApp
Please help I have search and tried the sample codes and answer in the forum am missing something.
Thanks
Nick Ace
First scenario
when show and hide button nothing happens - why and how can i fixed this?
In your functions, use return app at the end. Unless you return the app object, the UI doesn't get updated.
how can I display a message without closing the form? - Try
SpreadsheetApp.getActiveSpreadsheet().toast()
2nd scenario
When URL Link is Access the UI is always updated its like it is cache, how can I fixed this? - Save your most recent code as a version
on dev link: when show and hide button nothing happens - Again return app will take care of this
on dev link: when message button is click... - Browser.msgBox is not supported in a web app.
When Using UI it is generally a good idea to make everything happen inside this Ui, so try to avoid showing messages with Toast( as they are not supported in web apps anyway).
Since you are using the GUI it should be quite easy to use a label with your message that is initially invisible and to make it visible in an handler routine.
Note that this kind of handler can be a client handler as well unless you need to do something else from this action.
As for the other points of you question, our (very fast) friend Srik has already answered thoroughly ;-)