Click here: henriquecosta.kdhost.eu.org, type the number 00008513 and choose a radio button and enter, then choose any 8-digit number and type. This part is working wonderfully after so much sacrifice for me, I'm not a programmer. The problem is that when another div is loaded, the previous one is deleted. I need all divs to remain on the page, in all it will be 40 divs. Yesterday I could not resolve with the localstorage, I think it is the solution, after that the script will be finished. Well, I'm happy with what I got so far. If anyone has any tips to give me, I'll be very grateful! Thank you.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
</head>
<body>
<script>
var form = document.querySelector('form');
form.addEventListener('submit', function(e) {
e.preventDefault(); // <--- isto pára o envio da form
var url = this.action; // <--- o url que processa a form
var formData = new FormData(this); // <--- os dados da form
var ajax = new XMLHttpRequest();
ajax.open("GET", url, true);
ajax.onload = function() {
if (ajax.status == 200) {
var dados = JSON.parse(ajax.responseText);
alert('Dados enviados:\n' + JSON.stringify(dados, null, 4));
} else {
alert('Algo falhou...');
}
};
ajax.send(formData);
});
</script>
<form action="index.php">
Cartao:<input size="7" name="cartao" value="" required="" pattern="[0-9]{8}" type="text">
<input value="01" name="armario" type="radio" />01
<input value="02" name="armario" type="radio" />02
<input value="03" name="armario" type="radio" />03
<button type="submit">Enviar</button>
</form>
<table width=100% border=1>
<tbody>
<tr align=center valign="middle">
<td width=33%><div id="01"></div></td>
<td width=33%><div id="02"></div></td>
<td width=33%><div id="03"></div></td>
</tr>
</tbody>
</table>
<?php
if (isset($_GET['cartao'])):
$radioValue = $_GET['armario'];
$radiovalor = '"'.$radioValue.'"';
$file = 'banco.txt';
$searchfor = $_GET['cartao'];
//header('Content-Type: text/plain');
$contents = file_get_contents($file);
$pattern = preg_quote($searchfor, '/');
$pattern = "/^.*$pattern.*\$/m";
if(preg_match_all($pattern, $contents, $matches)):
json_encode($matches[0]);
$resultado = str_replace(array('"',' \r','[', ']'), '', htmlspecialchars(json_encode($matches[0]), ENT_NOQUOTES));
else:
$resultado = $_GET['cartao'];
endif;
else:
echo '';
endif;
// file_exists
if (isset($_GET['cartao'])) {
$path = './fotos/';
$recebe = $_GET['cartao'];
$img = $path.$recebe.".jpg";
if (file_exists($img)) {
$foto = '"<img width=80 height=80 src="'.$img.'">'; // existe
} else { $foto = ' <img width=80 height=80 src="./fotos/ausente.jpg">'; // não existe
}
}
?>
<script>
var x = '<?php echo $resultado, $foto; ?>';
var z = '<?php echo $radioValue; ?>';
document.getElementById(z).innerHTML += x;
</script>
</body>
</html>
There are several problems in your code which you are probably not aware of.
First of all, your whole page is reloaded everytime you click the "Enviar" button, because your javascript does not correctly prevent the default action.
To accomplish this, return false at the end of the function:
var form = document.querySelector('form');
form.addEventListener('submit', function(e) {
e.preventDefault(); // <--- isto pára o envio da form
var url = this.action; // <--- o url que processa a form
var formData = new FormData(this); // <--- os dados da form
var ajax = new XMLHttpRequest();
ajax.open("POST", url, true);
ajax.onload = function() {
if (ajax.status == 200) {
var dados = JSON.parse(ajax.responseText);
alert('Dados enviados:\n' + JSON.stringify(dados, null, 4));
} else {
alert('Algo falhou...');
}
};
ajax.send(formData);
return false;
});
By doing this, the whole page will not be reloaded.
Secondly, your server always returns a full html page, instead of differentiating, whether the url has been accessed by opening the page for the first time or if it received a request from your script.
If isset($_POST['cartao'] is true, than the request came from your javascript and you should return a JSON object containing the relevant data and build the html in your javascript and append it to your table.
I know that this all sounds a bit confusing if you are not a programmer but I hope I could point you in the right direction.
Once you return a JSON object from your server, I am happy to help you to render HTML from it in javascript.
Related
I have the following code:
- the javascript helps me select a text file and it chooses only the id from the text file. example of text file is below:
ID,Name,Surname
re-002,ram,kelu
rf-897,rem,juke
When i added the button 'loader', the javascript readText no longer displays the id that it took from the text file.
What i want to do is to allow user to select a text file, read only the ids, and then place the ids in my database.
My html page:
<!DOCTYPE html>
<html>
<head>
<title>reading file</title>
<script type="text/javascript">
var reader = new FileReader();
function readText(that){
if(that.files && that.files[0]){
var reader = new FileReader();
reader.onload = function (e) {
var output=e.target.result;
//process text to show only lines with "-":
output = output.split("\n").filter((line, i) => i != 0).map(line => line.split(",")[0]).join("<br/>\n");
document.getElementById('main').innerHTML= output;
};//end onload()
reader.readAsText(that.files[0]);
}
}
$("#loader").on("click", function(){
var upload = $.ajax({
type: "POST",
url: "loader.php",
data: {array:output},
cache: false,
beforeSend: function() {
}
});
</script>
</head>
<body>
<h1> Utilisateur Nommé </h1>
<h3> Import : <button id="loader" onclick='btn()'> Import</button>
<h3> Choose file : <input type="file" onchange='readText(this)' />
</h3>
</body>
</html>
My php page 'loader.php':
<?php
define ( 'DB_HOST', 'localhost' );
define ( 'DB_USER', 'root' );
define ( 'DB_PASSWORD', '' );
define ( 'DB_NAME', 'dbapp' );
$array = json_decode($_POST['output']);
$mysqli = new mysqli('DB_HOST','DB_USER','DB_PASSWORD','DB_NAME');
$arr_id = $mysqli->real_escape_string($array[0]);
if ($mysqli->connect_error) {
die('Error : ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
}
//MySqli Insert Query
$insert_row = $mysqli->query("INSERT INTO `user` (id) VALUES($arr_id)");
if($insert_row){
print 'Success! ID of last inserted record is : ' .$mysqli->insert_id .'<br
/>';
}else{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
// close connection
$mysqli->close();
?>
Your code is brittle. But moving output declaration outside readText might help actually send some data
var output; // move the output declaration here
var reader = new FileReader();
function readText(that) {
if (that.files && that.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
output = e.target.result;
//process text to show only lines with "-":
output = output.split("\n").filter((line, i) => i != 0).map(line => line.split(",")[0]).join("<br/>\n");
document.getElementById('main').innerHTML = output;
}; //end onload()
reader.readAsText(that.files[0]);
}
}
function btn() {
var upload = new XMLHttpRequest();
upload.open("POST", "loader.php");
upload.send(JSON.stringify({ array: output }))
upload.onreadystatechange = function () {
if (upload.readyState === XMLHttpRequest.DONE) {
if (upload.status === 200) {
alert(upload.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
}
<main id="main"></main>
<h1> Utilisateur Nommé </h1>
<h3> Import : <button id="loader" onclick="btn()"> Import</button>
<h3> Choose file : <input type="file" onchange='readText(this)' />
Bonus: done without jQuery.
https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started
I'm trying to upload a file and some text inside a textarea together using AJAX. I'm getting the following error in the PHP page that receives the data:
Notice: Undefined index: guion in file/path/here on line X
It means that the file is not being sent. Tried var_dump $_FILES and it output:
array(0) { }
HTML Code:
<div id="_AJAX_"></div>
<div role="form">
<div id="fileGuionGroup" class="form-group">
<label for="guion">Archivo Guión</label>
<input id="fileGuion" type="file" name="guion">
</div>
<div id="txtComentarioGroup" class="form-group">
<label for="comentario">Comentario</label>
<textarea id="txtComentario" class="form-control" name="comentario" rows="4" placeholder="Ejemplo: Solicito que por favor se monte este curso en plataforma."></textarea>
</div>
</div>
<button id="send_request" type="button" class="btn btn-primary btn-block" onclick="submitSolicitud(`{$cursoKey}`)"><i class="fa fa-fw fa-cogs"></i> Solicitar Montaje</button>
Javascript Code:
function submitSolicitud(cursoKey) {
var fileGuion = document.getElementById('fileGuion');
var txtComentario = document.getElementById('txtComentario');
var formGroupGuion = document.getElementById('fileGuionGroup');
var formGroupComentario = document.getElementById('txtComentarioGroup');
formGroupGuion.className = "form-group";
formGroupComentario.className = "form-group";
var guion = fileGuion.value;
var comentario = txtComentario.value;
var formData = new FormData();
formData.append('guion', guion);
formData.append('comentario', comentario);
connect = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
connect.onreadystatechange = function () {
onRSCallback(cursoKey);
};
connect.open('POST', '?view=modalsMatriz&modal=montaje&id=' + cursoKey + '&action=solicitarMontaje', true);
connect.setRequestHeader("Content-Type", "multipart/form-data");
connect.setRequestHeader("X-File-Name", guion.name);
connect.setRequestHeader("X-File-Size", guion.size);
connect.setRequestHeader("X-File-Type", guion.type);
connect.send(formData);
};
PHP Code:
case 'solicitarMontaje':
// This is the line that has the error of undefined index.
die($_FILES['guion']);
try {
if (!isset($_FILES['guion'])) {
# Code 1: Archivo Guión Field vacía
throw new Exception(1);
} elseif (!isset($_POST['comentario']) || $_POST['comentario'] == "") {
# Code 2: Comentario Field vacío
throw new Exception(2);
}
$tmp_file = $_FILES['guion']['tmp_name'];
$filename = $_FILES['guion']['name'];
move_uploaded_file($tmp_file, 'uploads/guiones/'.$filename);
die(0);
//$curso->crearSolicitudMontaje($_POST['comentario']);
} catch (Exception $e) {
# Output message to the screen so that Ajax captures it via connect.responseText #curso_FormMontaje.js
echo $e->getMessage();
}
break; # ./ case 'solicitarMontaje'
I've tried it using FormData() and Content-Type multipart/form-data but it did not work at all. Instead it was making the page be embedded inside the _AJAX_ div that shows the messages returned from the server (such as success messages, errors at some fields i.e fields that were sent empty).
This is what I get as result using FormData when clicking the submit button:
https://postimg.org/image/rsnrt3yq9/
Here is a very simple form data example, given what you have provided:
<script>
$(document).ready(function(){
// I don't know what your form is called...
$('.uploader').submit(function(e) {
// Clone the file input
var getFileInput = $("#fileGuion").clone();
// Stop form from submitting
e.preventDefault();
$.ajax({
url:'/url/to/ajax/dispatcher.php',
// Use FormData object, pass form
data: new FormData($(this)[0]),
processData: false,
contentType: false,
type: 'post',
success: function(response) {
// Put html back into placeholder
$('#_AJAX_').html(response);
// Replace the input
$("#fileGuion").replaceWith(getFileInput);
}
});
});
});
</script>
<div id="_AJAX_"></div>
<form class="uploader">
<label for="guion">Archivo Guión</label>
<input id="fileGuion" type="file" name="guion">
<label for="comentario">Comentario</label>
<textarea id="txtComentario" class="form-control" name="comentario" rows="4" placeholder="Ejemplo: Solicito que por favor se monte este curso en plataforma."></textarea>
<label>
<input type="checkbox" id="ackCheckbox"> <i>He revisado y estoy seguro de continuar con esta acción.</i>
</label>
<input type="submit" value="Upload">
</form>
Turns out that what was causing issues were the HTTP headers (setRequestHeader). I removed them and edited the code a little bit, here's what it looks like now fully functional:
JavaScript Code:
function submitSolicitud(cursoKey) {
var fileGuion = document.getElementById('fileGuion');
var txtComentario = document.getElementById('txtComentario');
var guion = fileGuion.files[0];
var comentario = txtComentario.value;
var formData = new FormData();
formData.append('guion', guion);
formData.append('comentario', comentario);
connect = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
connect.onreadystatechange = function () {
onRSCallback(cursoKey);
};
connect.open('POST', '?view=modalsMatriz&modal=montaje&id=' + cursoKey + '&action=solicitarMontaje', true);
connect.send(formData);
};
As expected, the data is recognized by PHP as below:
The file "guion" comes into PHP's $_FILES array ($_FILES['guion']).
The "comentario" field (textarea) is sent inside PHP's $_POST array ($_POST['comentario']).
Finally, both HTML and PHP code stayed the same and the conclusion is that by not setting the HTTP headers they seem to take the proper value automatically so that the request processes correctly.
I need to send only 1 variable to my .php file using AJAX (using method POST) and show it (with php). Here is my HTML code:
<script type = "text/javascript">
var XMLHttpRequestObject = false; //LO INICIALIZAMOS A FALSO PARA DESPUES COMPROBAR QUE ESTA CREADO CORRECTAMENTE
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); //PARA INTERNET EXPLORER
}
function irweb(idDiv) {
if (XMLHttpRequestObject) {
var objeto = document.getElementById(idDiv);
nom1="holaaaaaaa";
// var nom1 = document.getElementById('nombre').value;
//var com1 = document.getElementById('comentarios').value;
XMLHttpRequestObject.open("POST", "p2.php?");
XMLHttpRequestObject.setRequestHeader("Content-type","application/x-www-form-urlencoded");
XMLHttpRequestObject.onreadystatechange = function() {
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
objeto.innerHTML = XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send("n="+nom1);
}
}
</script>
</head>
<body>
<form method="post" id="formulario">
<input type="submit" value="Enviar" onclick ="irweb('contenedor')" id="enviar"/>
</form>
<div id="contenedor" style="background-color:#99FF66;text-align:center;"></div>
</body>
Here is my PHP code:
<?php
$cabe = <<< 'EOD'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
</head>
<html>
<body>
<p>hola</p>
</body>
</html>
EOD;
$pasado1=$_POST["n"];
$pasado2=$_POST["c"];
echo "El parametro pasado es -->".$pasado1;
echo "El parametro pasado es -->".$pasado2;
?>
I called some alerts in the JS code, to chek if I get the values correctly, and it works, but when I call the php file, nothing happens
When you click on the submit button, you:
Run the JavaScript
Submit the form
You don't see a result from the JS because the form submits (reloading the page) before the readystate has reached 4.
Stop the form submitting if the JS runs:
onclick="irweb('contenedor'); return false;"
… and fix your server side script so it can handle the POST data if the JS fails for any reason and the form does submit.
Have you tried using jquery? If not, try it for easy coding and maintenance
http://api.jquery.com/jQuery.post/
The ajax post code is simply as below :
$.ajax({
type: "POST",
url: url,
data: data,
success: success,
dataType: dataType
});
I need the onkeyup to fire more than once, but it seems to be only firing once!
When I enter something into the input box, it searches, but then whenever I backspace and search something else, the div stay's the same..
Here is my code:
<script type="text/javascript">
function suggest1() {
var dam_text = document.getElementById('dam').value;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject('MicrosoftXMLHTTP');
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById('myDiv').innerHTML = xmlhttp.responseText;
}
}
var target = 'dam_search.php?dam_text=' + dam_text;
xmlhttp.open('GET', target, true);
xmlhttp.send();
}
</script>
<input type="text" name="dam" id="dam" onkeyup="suggest1();"><br />
<div id="myDiv"></div>
Here is dam_search.php
<?php
//connect to db stuff here
if (isset($_GET['dam_text'])) {
$dam = $_GET['dam_text'];
getSuggest($text);
}
function getSuggest($text) {
$sqlCommand = "SELECT `name` FROM `table1` WHERE `name` LIKE '%$dam_text%'";
$query = mysql_query($sqlCommand);
$result_count = mysql_num_rows($query);
while ($row = mysql_fetch_assoc($query)) {
echo $row['name'].'<br />';
}
}
?>
ALSO: I am wondering how I can put the return of the name's it has searched into a dropdown from the input box instead of into the div, so when I click on one of the names, it auto fills the input box.
Thank you!
Still not sure about your issue with the keyup only firing once per page-load. That's very hard to speculate reasonably on without seeing more code. Never-the-less, here's an example I just threw together of how you can present the returned data in a more useful way.
The code requires that you download the AjaxRequest library I mentioned in an earlier comment.
(http://ajaxtoolbox.com/request/)
Here, I demo a few principles.
Arranging the data into a php class
constructing an array of instances of this class
returning this array as JSON
catching the JSON text and turning it back into an object in JS
Processing the data
I've given 2 very simple example - the first simply loads all filenames in the current directory (that holds jsonDir.php) into a select element. Choosing a filename results in it being copied into a text input next to the button.
The second, only retrieves names of png files. It chucks them all into a select element too. This time however, when an item is selected it is used as the src for an image. In each case the filenames are only grabbed if/when the corresponding button is pressed. There's a bit of redundant/otherwise crappy code I could have done better, but after 20 hours awake, I'm ready for bed!
Hope it's useful for you. Any questions, just ask. :)
1. jsonDir.php
<?php
class mFile
{
public $name, $time, $size;
}
if (!isset($_GET['wildcard']))
$wildCard = "*.*";
else
$wildCard = $_GET['wildcard'];
foreach (glob($wildCard) as $curFilename)
{
$curFileObj = new mFile;
$curFileObj->name = $curFilename;
$curFileObj->time = date("d/m/Y - H:i", filectime($curFilename));
$curFileObj->size = filesize($curFilename);
$fileArray[] = $curFileObj;
}
printf("%s", json_encode($fileArray));
?>
2. readDir.html
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='script/ajaxRequestCompressed.js'></script>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function myGetAjaxResponseWithCallback(url, target, callbackFunc)
{
AjaxRequest.get(
{
'url':url,
'onSuccess':function(req){ callbackFunc(req.responseText, target); }
}
);
}
function getResults1()
{
var url = "jsonDir.php";
var target = byId('resultsDiv');
myGetAjaxResponseWithCallback(url, target, jsonDataReceived1);
}
function getResults2()
{
var url = "jsonDir.php?wildcard=*.png";
var target = byId('resultsDiv2');
myGetAjaxResponseWithCallback(url, target, jsonDataReceived2);
}
function jsonDataReceived1(responseText, targetContainer)
{
var resultObject = JSON.parse(responseText);
targetContainer.innerHTML = "";
var mStr = "There were " + resultObject.length + " records returned" + "<br>";
var mSel = newEl("select");
mSel.addEventListener('change', doAutofill, false);
var i, n = resultObject.length;
for (i=0; i<n; i++)
{
var curRecordOption = new Option(resultObject[i].name, i);
mSel.appendChild(curRecordOption);
}
targetContainer.innerHTML = mStr;
targetContainer.appendChild(mSel);
}
function jsonDataReceived2(responseText, targetContainer)
{
var resultObject = JSON.parse(responseText);
targetContainer.innerHTML = "";
var mSel = newEl("select");
mSel.addEventListener('change', showSelectedImg, false);
var i, n = resultObject.length;
for (i=0; i<n; i++)
{
var curRecordOption = new Option(resultObject[i].name, i);
mSel.appendChild(curRecordOption);
}
targetContainer.innerHTML = '';
targetContainer.appendChild(mSel);
}
function doAutofill(e)
{
var curSelIndex = this.value;
var curText = this.options[curSelIndex].label;
byId('autofillMe').value = curText;
}
function showSelectedImg(e)
{
byId('previewImg').src = this.options[this.value].label;
}
</script>
<style>
img
{
border: solid 2px #333;
}
</style>
</head>
<body>
<button onclick='getResults1()'>Get *.* dir listing</button> <input id='autofillMe'/>
<div id='resultsDiv'></div>
<hr>
<button onclick='getResults2()'>Get *.png dir listing</button> <img id='previewImg' width='100' height='100'/>
<div id='resultsDiv2'></div>
</body>
</html>
Found out my problem. The query wasn't correctly being processed!
I had the variable $dam_text as the LIKE statement, when it should have been $dam:
<?php
//connect to db stuff here
if (isset($_GET['dam_text'])) {
$dam = $_GET['dam_text'];
getSuggest($text);
}
function getSuggest($text) {
$sqlCommand = "SELECT `name` FROM `table1` WHERE `name` LIKE '%$dam_text%'";
$query = mysql_query($sqlCommand);
$result_count = mysql_num_rows($query);
while ($row = mysql_fetch_assoc($query)) {
echo $row['name'].'<br />';
}
}
?>
Also, the variable $dam wasn't being submitted inide the function, so I moved it from the 'if' statement, into the function:
<?php
//connect to db stuff here
if (isset($_GET['dam_text'])) {
getSuggest($text);
}
function getSuggest($text) {
$dam = $_GET['dam_text'];
$sqlCommand = "SELECT `name` FROM `table1` WHERE `name` LIKE '%$dam%'";
$query = mysql_query($sqlCommand);
$result_count = mysql_num_rows($query);
while ($row = mysql_fetch_assoc($query)) {
echo $row['name'].'<br />';
}
}
?>
The above code works perfectly! Turns out it wasn't onkeyup after all! Thanks for all your help!
OnKeyUp will only fire once per event. pressing 'A' 'B' and 'C' will result in three calls to suggest1();
To make sure your browser is working correctly try this
<script type="text/javascript">
function suggest1() {
document.getElementById('myDiv').innerHTML = document.getElementById('dam').value;
}
</script>
<input type="text" name="dam" id="dam" onkeyup="suggest1();"><br />
<div id="myDiv"></div>
You should see the div change for every keystroke that occurs in the input.
There is two many unknowns for me to directly point at your actual issue.
Your PHP will output nothing for a zero entry query, and will only output 1 item if you query LIKE only matches one thing. I think your problem lies elsewhere, an not with onkeyup
T test to onkeyup on your system/browser:
Try adding some debug header like echo strlen($text).'<br />'; to your PHP file. You should see the number change with out relying on your SQL query for every key press that adds or deletes text (that includes the backspace key).
Your code looks fine. And runs fine for me using the public HTTP GET echo service at http://ivanzuzak.info/urlecho/
Swapping out your PHP for the echo service works fine (with a bit of a typing delay)
<script type="text/javascript">
function suggest1() {
var dam_text = document.getElementById('dam').value;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject('MicrosoftXMLHTTP');
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById('myDiv').innerHTML = xmlhttp.responseText;
}
}
var target = 'http://urlecho.appspot.com/echo?body=' + dam_text;
xmlhttp.open('GET', target, true);
xmlhttp.send();
}
</script>
<input type="text" name="dam" id="dam" onkeyup="suggest1();"><br />
<div id="myDiv"></div>
I have an expensive form action that builds a zip file on the server and returns it to the browser.
<form action='/download' method='post'>
<input type='submit' value='download'/>
</form>
I want to block the page on click of the button so that the user doesn't repeatably hit the button.
However I want to unblock the page after the form returns.
How can trigger an event on successful completion of the form?
(I know I can trigger this by changing the form to be an ajax submission but then the save file dialog does not appear...)
Any suggestions?
Thanks
One way you could handle this without using AJAX could be submitting the content of the form to an iframe element. If you attach an onsubmit function to the form that disables further submissions and attach an onload function to the iframe, you should be able to disable the user from submitting the form multiple times.
Example HTML:
<form action="/download" method="post" target="downloadFrame" onsubmit="return downloadFile();">
<input type="submit" value="download" />
</form>
<iframe style="width: 0px; height: 0px;" scrolling="no" frameborder="0" border="0" name="downloadFrame" onload="downloadComplete();"></iframe>
Example Javascript:
var downloading = false;
function downloadFile() {
var isDownloading = downloading;
downloading = true;
return !isDownloading;
}
function downloadComplete() {
downloading = false;
}
It appears no one has yet found a way to detect the post return in the browser itself, but there is another possibility using AJAX. It is a bit more involved though:
<script type="text/javascript">
$(function () {
$('#submitbtn').click (function () {
window.setTimeout (dldone, 100);
return true;
});
function dldone () {
$.get ("/downloadstatus?rand="+$('#rand').val (), function (data) {
if (data == 'done') {
// data generation finished, do something
} else {
window.setTimeout (dldone, 100);
}
});
}
});
</script>
<form action="/generatedata" method="post">
<input type="hidden" id="rand" value="[RANDOMVALUE]">
<input type="submit" id="submitbtn" value="Download Data">
</form>
On the server, you would have to do some inter-process-communication to signal when the data generation is done. Since I already have a database, I did it like this:
public function downloadstatusAction () {
if ($this->db->fetchOne ("SELECT rand FROM dlstatus WHERE rand = ?", (int) $_GET["rand"])) {
$db->delete ("dlstatus", array ("rand = ?" => (int) $_GET["rand"]));
print "done";
} else {
print "loading";
}
}
public function generatedataAction () {
// generate data
$this->db->insert ("dlstatus", array ("rand" => (int) $_POST["rand"]));
// output data
}
I am sure there are more elegant ways to do this, but you get the idea. This appears to work fine in all browsers I tested.
I used this:
function generatePdfZipViaWS_ajax(theUrl) {
//=========================
// testé avec Chrome 37.0.2062.124 m, Firefox 32.0.3
// ça block avec IE9 à cause du xmlHttp.overrideMimeType
//=========================
var xmlHttp = new XMLHttpRequest();
var alert = document.getElementById("alertError");
block_UI();
var url = "undefined";
xmlHttp.open("GET", theUrl, true);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlHttp.overrideMimeType("application/octet-stream");
xmlHttp.responseType = "blob";
xmlHttp.onload = function(oEvent) {
if (xmlHttp.status == 200) {
deblock_UI();
// a mettre apres un certain temps: window.URL.revokeObjectURL(url);
} else {
alert.style.display = "block";
deblock_UI();
// console.log("Error " + xmlHttp.status + " occurred downloading your file.<br \/>");
}
};
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == xmlHttp.DONE) {
if (xmlHttp.status == 200) {
var contentDisposition = xmlHttp.getResponseHeader("Content-Disposition");
var type = xmlHttp.getResponseHeader("Content-Type");
var reponseType = xmlHttp.responseType;
var pos1 = contentDisposition.indexOf("archive");
var pos2 = contentDisposition.lastIndexOf(".zip") + 4;
var fileName = contentDisposition.substring(pos1, pos2);
if (fileName === null) {
fileName = "archivexxxxxxxxxxxxxx.zip";
}
console.log("fileName:" + fileName);
var blob = xmlHttp.response;
url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.style = "display: none";
a.href = url;
a.download = fileName;
a.type = type;
document.body.appendChild(a);
a.click();
//a.delete();
deblock_UI();
} else {
var msg =" Une erreur " + xmlHttp.status +" est apparue pendant que votre demande était traitée.\n"
msg = msg + "Merci de réessayer plus tard!";
alert.innerHTML = msg;
alert.style.display = "block";
deblock_UI();
console.log(msg);
}
}
};
xmlHttp.send();
}
I don't have time to write a proper answer right now, but since nobody else has a good answer, I think a "Mutation Observer" would work... https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver