localStorage causes infinite refreshing the page? - javascript

I'm doing localStorage for a simple form. When user open up the form, all the saved data will be displayed in the corresponding input filed, and after user fills out the form, all the info will be saved.
Now I can save the data and also display the data, just that when I reopen the page, data is displayed while the page's being infinite refreshed. Does anybody know how did that happen?
Here is the code:
HTML:
<form id="formData">
<fieldset>
<legend>Please fill in</legend>
<label for="name">Name:</label>
<input name="name" type="text"><br/>
<label for="txt">Introduction:</label>
<input name="txt" type="textarea"><br/>
<label for="someCheck">Checkbox:</label>
<input name="someCheck" type="checkbox"><br/>
<label for="someRadio">Radio:</label>
<input name="someRadio" type="radio"><br/>
<input type="submit">
</fieldset>
CSS:
fieldset{
width: 50%;
margin: 0 auto;
padding: 5px 20px;
box-sizing: border-box;
}
label{
width: 18%;
display: inline-block;
}
input{
margin: 0;
padding: 0;
}
input[type=submit]{
padding: 2px 10px;
outline: none;
border-radius: 4px;
margin: 6px 0;
cursor: pointer;
}
Jquery:
if(Modernizr.localstorage){
var form=document.querySelector('#formData');
if(localStorage.formData){
//step one:
//display the stored value, title=my+title&...&
var fd;
fd=localStorage.formData.split('&'); //['title=my+title']
$.each(fd,function(index,pair){
pair=pair.split('=');//title,my+title
console.log(pair[0]+":"+pair[1]);
if(pair[1]==="on"){
form[pair[0]].checked=true;
}else{
form[pair[0]].value=unescape(pair[1]).replace(/\+/g," ");
}
});
}
//step two:
//save form to storage when filled outline
form.submit(function(e){
//serialize form data to url
localStorage.formData=$(this).serialize();
alert('Okay, refresh the page now.');
e.preventDefault();
});
}

The infinite reload is caused by form.submit(). That is triggering the HTML submit action. Part of which is to reload the page.
I suspect what you really want is to listen for the submit event and do the local storage save:
document.querySelector("#formData").addEventListener("submit", function(e){
localStorage.formData=$(this).serialize();
alert('Okay, refresh the page now.');
e.preventDefault();
});

Related

How to stop spinner after operation is finished

I am building my first web app using Flask. I'm new to html/ JavaScript/ CSS - please bear with me.
The app does the following: The user uploads an Excel file as follows:
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
Then they select certain parameters using dropdown lists. When the user clicks "Submit", the data is manipulated using pandas and a new file is exported in Excel.
I managed to add a spinner to the "submit" button using html and CSS. I added an event listener to my JavaScript so the spinner is activated when the button is clicked. At the moment, the spinner runs indefinitely, however I would like the spinner to stop and the button text to revert to "submit" once the operation is finished, i.e. the export is complete. Does anybody know how I can accomplish this?
Here is my html:
<button type="submit" id="submit" class="button">
<span class="button__text">Submit</span>
</button>
Here is my CSS:
<style>
.button {
position: relative;
padding: 8px 16px;
background: #009579;
border: none;
outline: none;
border-radius: 2px;
cursor: pointer;
}
.button:active {
background: #007a63;
}
.button__text {
font: bold 20px "Quicksand", san-serif;
color: #ffffff;
transition: all 0.2s;
}
.button--loading .button__text {
visibility: hidden;
opacity: 0;
}
.button--loading::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border: 4px solid transparent;
border-top-color: #ffffff;
border-radius: 50%;
animation: button-loading-spinner 1s ease infinite;
}
/*animate spinner - spin from 0 to 1 turn*/
#keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
</style>
Here is my JavaScript:
<script type="text/javascript">
(() => {
const elem = document.getElementById('submit');
elem.disabled = false;
elem.addEventListener('click', e=> {
elem.classList.add('button--loading');
});
})();
</script>
Basically, your frontend (the HTML/Javascript) needs some way of knowing when "the export is complete". Depending on your definition of "export" and "complete".
At the most rudimentary level, you could have the frontend poll the server every second after the upload starts, and have the server return some kind of status as to what the state of the process is. This could be as simple as:
GET /status/1234
> {"status": "IN_PROGRESS"}
which, when the "export is complete" switches to:
> {"status": "COMPLETE"}
And when the frontend receives the COMPLETE status, it removes the spinner. Notice the 1234. You will need some way of identifying the upload in progress. One way to do this would be to assign it a random id when you first accept the form, so the initial POST /upload returns > {'id': 1234} which the client can then use for the subsequent polling.
If "export is complete" actually only means that the file is finished uploading, you could still use a polling method, but a much slicker way is to use the client (web browser) method of determining how many bytes have been sent (see this SO answer).

PHP-based form auto completion with large dataset [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am developing a web application where I have a large (~ 50'000) quantity of text strings (called "items" here) in a SQL database. The user shall select three out of these items in a input form. I tried a few "direct" solutions (Drop-Down combo box, etc.), but these are far too slow with 50'000 items to choose from. Traditional solutions which use JavaScript to implement auto-completion for text boxes suffer from a similar problem: The JavaScript file with the allowed choices becomes far too large (many MiB).
I would prefer to have a solution where the remaining possible items are dynamically fetched from the SQL database while the user types. If, e.g., the first three letters have been typed, only a few hundred possible items will typically remain. However, I have no idea how to implement database access while the user types (without reloading the page, so that PHP code would be executed).
I do not use any content management system; I would prefer a pure HTML/PHP/JavaScript/jQuery/CSS solution that does not rely on bulky third-party libraries. Thanks for your suggestions!
you need to use php jquery and ajax
<form autocomplete="off" action="">
<div class="autocomplete" style="width:300px;">
<input id="myInput" type="text" name="myCountry" placeholder="Country">
<div id="myInputautocomplete-list" class="autocomplete-items">
//insert ajax response here
</div>
</div>
<input type="submit">
</form>
//css code
* { box-sizing: border-box; }
body {
font: 16px Arial;
}
.autocomplete {
/*the container must be positioned relative:*/
position: relative;
display: inline-block;
}
input {
border: 1px solid transparent;
background-color: #f1f1f1;
padding: 10px;
font-size: 16px;
}
input[type=text] {
background-color: #f1f1f1;
width: 100%;
}
input[type=submit] {
background-color: DodgerBlue;
color: #fff;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
/*when hovering an item:*/
background-color: #e9e9e9;
}
.autocomplete-active {
/*when navigating through the items using the arrow keys:*/
background-color: DodgerBlue !important;
color: #ffffff;
}
<script>
window.addEventListener('load',function(){
jQuery(document).ready(function($) {
$("#myInput").keypress(function() {
var inputData = $("#myInput").text('');
if(inputData.length > 2) {
$.ajax({
url : "/ajax.php",
type : "POST",
data : {'myInput': $(this).val()},
dataType: 'json',
success: function (response) {
//after ajax call here you get the data
alert(response.data);
// user below divs to iterated data
/*
<div><strong>D</strong>enmark
<input type="hidden" value="Denmark"></div>
<div><strong>D</strong>jibouti
<input type="hidden" value="Djibouti"></div> */
});
}
});
});
});
</script>
Now in ajax.php file
$inputData = $_POST[myInput];
// make sql connection or include connection file
// after connection write query to get data
//suppose table name items
$query = "select * from tableName where itemName like $inputData%";
$res = mysql_query($query);
$data = mysql_fetch_data($res);
$result = json_encode("code":200,"data":$data)
return $result;

onSubmit Adding a Second Javascript Action After Form Validation

I have a form that uses very basic input validation using javascript onSubmit before the server side processing begins in PHP.
However, due to the time the PHP script takes to process (uploading images etc) I am trying to use the same onSubmit function to display a "please wait" notice if it passes validation. Or is there a better way? I tried in PHP, but the processing has to complete before I can echo any output. Anything I have tried from other SO posts stops the validation process.
<form id="form" method="post" action="" onsubmit="return Validate(this)" autocomplete="off">
Current Javascript Example
function Validate(myForm) {
var error = '';
// Example Filed
if(myForm.name.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
return false;
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
return true;
}
}
CSS & HTML Waiting Notice (Initially Hidden)
<style>
#processing {
display:block;
position: fixed;
top: 0;
left: 0;
background: rgba(255,255,255,0.8);
width: 100%;
height: 100%;
}
#popup {
width: 300px;
min-height: 160px;
padding:20px;
background-color: #fff;
border: 5px solid #06C;
text-align: center;
color: #202020;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -100px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
}
#popup img {
height:60px;
width:60px;
}
</style>
<div id="processing">
<div id="popup">
<img width="60" height="60" src="../waiting.gif" />
<h3>Please Wait!</h3>
<p>The form is processing...</p>
</div>
</div>
Any help would be appreciated
All you need to do is have the "...Please Wait..." element already present in the document, but hidden and then show it when the submit takes place. You do this by applying a CSS class to the element in the HTML, which hides it initially and then remove that class when the form is valid.
A couple of side notes...
Don't use inline HTML event attributes (onsubmit, onclick, etc.). That is how events were registered 20 years ago and there are many drawbacks to using them. Unfortunately, because most people just copy what others have done, the use of this approach just will not die. Instead, follow modern standards and use .addEventListener().
Also, don't ever name an element or a variable name as name is a property of the Global window object and the use of that name can cause problems in the code.
// Get references to the DOM elements that your code will need
var frm = document.getElementById("form");
var wait = document.getElementById("processing");
var userName = document.getElementById("txtName");
frm.addEventListener("submit", validate); // Set up events the modern, standards-based way
// All event handlers will automatically be passed a reference
// to the event object for that event
function validate(evt) {
var error = '';
// Example Filed
if(userName.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
evt.preventDefault(); // Stop the event
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
wait.classList.remove("hidden"); // Remove the hidden class
}
}
#processing {
display:block;
position: fixed;
top: 0;
left: 0;
background: rgba(255,255,255,0.8);
width: 100%;
height: 100%;
}
#processing.hidden { display:none } /* This hides the message by default */
#popup {
width: 300px;
min-height: 160px;
padding:20px;
background-color: #fff;
border: 5px solid #06C;
text-align: center;
color: #202020;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -100px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
}
#popup img {
height:60px;
width:60px;
}
<form id="form" method="post" action="#" autocomplete="off">
<input type="text" id="txtName">
<input type="submit">
</form>
<div id="processing" class="hidden">
<div id="popup">
<img width="60" height="60" src="../waiting.gif" />
<h3>Please Wait!</h3>
<p>The form is processing...</p>
</div>
</div>
On your javascript validation, you could let the user know the image is loading by showing a simple message.
<div class="loading" style="display:none;">Loadin ...</div>
function Validate(myForm) {
var error = '';
// Example Filed
if(myForm.name.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
return false;
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
// show the user the image is loading
$('#form .loading').show();
return true;
}
}
After it loads you may remove the message once you get a response from the server.
$('#form .loading').hide();

