Show loader during PHP processing after an HTML form submission - php

I have an HTML form like the one shown below, which after submitting is processed by PHP:
<form action="<?php print $_SERVER['PHP_SELF'] ?>" method="POST" enctype="multipart/form-data" id="decisions_form">
<!-- ... -->
<div style="text-align:center;">
<input type="submit" name="submit" value="Submit Decisions" id="decisions_button">
</div>
</form>
PHP does some processing, which could take a few seconds. After processing is complete, I refresh the page as below (probably not best practice, I don't know):
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// PHP...
}
echo ('<meta http-equiv="refresh" content="0.1;">');
?>
I would like to show a full-screen "loader/spinner", which would be activated after submitting and during PHP processing. Normally, If I understand it correctly, this loader/spinner should be interrupted by the refresh page command -- which is what I want
Looking for such loaders was unsuccessful, if not totally confusing for a inexperienced person like me.
It would be ideal if I could avoid JS and do it in a pure HTML/CSS fashion (is it even possible?).

I am not aware of a mechanism to do it in pure HTML. There are probably other and more sophisticated ways to do it than what I show below, but this worked well for me. Every time you place a call to the server, the ajax start function executes and delays 1 second (change the delay however you want) and then displays the waiting gif. When the ajaxStop function is called upon completion of the server call and stops the wait gif and enables the buttons. Note this should be the first tag in your html file after the css definitions.
Javascript code
<script defer>
$( document ).ready(function() {
// gif on 1 second timer delay before displaying, so user does not have it appear to quickly if the delay is short.
var loadingTimer;
$(document).ajaxStart(function() {
$(':button').prop('disabled', true); // disable all the buttons
loadingTimer = setTimeout("$('#process-wait').show()", 1000); // show the waiting gif
});
$(document).ajaxStop(function() {
clearTimeout(loadingTimer);
$("#process-wait").hide(); // hide the waiting gif
$(':button').prop('disabled', false); // enable all the buttons
});
});
</script>
Here is the css you need to go along with that. You can make it as big as you want, by adjusting the height and width values. Pick your own gif image simply set the url parameter to the directory path and name of the gif file.
#process-wait {
background: transparent url(images/process-wait.gif);
background-repeat: no-repeat;
height: 150px;
width: 150px;
z-index: 99999;
display:none;
position: absolute;
top: 50%;
left: 50%;
margin-left: 10px;
margin-top: 0px;
transform: translate(-50%, -50%);

Here's a complete example:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
header("Content-Type: application/json");
echo json_encode($_SERVER);
exit;
}
?>
<!doctype html>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
<div hidden class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
<form action="<?php print $_SERVER['PHP_SELF'] ?>" method="POST" enctype="multipart/form-data" id="decisions_form">
<input type="text" name="dummy" value="dummy value">
<!-- ... -->
<div style="text-align:center;">
<input type="submit" name="submit" value="Submit Decisions" id="decisions_button">
</div>
</form>
<div class="complete" hidden>
Submission received<br>
<button class="reset">Reset</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
<script>
window.addEventListener('load', () => {
const decisionsForm = document.querySelector('#decisions_form');
const spinner = document.querySelector('.spinner-border');
const complete = document.querySelector('.complete');
const resetButton = document.querySelector('.reset');
// Show spinner, hide form
function formSending() {
spinner.removeAttribute('hidden');
decisionsForm.style.display = 'none';
}
// Hide spinner, show complete message
function formSent() {
complete.removeAttribute("hidden");
spinner.setAttribute("hidden", true);
}
// Show form, hide everything else
function reset() {
decisionsForm.style.display = 'block';
spinner.setAttribute("hidden", true);
complete.setAttribute("hidden", true);
}
// Send form data in the background
async function submitDecisionsForm(event) {
// Display spinner
formSending();
// Collect data to send
// event.target = the form
// event.target.action the action property on <form action="">
// the POST body gets set by reading the data from the form object (event.target)
const response = await fetch(event.target.action, {method: "POST", body: new FormData(event.target)});
// Submit is complete.. show the complete message and reset button
formSent();
// Format the response if you want to use it later
const responseJson = await response.json(); // or response.text() depending on what send back from the server
// Output to browser's dev console for debugging
console.log(text);
}
// Capture submit event
decisionsForm.addEventListener("submit", (event) => {
// Stop form from submitting immediately by default
event.preventDefault();
// Send form data in the background
submitDecisionsForm(event);
});
// demo: reset the form when clicking the reset button
resetButton.addEventListener('click', reset);
});
</script>
See comments in the code for explanation of parts.

Related

how to create checkbox events that call jQuery functions on other pages?

I'm wanting a checkbox in theme.php to trigger a function in front.php
that changes a css file from default with a white background to blue with a blue background.
Unchecking the checkbox reverts it back to default.
I've tried various different methods from having the script in theme.php to moving it to front.php using all the different jQuery functions including load, change, click, post, using if/else, appending to the header tags in front.php...
nothing works.
in theme.php
<div class="main-content">
<input type="checkbox" id="front"/>
<label for="front">FrontEnd</label>
</div>
and in front.php
const frontEnd = document.querySelector("#front");
frontEnd.addEventListener('change', function(e) {
if(frontEnd.checked){
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "css/blue.css";
document.getElementsByTagName("head")[0].appendChild(link);
}else{
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "css/default.css";
document.getElementsByTagName("head")[0].appendChild(link);
}
});
any tips on what I may be missing?
cheers.
$(document).ready(function($){
$('#test').click(function(){
$("#main-div").toggleClass('class-yellow');
});
// $('#test').prop('checked', true); //Checks it
// $('#test').prop('checked', false); //Unchecks it
});
.class-yellow {
background:yellow;
width:200px;
padding:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='main-div'>
<label for="test">adding style when click</label>
<input type="checkbox" id='test'>
</div>

Display a hidden DIV after a form submit action

I am trying to show a hidden div after submitting a form data
Below is my form html where the input section will have a form to enter the data and after submitting the form I have to show hidden output section and show result there
html code:
<div id="input">
----- some form datas here ----
<div id="submit">
<input type="submit" id="generate" name="script" value="generate" />
</div>
</div>
<div id="output" style="display: none;">
--- php echo from above form------
</div>
</form>
css:
#input{
width:800px;
margin: auto;
border-width:1px;
border-style:solid;
border-color:#ddd;
}
#output{
width:800px;
margin: auto;
border-width:1px;
border-style:solid;
border-color:#ddd;
}
After going through some previous discussion about the same topics, below is one of the answered solution for this
create a JavaScript like to show the hidden div after form submission.
$('form').submit(function(){
$('#output').show();
});
or
$('form').submit(function(e){
$('#output').hide();
e.preventDefault();
// Or with: return false;
});
But both the solutions are not working for me.the second is able to show the hidden div output but it not showing actual form data.
How can I show it correctly ? I need to show this after form submission (type="submit")
UPDATE:
Removed the inline css to hide div
Added css function in style sheet to hide div
#output{
display:none;
width:800px;
margin: auto;
border-width:1px;
border-style:solid;
border-color:#ddd;
}
Added below jquery to show div on form submit
$('form').submit(function(){
$('#output').css({
'display' : 'block'
});
});
Still I an not able to achieve the result. Any clue here ?
use
<form id="form" action="">
</form>
To display output
$(document).ready(function() {
$('#output').hide();
$('#form').submit(function(){
$('#output').show();
});
});
$('form').submit(function(e){
$('#doutput').hide();
e.preventDefault();
// Or with: return false;
});
Here in your script you are spelling doutput. replace it with output
and to show use .css() function and define display: block !important; because you have displayed it in your inline style so to override this you need to set !important.
Alternatively, define display: none; in the stylesheet instead of using in inline style and do the rest without setting !important
Remove Display: none;
And do this code
$('form').submit(function(e){
$('#doutput').hide();
e.preventDefault();
// Or with: return false;
});
to hide and
$('form').submit(function(e){
$('#doutput').hide();
e.preventDefault();
// Or with: return false;
});
to show
You could use .hide() and .show() as opposed to editing CSS attributes via .css().
$('document').ready(function() {
$('#output').hide();
$('form').submit(function(e) {
$('#output').show();
e.preventDefault();
});
});
if you want to show results within the DIV, there are many ways to do this.
Javascript
Give all your form data an ID, and then write a javascript function to fill the answers in the said DIV.
Ajax
Post your form to ajax, return the response to your DIV
New page request
After submitting, check to see if $_POST is set and then show the div with $_POST contents.
If I got it right you don't want to reload the page.
In this case you need to send the form data via ajax call.
Than you can display the response and the hidden div.
CSS
#output {
display:none;
}
jQuery
$(document).ready(function(){
$('form').submit(function(e){
// Prevent the default submit
e.preventDefault();
// Collect the data from the form
var formData = $('form').serialize();
//Send the from
$.ajax({
type: "POST",
url: "generator.php",
data: formData,
success: function(msg){
// Insert the response into the div
$('#ajaxResponse').html(msg);
// Show the hidden output div
$('#output').slideDown();
}
});
});
});
HTML
<div id="output">
--- php echo from above form------
<div id="ajaxResponse"></div>
</div>
You could try using the "action" attribute of the form element or you could try the jquery serializeArray method at the form element right after the submit.
<form>
<input type="text" name="giveNameHere" />
<input type="submit" id="generate" name="script" value="generate" />
</form>
<div id="output" style="display: none;">
Output Content
</div>
$('form').submit(function () {
$('#output').show();
console.log($(this).serializeArray());
return false;
});
Please see this jsfiddle

uploadprogress_get_info installed correctly and but not working in different code

I know I have no issues with installing uploadprogress extension because when I tried this very simple tutorial: http://www.ultramegatech.com/2010/10/create-an-upload-progress-bar-with-php-and-jquery/, it worked beautifully!
I then tweaked it just a little bit to have a very simple (not jQuery-UI) progress bar, which also worked. Here's the working code:
upload_getprogress.php:
<?php
if (isset($_GET['uid'])) {
$status = uploadprogress_get_info($_GET['uid']);
if ($status) {
echo round($status['bytes_uploaded']/$status['bytes_total']*100);
}
else {
echo 100;
}
}
?>
upload_form.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Upload Something</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<style>
#progress-bar, #upload-frame {
display: none;
}
</style>
<script>
(function ($) {
var pbar;
var started = false;
$(function () {
$('#upload-form').submit(function() {
$('#upload-form').hide();
pbar = $('#progress-bar');
pbar.show();
$('#upload-frame').load(function () {
started = true;
});
setTimeout(function () {
updateProgress($('#uid').val());
}, 1000);
});
});
function updateProgress(id) {
var time = new Date().getTime();
$.get('upload_getprogress.php', { uid: id, t: time }, function (data) {
var progress = parseInt(data, 10);
if (progress < 100 || !started) {
started = progress < 100;
updateProgress(id);
}
started && $('#inner').css('width', progress+ "%");
});
}
}(jQuery));
</script>
<style>
#progress-bar
{
height:50px;
width:500px;
border:2px solid black;
background-color:white;
margin:20px;
}
#inner
{
height:100%;
background-color:orange;
width:0%;
}
</style>
</head>
<body>
<form id="upload-form"
method="post"
action="upload.php"
enctype="multipart/form-data"
target="upload-frame" >
<input type="hidden"
id="uid"
name="UPLOAD_IDENTIFIER"
value="<?php echo $uid; ?>" >
<input type="file" name="file">
<input type="submit" name="submit" value="Upload!">
</form>
<div id="progress-bar"><div id='inner'></div>
<iframe id="upload-frame" name="upload-frame"></iframe>
</body>
</html>
All fine and dandy, no issues! So I know for a fact there is nothing wrong with the way I've set up the uploadprogress extension.
However, having completed the demo successfully, I needed to integrate it into my javascript and jQuery intensive web-app, which includes file uploads.
Now when I try it, I get “NULL” from the uploadprogress_get_info() function. Why?
In my application page, my image upload form is created dynamically. But at the beginning of my page (and before the user hits a button that dynamically creates an image upload form), I am using this line:
<input type='hidden' name='UPLOAD_IDENTIFIER' id='uid' value='<?php echo md5(uniqid(mt_rand())); ?>' />
Is this the problem? Is there a specific time or place this hidden input should be present?
Before including the above line at the top of my page, I've also included a long .js file that includes a bunch of jQuery plugins, but starts with the following code:
var started = false;
function updateProgress(id) {
console.log("updating progress"); // this msg appears, so i know i'm getting this far
var time = new Date().getTime();
$.get('upload_getprogress.php', { uid: id, t: time }, function (data) {
var progress = parseInt(data, 10);
if (progress < 100 || !started) {
started = progress < 100;
updateProgress(id);
}
//started && pbar.progressbar('value', progress);
$('#inner').css('width', progress+ "%");
});
}
// a lot more functions, then:
function imageDialog(imgtype, x, y, editsource) {
// this function dynamically generates a dialog for image uploading
// which shows up when a user hits an "image upload" button
// there's lots of code that creates a new form which is assigned to $imgform
// lots of elements and a couple of iframes are appended to $imgform
// then finally:
$imgform.submit(function() {
pbar = $('#progress-bar');
$('#inner').css('width', "0%");
pbar.show();
started = true;
setTimeout(function () {
updateProgress($('#uid').val());
}, 1000);
});
/* other irrelevant stuff */
}
However, while the upload progress bar shows up as expected, it never increases in progress.
So I edited the upload_getprogress.php to look like this:
if (isset($_GET['uid'])) {
$uid = $_GET['uid'];
//$status = uploadprogress_get_info($_GET['uid']);
echo "progress for $uid is: ".uploadprogress_get_info($uid);
}
In Firefox, I can see the response of the ajax call, and what I get as output from upload_getprogress.php is:
progress for 6e728b67bd526bceb077c02231d2ec6f is:
I tried to dump $status into a variable and output to file, and the file said:
the current uid: 02e9a3e0214ffd731265ec5b0b220b4c
the current status: NULL
So basically, the status is consistently returning NULL. Why? This was (and still is) working fine in the demo, what could be going wrong while integrating it into my web app code? There's nothing wrong with the image uploading on its own - my images are getting uploaded fine, but the progress isn't getting tracked!
The form that gets created dynamically looks like this:
<div class="dialog-container">
<form id="imgform" method="post" enctype="multipart/form-data" action="upload_1-img.php" target="upload_target">
Select image:
<br>
<input id="image" type="file" name="image">
<div id="imgwrapper"></div>
<input id="filename" type="hidden" value="" name="filename">
<input id="upath" type="hidden" value="xxxxxxxxxxxxxxxxxxxxxxxxxx" name="upath">
<center>
<input id="imgupload" type="submit" onclick="showUploadedItem()" value="Upload">
<input id="clearcrop" type="button" disabled="disabled/" value="Clear selection">
<input id="imgapproved" type="button" disabled="disabled" value="Done">
<input id="imgcancel" type="button" value="Cancel">
</center>
</form>
</div>
<div id="progress-bar"><div id='inner'></div></div>
<!-- etc etc some other elements -->
</div>
and my own upload_1-img.php starts off with:
$filename = $_FILES["image"]["tmp_name"];
$file_info = new finfo(FILEINFO_MIME);
$bfr = $file_info->buffer(file_get_contents($filename)) or die ("error");
// some more stuff, getting file type and file's $name
if( /* a bunch of conditions */ )
move_uploaded_file( $_FILES["image"]["tmp_name"], $upath . "/" . $name);
Woohoo! I figured it out, thanks to this bug:
https://bugs.php.net/bug.php?id=57505
Basically, just I removed this static line from the page where users get to upload files:
<input type='hidden' name='UPLOAD_IDENTIFIER' id='uid' value='<?php echo md5(uniqid(mt_rand())); ?>' />
and in my javascript function that creates the image dialog dynamically, I just added the hidden input dynamically, right above the line where I generated the file input.
So the relevant part of the dynamically created form then looks like:
<input type='hidden' name='UPLOAD_IDENTIFIER' id='uid' value='1325a38f3355c0b1b4' />
<input id="image" type="file" name="image">
Now since this is getting dynamically created via javascript anyway, I can just replace that value above with a random js function.
Now the progress bar is advancing as it ought to! :D

Getting variable from the Url

I have a jquery function that retrieves information that a user clicks on in a database table.The user can select any one of ten rows that becomes highlighted when mouseover and when the user clicks the highlighted row the function retrieves it and puts it into a textbox. Then if the user submits this request for purchase I want to echo the textbox on the next page which is an order form.
The code below works well up until I try to retrieve the information from the url. I can see that it is passed in the url to the next page but after trying for two days I have not been able to retrieve it. I don't know where to go from here. Can someone look at this and see if I have not coded properly or done something wrong.
I have copied down the code that applies...
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("table tr").click(function(){
$("#txttread").val($.map($(this).children('td:not(:eq(7))'), function (item) { return $(item).text() }).join(' - '));
});
});
$(document).ready(function() {
$('.pickme tr').not(':first').hover(
function() { $(this).addClass('highlight'); },
function() { $(this).removeClass('highlight'); }
).click( function() {
$('.selected').removeClass('selected');
$(this).addClass('selected').find('input').attr('checked','checked');
});
});
</script>
</head>
<body>
<form action="Order.html" method="GET" name="myform2" />
<div>
<div style="text-align:left height:250px;">
<DIV STYLE="font-family: Arial Black;
color: black; font-size: 20pt;">
Select from inventory below:<br/><input type="text" style="width:500px; height:35px;" rows="1" STYLE="font-family: Arial Black;
color: red; font-size: 20pt;" name="txttread" id="txttread" DISABLED /></div></div></div>
<div>
<div style="text-align:center;">
<br/><input type="button" button id="getone" name="getone" value="Submit your request for purchase" onclick="window.location.href = 'http://localhost/order.html?txttread='+ ( $('#txttread').val() )"><br/><hr/>
</body>
</html>
The url on the next page is....
http://localhost/order.html?txttread=Firestone - All Season - FR-710 - 225/60/16 - 4 - 3 - 60.00
I think this has to do with the URL not being encoded correctly. On that last line where you append the $('#txttread').val(), you should wrap it with encodeURIComponent():
<input type="button"
button id="getone"
name="getone"
value="Submit your request for purchase"
onclick="window.location.href = 'http://localhost/order.html?txttread=' + encodeURIComponent($('#txttread').val());">
This might not answer your question completely, but consider this:
window.location.href = 'http://localhost/order.html?txttread='+ ( $('#txttread').val() )
You should apply proper escaping when you pass parameters:
window.location.href = 'http://localhost/order.html?txttread=' + encodeURIComponent( $('#txttread').val() );
To access the value of txttread from an HTML page:
function getParameterByName(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.search);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
As found here: https://stackoverflow.com/a/901144/1338292

jquery/ajax doesnot work

For some reason this does not work. I have copy/paste the code, but it goes to the html-echo.php rather than displaying the result in the htmlExampleTarget
What am I doing wrong here.
Thanks
Dave
edit: sorry guys - here is the url - http://jquery.malsup.com/form/#html
<script src="js/jquery-1.3.2.js" type="text/javascript" language="javascript"></script>
<script type="text/javascript">
// prepare the form when the DOM is ready
$(document).ready(function() {
// bind form using ajaxForm
$('#htmlForm').ajaxForm({
// target identifies the element(s) to update with the server response
target: '#htmlExampleTarget',
// success identifies the function to invoke when the server response
// has been received; here we apply a fade-in effect to the new content
success: function() {
$('#htmlExampleTarget').fadeIn('slow');
}
});
});
</script>
<div style="position:absolute; top:129px; left: 400px; width:500px; border:#000000 thin solid;">
<form id="htmlForm" action="submit_form.php" method="post">
Message: <input type="text" name="message" value="Hello HTML" />
<input type="submit" value="Echo as HTML" />
</form>
Reply: <div id="htmlExampleTarget"></div>
</div>
and on the submit-form.php page
echo '<div style="background-color:#ffa; padding:20px">' . $_POST['message'] . '</div>';
You have two <script> elements. One of them loads jQuery, the other runs ajaxForm. You haven't loaded the .js file that contains the ajaxForm code.
See the documentation:
Include jQuery and the Form Plugin external script files and a short script to initialize the form
Since you haven't, the script errors when trying to run the function, so it doesn't prevent the default action. The code to make the Ajax request is missing (so that doesn't happen), and the default action runs (for the browser goes to the URI in the action attribute).

Categories