cancel button cannot be clicked after file select (form submission) - javascript

I have a very simple html page which has a file upload button as well as a modal popup to show loading status and a cancel button. My problem is that the cancel button seems to be blocked while it's processing the file (making it useless). How can I have a button which will cancel the form submission.
HTML:
<body>
<div id="myModal" class="modal">
<div class="modal-content">
<p>Processing File.</p>
<div class="loader-inner pacman"><div></div><div></div><div></div><div></div><div></div></div>
<div id="progressbar" ></div>
<input type = "button" name="cancel" value = "cancel" onclick = "cancelRead()" />
</div>
</div>
<div>
<input type="file" id="logSelector" name="log" title="Select a log file" onchange="logSelected();"/>
JS:
function cancelRead() {
console.log("cancelRead"); //never see this message even though the button is clicked
fileReader.abort();
operationAborted = true;
document.execCommand('Stop');
}
The logSelected() method is quite lengthy and I omitted it from the above code mostly to eliminate clutter. That method uses FileReader to read the selected file than create a table from the data. However I do signal to this method to stop via the operationAborted variable. however like i said in the comments, this method is never called by clicking my button. The cancel button doesnt even animate like it was clicked.
The promise api was mentioned below, here is my attempt at it. Although it works it did not fix the issue of the cancel button not clickable due to the main/only thread being used.
var promise = $.Deferred(function (dfd) {
FILE_READER.onload = function (event) {
var contents = event.target.result;
dfd.resolve(contents);
};
FILE_READER.readAsText(file);
}).promise();
$.when(promise).then(function (contents) {
processFile(contents.split('\n'));
});

And it's almost sure that it will never work, due to how event loop works in javascript browsers.

This could be because the file reader is using up all of the thread leaving to time to process the function to be called - you see, JavaScript only has one thread & thus can only handle one thing at a time, & this one thing is the file reader!
edit
However you could use a promise (as explained here) to run the file reader asynchronously & cancel the promise.I don;t have much experience with using promises so I can't give much advice, but it is worth a look.

You page remain blocked until this thead (uploading the file) its done. Since its a blocking function, your user won't be able to do anything until this task end.
Your alternative is to use non-block io

Related

How can I get elements inner text after dom is being refreshed after the submit button?

I'm working on automating a task (filling a form and submitting data then getting the result message where the data is being read from a txt file line by line).
While running my JS code via the console, everything works fine until before the clicking on submit button. after the click on the submit button, I can see the HTML is being reloaded with new data and the URL is changed from www.example.com to www.example.com/requests/12345 and then the next step after the click is not respected.
I thought may be because I was using:
document.getElementByID("btn-submit").click();
and changed it to
$("#btn-submit").click().trigger('change');
But still same issue.
I tried to use sleep functions and setTimeout to wait for the new HTML to load but this didn't help at all :(
The task is simple steps until button click all works perfect, I'm stuck only at after the submit button as I want to get the results that shows on the page after clicking the submit button.
Any ideas please what is being done wrong from my side?
The Elements I'm trying to get are in a div that is empty before the submit button is being clicked like this
<div id="message-bar">
</div>
After the submit button is clicked it is filled like the below (also the URL is changed to something link www.example.com/requests/12345 - of course the result elements won't show if the button is not clicked:
<div id="message-bar">
<div id="alert-success" class="alert alert-success">
<button type="button" class="close" data-dismiss="alert">×</button>
<div class="text alert-text">Request approved!</div>
<ul id="bullet-items"><li>Thank you</li></ul>
</div>
</div>
I tried to check if the element is not empty, then get the elements innerText, but seems like my code is being removed when the page URL changes after the submit button:
if (document.getElementById("message-bar").innerText != "") {
// do something
}
Thank you so much
Try
$("#btn-submit").click(function(event){
event.preventDefault();
})
Or without jQuery
var btn = document.getElementById('btn-submit');
btn.addEventListener('click',function(event){
event.preventDefault();
})
Try using the .preventDefault() event
https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault).
From what I understand you need the content not after the click, but after what the click is triggering. Here’s the same Q, answered. Basically you wait for the mods to happen then “read” the element content.
to fix my issue, I thought of using window.open("URL") by creating a variable for it and then using it to process my the whole automation process on the new window and I was able to get all the result message from the new window
var newWindow = window.open("the URL");
newWindow.$('input[id="input"]').val("1234").trigger('change');
etc...

Multiple forms with one button for 2 different functions [duplicate]