Modal External Url improperly redirecting

I am trying to modally open an external url. This external location enables the user to input a payment. After the user has sucessfully paid, the user should be directed back to the site that I am working on. In order to accomplish this, I am currently styling an iframe as a modal window. When the user clicks the 'next' button, a form action posts the external url to my iframe. Then, the css creates a modal-like effect in order to prevent the user from clicking buttons on the previous screen until the payment is input. The external url requires a return url and a cancel url as input parameters. When the user is done with the website, they will click either submit or cancel and the external site will navigate the user to the appropriate location. The problem that I am having is when the user clicks cancel or submit on the external site, the modal window remains open and navigates to the new location. What I want to happen is for the modal window to close and for the user to be navigated to the necessary url in the main browser. Does anyone have an idea for how to accomplish this or a method of coding this that would avoid this problem? Thanks!
Code:
<style>
.modalDialog {
position: fixed;
font-family: Arial, Helvetica, sans-serif;
top: -60;
right: 0;
bottom: 0;
left: 0;
background: #EAC5C5;
z-index: 99999;
opacity:0;
-webkit-transition: opacity 400ms ease-in;
-moz-transition: opacity 400ms ease-in;
transition: opacity 400ms ease-in;
pointer-events: none;
}
.modalDialog:target {
opacity:1;
pointer-events: auto;
}
.modalDialog > div {
width: 850px;
height: 700px;
position: relative;
margin: 10% auto;
padding: 5px 20px 13px 20px;
background: #fff;
}
.close {
background: #606061;
color: #FFFFFF;
line-height: 25px;
position: absolute;
right: -12px;
text-align: center;
top: -10px;
width: 24px;
text-decoration: none;
font-weight: bold;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
-moz-box-shadow: 1px 1px 3px #000;
-webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000;
}
.close:hover { background: #00d9ff; }
</style>
<script type="text/javascript">
function openModal() {
window.location.assign("#openModal")
}
function cancelUrl() {
window.location.assign("#close")
}
</script>
<body>
<form action="https://hostedpage" target="my-iframe" method="post" id="testForm" runat="server">
<label for "Hidden4">Amount: </label>
<input type="text" name="Amount" id="Hidden4" value="" />
<input type="hidden" name="RURL" id="Hidden7" value="https://testurl.com" />
<input type="hidden" name="CURL" id="Hidden8" value="http://testurl2.aspx#close" />
<asp:Button ID="Submit" runat="server" Text="Next" UseSubmitBehavior="true" OnClientClick="openModal()" />
</form>
<div id="openModal" class="modalDialog" >
<div id="div1">
X
<iframe id="iframe" name="my-iframe" style="width: 850px; height: 700px;" frameborder="0" ></iframe>
</div>
</div>
</body>
So the code is more complicated than when I first asked this question, but the overall idea remains. So, I changed the RURL to be "testurl.com&type=submit" and the CURL to be "testurl2.aspx&type=cancel". I am using c# .net and in the Page_Load function, I am detecting if the type parameter exists. If it does, I change the iframe to a different view. This view has only two hidden buttons and a hidden string (I want to pass this info to the parent. The value is set in the Page_Load function).
<asp:View ID="newView" runat="server" >
<form id="frm" runat="server" style="display:none">
<asp:TextBox ID="Label25" runat="server" CssClass="NoDisplay" />
<input type="button" id="hiddenButton" onclick="parent.submit(this.form.Label25.value);" style="display:none" />
<input type="button" id="hiddenCancel" onclick="parent.cancel();" style="display:none" />
</form>
</asp:View>
Even though the iframe is a different view, it still goes through all the motions of loading the page. I capture the page load and determine if the type parameter is in the url. If it is, I click one of the buttons on the view. This triggers the parent functions that either submit or cancel the modal window. I know this seems a little roundabout, but it has to be because of the fact that the buttons the user is clicking to close the modal are on the hosted site. Also, doing this allows me to do more complicated things in the process, such as capture the response from the hosted site and throw it into our database.
<script type="text/javascript">
function testFunction() {
var urlParms = new Array();
urlParms = document.URL;.split("?");
if (typeof thisNVP[1] !== "undefined") {
var parmArray = urlParms[1].split("&");
var thisfrag = new Array();
for (i = 0; i < parmArray.length; i++) {
thisfrag = parmArray[i].split("=");
if (thisfrag[0] == "type") {
if(thisfrag[1] == "cancel") {
document.getElementById("hiddenCancel").click();
} else {
document.getElementById("hiddenButton").click();
}
}
}
}
}
</script>
<body onload="testFunction()">
</body>

Hitting 'Cancel' during file upload in Chrome clears value

I'm working with a simple html type="file" input, and I'm having an issue in Chrome. Specifically, when you browse to and choose a file, it saves the value. However, if you re-browse, then press cancel it will clear out the value.
The html is simple:
<input type="file">
Here is a simple fiddle- http://jsfiddle.net/78ghn/.
This doesn't happen in other browsers -- is there a way to force Chrome to retain the value??
function f()
{
document.getElementById("b").appendChild(document.getElementById("a"));
document.getElementById("d").innerHTML = document.getElementById("c").innerHTML
document.getElementById("alert").innerHTML = 'Your last file was '.concat(document.getElementById("b").lastChild.value.slice(12))
}
function g()
{
if(document.getElementById("b").lastChild.value)
{
document.write("You have submitted ".concat(document.getElementById("b").lastChild.value.slice(12)));
}
else
{
document.write("You have submitted nothing.");
}
}
#a
{
opacity: 0;
width: 100%;
height: 100%;
}
#c
{
display: none;
}
#d
{
width: 100%;
height: 100%;
}
#e
{
background-color: green;
border: 2px solid black;
color: white;
font-size: 16pt;
width: 180px;
height: 90px;
}
#f
{
position: relative;
left: 25%;
bottom: 70%;
}
<form>
<div id='e'>
<span id='d'>
<input type="file" onchange='f();' id='a'>
</span>
<span id='f'>Select File</span>
</div>
<input type='button' value='Submit' onclick='g();'>
</form>
<span id='alert'>You have chosen no files.</span>
<ul id='b'>
</ul>
<form id='c'>
<input type="file" onchange='f();' id='a'>
</form>
I was unable to find a native implementation for this, so I tried my own workaround. It takes input from a custom CSS button overlay, then adds the actual input element to a list and replaces it with an empty one. The value is read and displayed, as it would be with a normal input. It is not included, but submitting it would involve moving the original input (last element of ul with id='b') to a form and submitting it via JavaScript. It is not optimal, but it does work.

Categories