I have HTML two forms, one that submits data upon entry to a database using PHP, the other directs the user to a paypal payment page, my problem is that the user would have to submit both forms which of course I do not want them to have to do. Is there anyway to use one submit button for two forms?
(Javascript is welcome)
You should be able to do this with JavaScript:
<input type="button" value="Click Me!" onclick="submitForms()" />
If your forms have IDs:
submitForms = function(){
document.getElementById("form1").submit();
document.getElementById("form2").submit();
}
If your forms don't have IDs but have names:
submitForms = function(){
document.forms["form1"].submit();
document.forms["form2"].submit();
}
A form submission causes the page to navigate away to the action of the form. So, you cannot submit both forms in the traditional way. If you try to do so with JavaScript by calling form.submit() on each form in succession, each request will be aborted except for the last submission. So, you need to submit the first form asynchronously via JavaScript:
var f = document.forms.updateDB;
var postData = [];
for (var i = 0; i < f.elements.length; i++) {
postData.push(f.elements[i].name + "=" + f.elements[i].value);
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "mypage.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(postData.join("&"));
document.forms.payPal.submit();
You can submit the first form using AJAX, otherwise the submission of one will prevent the other from being submitted.
In Chrome and IE9 (and I'm guessing all other browsers too) only the latter will generate a socket connect, the first one will be discarded. (The browser detects this as both requests are sent within one JavaScript "timeslice" in your code above, and discards all but the last request.)
If you instead have some event callback do the second submission (but before the reply is received), the socket of the first request will be cancelled. This is definitely nothing to recommend as the server in that case may well have handled your first request, but you will never know for sure.
I recommend you use/generate a single request which you can transact server-side.
The currently chosen best answer is too fuzzy to be reliable.
This feels to me like a fairly safe way to do it:
(Javascript: using jQuery to write it simpler)
$('#form1').submit(doubleSubmit);
function doubleSubmit(e1) {
e1.preventDefault();
e1.stopPropagation();
var post_form1 = $.post($(this).action, $(this).serialize());
post_form1.done(function(result) {
// would be nice to show some feedback about the first result here
$('#form2').submit();
});
};
Post the first form without changing page, wait for the process to complete. Then post the second form.
The second post will change the page, but you might want to have some similar code also for the second form, getting a second deferred object (post_form2?).
I didn't test the code, though.
If you have a regular submit button, you could add an onclick event to it that does the follow:
document.getElementById('otherForm').submit();
if you want to submit two forms with one button you need to do this:
1- use setTimeout()
2- allow show pop up
<script>
function myFunction() {
setTimeout(function(){ document.getElementById("form1").submit();}, 3000);
setTimeout(function(){ document.getElementById("form2").submit();}, 6000);
}
</script>
<form target="_blank" id="form1">
<input type="text">
<input type="submit">
</form>
<form target="_blank" id="form2">
<input type="text">
<input type="submit">
</form>
javascript doesn't submit two forms at the same time. we submit two forms with one button not at the same time but after secounds.
edit: when we use this code, browser doesn't allow pop up.
if you use this code for your software like me just set browser for show pop up but if you use it in designing site, browser is a barrier and code doesn't run.

$(element).click() not triggering even inside $(function() {})

I have an input element (Dropzone) that's hidden, and is written in the original html's body (was not appended).
<div style="display: none;">
<form action="/uploadProfile" method="post" class="dropzone" id="uploadProfileDropzone"></form>
</div>
Now inside my .js script, I'm trying:
$(function() {
$('#uploadProfileDropzone').click()
})
And nothing happens. However, if I'm calling $('#uploadProfileDropzone').click() inside Chrome's console, it works.
What could possibly be the problem?
EDIT:
Problem might be that I'm trying to call the function before my Dropzone has initialized. Is there a way to know when this happens?
However, even when trying:
$(function() {
setTimeout(function() {
$('#uploadProfileDropzone').click()
}, 5000)
})
Which is a lot after the page fully loads, still nothing happens
SOLUTION:
It turns out that some (or even most of the) browsers block such activity. It's pretty obvious why, looking back at it now. My intention was to navigate to a page that once ready, opens a file dialog for a profile upload action. It seems logically correct to block such action from a user experience point of view, as it can lead to spam and undesired activity from websites. I solved it by displaying a simple popup box on load, that forces the user to press a button, that in turn calls $('#uploadProfileDropzone').click() and it worked.
You possibly have two options:
1) Programatically create your dropzone
Dropzone.autoDiscover = false;
let csvDropzone = new Dropzone("#uploadProfileDropzone", {
paramName: "file",
init: function() {
$('#uploadProfileDropzone').click();
}
});
<div style="display: none;">
<form action="/uploadProfile" method="post" class="dropzone" id="uploadProfileDropzone">
</form>
</div>
2) You can try using init configuration method directly without initialising the dropzone in your JS code:
// Taken from the dropzone config page
Dropzone.options.uploadProfileDropzone = {
init: function() {
$('#uploadProfileDropzone').click();
}
};
It turns out that some (or even most of the) browsers block such activity. It's pretty obvious why, looking back at it now. My intention was to navigate to a page that once ready, opens a file dialog for a profile upload action. It seems logically correct to block such action from a user experience point of view, as it can lead to spam and undesired activity from websites. I solved it by displaying a simple popup box on load, that forces the user to press a button, that in turn calls $('#uploadProfileDropzone').click() and it worked.
you should use document ready event (code works once elements are initialized)
$(document).ready(function(){
$('#uploadProfileDropzone').click(function(){
// Do something here
});
});
OR
$('#uploadProfileDropzone').on('click',function(){ write your code here });

Switch from iframe "AJAX" to proper AJAX

This is legacy code.
I'm working on a project where we're using iframes to simulate AJAX.
Basically, we're using the target attribute to submit the <form> in an iframe, resulting in the request not opening a new tab. Also, we echo a <script></script> in the response from the PHP, and the result is executed since it populates the iframe.
Here's an example of such <form> :
<form id="form_to_submit" method="POST" action="ajax/createUser" target="iframe_name">
<input type="text" name="input_to_send">
<button type="button" onclick="$('#form_to_submit').submit()">Submit With Onclick!</button>
</form>
Nowadays, not only this looks evil, but it has one (perhaps others) huge pitfall. If one request is made through this process, and the client goes somewhere, and then goes back in his browser history, it'll send the request again.
To fix this last problem, there are many solutions. I think the one I prefer the most is to use real AJAX instead of iframes. Now, in theory, I could change every single form in the source code to make it use AJAX, but I know I won't have 1 straight week of work just for this purpose.
I'm looking for a "quick" way to intercept these requests before they're sent to the iframe, and send them with AJAX instead.
So far, I tried to target <form> tags which have a target="iframe_name" and listen to the submit event to then send the request again with a same method/URL/data.
$('form[target=iframe_name]').on('submit', function (event) {
event.preventDefault(event);
var url = $(this).attr('action'),
datas = $(this).serialize();
$.post(url, datas).done(function (response) {
eval($(response).text());
});
});
But that only works if they're submitted through a real click on a submit button. I'd say 95% of these cases are submitted through onclick tags which will .submit() the forms, and in these cases, the submit event won't trigger it appears.
I'm stuck, any idea ?
Note : I'm tagging jquery only to let you know it's available to be used, even though the question is still relevant with any lib/framework of JS.
You can actually remove the onclick attributes just by doing a general jQuery action on document ready:
<script>
$(document).ready(function() {
var getButton = $('form').find('button');
getButton.prop('onclick',null);
// put listener script here for new form submit (using ajax)...
});
</script>
This piece of code just does a general lookup on the page for all forms, finds the buttons, then removes the onclick attribute. Once you do this the form should not submit anymore with that inline javascript.
I would suggest this be temporary as you incrementally change the forms over time to natively work using the jQuery listener (like the other 5% of forms you have created with no onclick).

Sending a form request in Python

I am trying to simulate a button click in Python on a website, when that button is clicked it adds some stuff to the end of the URL and returns false. If I add the stuff to the end of the URL it takes me to the right place but doesn't register that the button was click which is why I think I need to use the return false part.
Here is the exact code for the button and the button area. I don't know if this is actually doing anything or just setting up the button and waiting for the javascript to actually do the execution.
<div class="contractLink"><button type="button" value="upgrade to level 3"id="button533e24e4d7c79" class="green build" onclick="window.location.href = 'dorf1.php?a=16&c=fb5ad7'; return false;">
<div class="button-container addHoverClick">
<div class="button-background">
<div class="buttonStart">
<div class="buttonEnd">
<div class="buttonMiddle"></div>
</div>
</div>
</div>
<div class="button-content">upgrade to level 3</div>
</div>
</button>
This is where the script is that gets run when the button is clicked. I basically want to simulate the button being clicked through a python script which should go to a different URL and say "it's upgraded" (not literally say "it's upgraded" but make the website think it is and start the upgrading process)
<script type="text/javascript">
window.addEvent('domready', function()
{
if($('button533e24e4d7c79'))
{
$('button533e24e4d7c79').addEvent('click', function ()
{
window.fireEvent('buttonClicked', [this, {"type":"button","value":"upgrade to level 3","name":"","id":"button533e24e4d7c79","class":"green build","title":"","confirm":"","onclick":"window.location.href = \u0027dorf1.php?a=16\u0026amp;c=fb5ad7\u0027; return false;"}]);
});
}
});
</script>
Any help would be great, thanks for your time.
This is an alternative to using Python; this might be useful to those wishing to have a button click simulation without having normal subsequent action take place at the testers discretion.
Assuming that the id of the button to be simulated is "button533e24e4d7c79", the jQuery library has the trigger method to trigger the click (or any supported event for that matter) of this button:
$("#button533e24e4d7c79").trigger("click"); // This will mimic the clicking of the button (programmatically) -- requires Jquery
My understanding is that the trigger method will invoke the "click" event and stop at the event handler (i.e., won't follow links, won't continue with form submission, etc.). I haven't fully tested, but that's my understanding.
If it's desired to fully simulate the button click, jquery.simulate.js library (https://github.com/eduardolundgren/jquery-simulate/blob/master/jquery.simulate.js) provides the simulate method to allow following of links, etc.
The jQuery learning page at http://learn.jquery.com/events/triggering-event-handlers/ provides the proper explanation.

Categories