I have been trying to manage that the signature image gets submitted to upload to a folder and add to
the database at the same time but having a tough time. Everything is working except uploading the signature image to a folder and submitting it to the database with the same record.
I am using the digital signature from this jquery code : https://www.jqueryscript.net/mobile/Simpe-Mobile-Signature-Pad-with-jQuery-Html5-Canvas.html
Current example of what I have : http://dev.teqcube.com/signin-test/signin.php
This is for the 'New Visitor' Section
This is the form
<form method="post" action="">
<!-- VISITOR FIRST NAME -->
<div class="form-group">
<input type="text" class="form-control" name="visitor_first_name" id="visitor_first_name" placeholder="First Name" required>
</div>
<!-- VISITOR LAST NAME -->
<div class="form-group">
<input type="text" class="form-control" name="visitor_last_name" id="visitor_last_name" placeholder="Last Name" required>
</div>
<!-- VISITOR COMPANY NAME -->
<div class="form-group">
<input type="text" class="form-control" name="visitor_company_name" id="visitor_company_name" placeholder="Company Name" required>
</div>
<!-- VISITING PURPOSE -->
<div class="form-group">
<select class="custom-select form-control" name="visitor_visiting_purpose" id="visitor_visiting_purpose" style="width:100%;" required="required">
<option value="" selected>Visiting Purpose</option>
<option value="Visiting">Visiting</option>
<option value="Cleaning">Cleaning</option>
<option value="Delivery">Delivery</option>
<option value="Maintanance">Maintanance</option>
</select>
</div>
<!-- APARTMENT NUMBER -->
<div class="form-group">
<input type="text" class="form-control" name="visitor_visiting_apartment_number" id="visitor_visiting_apartment_number" placeholder="Apartment Number" required>
</div>
<!-- FORM SUBMIT FOR NEW REGISTRATION -->
<div class="submitBtnContainer">
<button type="button" data-toggle="modal" data-target="#digitalSignatureModal" class="btn my-2 my-sm-0 submitTakePhoto"><i class="fa fa-pencil" aria-hidden="true"></i>Signature</button>
<button type="submit" name="sign_visitor_in" class="btn btn-success my-2 my-sm-0 signoutVisitorFormOption1"><i class="fa fa-sign-in" aria-hidden="true"></i> Sign In</button>
</div>
<!-- #### MODAL TO APPLY DIGITAL SIGNATURE #### -->
<div class="modal fade" id="digitalSignatureModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<!-- MODAL BODY LOGO -->
<div class="col-md-12">
<div id="signinSuccessModalLogo">
<img src="img/Excellent-visitor-signin-small.png" alt="">
</div>
</div>
<!-- MODAL BODY CONTENT -->
<div class="col-md-12">
<div class="modal-body" id="signinSuccessModalContent">
<!-- DISPLAY IMAGE AFTER SIGNED -->
<div id="signaturePad" data-role="content"></div>
<!-- DIGITAL SIGNATURE SECTION -->
<div id="divPopUpSignContract">
<div class="ui-content popUpHeight">
<div id="div_signcontract">
<!-- CANVAS TO DRAW SIGNATURE -->
<canvas id="canvas">Canvas is not supported</canvas>
<!-- SUBMIT SIGNATURE OR CLEAR -->
<div class="col-md-12">
<!-- <input id="btnSubmitSign" type="button" class="btn btn-success" data-dismiss="modal" data-inline="true" data-mini="true" data-theme="b" value="Submit Signature" onclick="fun_submit()" style="border-radius: 5px; padding: 15px;" /> -->
<input id="btnSubmitSign" type="button" class="btn btn-success" data-inline="true" data-mini="true" data-theme="b" value="Submit Signature" onclick="fun_submit()" style="border-radius: 5px; padding: 15px;" />
<input id="btnClearSign" type="button" class="btn btn-warning commentbtn" data-inline="true" data-mini="true" data-theme="b" value="Clear" onclick="init_Sign_Canvas()" style="border-radius: 5px; padding: 15px;" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /MODAL BODY CONTENT -->
</div>
</div>
</div>
<!-- #### MODAL TO APPLY DIGITAL SIGNATURE #### -->
</form>
This is the php code to add the info to the database.
I am getting an error with $visitor_signature. I have tried different methods but not succeeding.
// ### SUBMIT SIGNIN FORM FOR NEW VISITOR REGISTRATION ###
if(isset($_POST['sign_visitor_in'])) {
date_default_timezone_set('Asia/Dubai');
$currentTime = date("H:i:s");
// *** RETREIVE SUBMITTED INFORMATION ON SUBMIT FOR NEW VISITOR REGISTRATION ***
$visitor_first_name = $_POST['visitor_first_name'];
$visitor_last_name = $_POST['visitor_last_name'];
$visitor_company_name = $_POST['visitor_company_name'];
$visitor_visiting_purpose = $_POST['visitor_visiting_purpose'];
$visitor_visiting_apartment_number = $_POST['visitor_visiting_apartment_number'];
//$visitor_visit_status = $_POST['visitor_visit_status'];
$visitor_signin_date = date("Y-m-d");
$visitor_signin_time = date("H:i:s");
$visitor_signout_date = date("H:i:s");
$visitor_signout_time = date("H:i:s");
$visitor_signature = $_FILES['visitor_signature']['name'];
$visitor_signature_tmp = $_FILES['visitor_signature']['tmp_name'];
move_uploaded_file($visitor_signature_tmp, "img/sign-in-signatures/$visitor_signature");
exit();
// *** I added exit() for testing purpose and once it works I remove it.
// *** ADD NEW VISITOR SIGNIN RECORD TO DATABASE ***
$query = "INSERT INTO visitors(visitor_first_name, visitor_last_name, visitor_company_name, visitor_visiting_purpose,
visitor_visiting_apartment_number, visitor_visit_status, visitor_signin_date, visitor_signin_time, visitor_signout_date, visitor_signout_time, visitor_signature)";
$query .= "VALUES('{$visitor_first_name}', '{$visitor_last_name}', '{$visitor_company_name}',
'{$visitor_visiting_purpose}', '{$visitor_visiting_apartment_number}', 'Signed In', '{$visitor_signin_date}', '{$visitor_signin_time}', '', '', '{$visitor_signature}')";
$result = mysqli_query($connection, $query);
// *** GENERAL CONFIM QUERY ***
if(!$result) {
die("QUERY FAILED. " . mysqli_error($connection));
}
}
The below code is part of the js file where the signature takes place
function fun_submit() {
if(isSign) {
var canvas = $("#canvas").get(0);
var imgData = canvas.toDataURL();
jQuery('#signaturePad').find('p').remove();
jQuery('#signaturePad').find('img').remove();
jQuery('#signaturePad').append(jQuery('<p>Your Signature:</p>'));
jQuery('#signaturePad').append($('<img/ name="visitor_signature">').attr('src',imgData));
// I BELIEVE THIS IS WHERE THE PROCESS HAPPENS TO UPLOAD THE IMAGE TO THE FOLDER
// I HAVE BEEN TRYING WITH DIFFERENT CODES IN THIS SECTION BUT NOT SUCCEEDING
closePopUp();
} else {
alert('Please sign');
}
}
Any help would be gladly appreciated.
Regards
I think that you should :
change your HTML code with adding a hidden field in your form, like this :
<input type=hidden name="visitor_signature" id="visitor_signature">
change your JS code in the fun_submit() function with adding : jQuery('#visitor_signature').val(imgData)
and finally change your PHP code from :
$visitor_signature = $_FILES['visitor_signature']['name'];
$visitor_signature_tmp = $_FILES['visitor_signature']['tmp_name'];
move_uploaded_file($visitor_signature_tmp, "img/sign-in-signatures/$visitor_signature");
to
$visitor_signature = $_POST['visitor_signature'];
// we receive something like : data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvcAAADICAYAAABszM7qAAAZc0lEQVR4Xu3da4hVVRsH8GVeS
// we remove the "data:image/png;base64,"
$visitor_signature = preg_replace('#^data:image/\w+;base64,#i', '', $visitor_signature);
$visitor_signature = base64_decode($visitor_signature);
file_put_contents("img/sign-in-signatures/visitor_signature.png",$visitor_signature);
as the signature image isn't anymore a uploaded file, but a base64 string put in the textfield "visitor_signature"
thank you so much for your time, I appreciate it.
I did as you pointed out to me and started getting an sql error : You have an error in your SQL syntax; check the manual that corresponds to your SQL server version for the right syntax to use near
I then had a look around and added base64_encode before it inserts into the db and then it worked. Without the base64_decode the image won't open in the folder but without the encode afterwards it doesn't upload to the db. Code looks like this now :
$visitor_signature = $_POST['visitor_signature'];
// we receive something like : data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvcAAADICAYAAABszM7qAAAZc0lEQVR4Xu3da4hVVRsH8GVeS
// we remove the "data:image/png;base64,"
$visitor_signature = preg_replace('#^data:image/\w+;base64,#i', '', $visitor_signature);
$visitor_signature = base64_decode($visitor_signature);
file_put_contents("img/sign-in-signatures/" . $visitor_first_name . "_" . $visitor_last_name . "_signature_" . $visitor_company_name . ".png",$visitor_signature);
$visitor_signature = base64_encode($visitor_signature);
Inside the db it still add a huge string but in the backend I am calling the image :
// VISITOR SIGNATURE IMAGE
echo "
<td style='text-align:center;'>
<img src='../img/sign-in-signatures/{$visitor_first_name}_{$visitor_last_name}_signature_{$visitor_company_name}.png' width='125px'>
</td>";
Once again thank you for your time, I hope you have a great upcoming 2019.
Regards
Related
I am not really good at the HTML world, and I'm not even sure how to debug this one. Anyway, I have an ASP.NET core App. My issue is in a CSHTML view. It is a timeclock system. User logs time against an existing job.
I have an Index.cshtml that is working. It will verify a JobNumber to make sure it exists in the database. And if the user enters a partial number and hits F3, it pops up a modal window (I'm using Bootstrap 5) to allow them to select from a list.
The problem is, the user wants to add more Job numbers. So, they can clock time against up to five Jobs at once. So, I am creating new fields, and naming them JobNumber2, JobNumber3, etc.
What I want to do is reuse the existing scripts to add the verification and popup functionality to each of the new fields.
I have tried several different things based on a half a dozen tutorials out there, but I am just not good enough at Javascript and JQuery to know how to do this.
Any help is appreciated!
[EDIT]
Ruikai Feng's answer shows how to match the first function, but that one calls validateJobNumber(jobNumber), and the result will update a field -- again based on the same pattern. So, now it updates: jobNumberValidationMessage -- but I need it to update the correct jobNumberValidationMessage depending on which JobNumber field got matched in the first half of this. IDK, maybe these could be combined into one function? I'm not sure. But how do I take what I matched with id^='JobNumber to figure out which jobNumberValidationMessage to update (ie jobNumberValidationMessage2, jobNumberValidationMessage3, etc) ;
------------ END EDIT
Here's the code I have that is working, but needs changed:
#using Microsoft.AspNetCore.Http
#using Microsoft.AspNetCore.Http.Extensions
#model dynamic
<!DOCTYPE html>
<html>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-10">
<!-- Clock-In Header -->
<h3>
<img class="logo large" src="logo-png-transparent.png")"
alt="Logo" width="100" height="100"> Add Job Number(s) to Track Time for: #Model.Employee.Name
</h3>
<hr /> <!-- Ruler Line for Separation -->
<!-- End Clock-In Header -->
<!-- Clock-In Form -->
<div class="row">
<div class="col-1 col-md-12 offset-md-0">
<div class="card">
<div class="card-body">
<form asp-action="ClockInBegin" method="post">
<label for="JobNumber" class="col-7 col-md-2 col-form-label text-md-right">Job Number</label>
<div class="col-md-4">
<input type="text" id="JobNumber" name="JobNumber" class="form-control" onkeydown="jobNumberKeyDown(this)" onblur="jobNumberBlur(this)" value="#Model.TrackingItem.JobNumber">
<div class="col-md-8">
<span id="jobNumberValidationMessage"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="form-check form-switch col-4 align-with-label">
<input class="form-check-input" type="checkbox" value="" id="MultipleCheck">
<label class="form-check-label" for="MultipleCheck">Multiple</label>
</div>
</div> <!-- End form-group row -->
<div>
<button type="submit" class="btn btn-primary w-100">Start Clock</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Clock-In Modal Pop-up -->
<div class="modal fade" id="myModal">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Select Job Number</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<select id="jobNumberSelect" class="form-control">
<option value="">Select Job Number</option>
<!-- Dynamic options generated via JavaScript or ajax -->
</select>
</div>
<div class="modal-footer">
<button type="button" id="CANCEL"class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" id="OK" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
</div>
</div>
</div>
<!-- End Clock-In Modal Pop-up -->
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$("#JobNumber").blur(function () {
var jobNumber = $(this).val();
validateJobNumber(jobNumber);
});
$("#JobNumber").keydown(function (event) {
if (event.key === "F3") {
event.preventDefault();
if (event.target.value.length >= 2) {
// Open the modal
$('#myModal').modal('show');
// Populate the select options
$.ajax({
type: "GET",
url: "#Url.Action("GetJobNumbers")",
data: { searchTerm: event.target.value },
dataType: "json",
success: function (data) {
$("#jobNumberSelect").empty();
$.each(data, function (index, item) {
$("#jobNumberSelect").append("<option value='" + item + "'>" + item + "</option>");
});
$("#jobNumberSelect").val("..."); // clear the initial value. Make them select it
//set prompt in first cell of select
$("#jobNumberSelect").prepend("<option value=''>Select Job Number</option>");
$("#myModal").modal("show");
}
});
}
}
});
$("#jobNumberSelect").change(function () {
$("#JobNumber").val($(this).val());
});
$("#OK").click(function () {
$("#JobNumber").val($("#jobNumberSelect").val());
validateJobNumber(); // call the validation
$("#myModal").modal("hide");
});
$('#MultipleCheck').change(function () {
if (this.checked) {
$(this).val(true);
$('[name="MultipleCheck"]:hidden').val(true);
$("#hiddenFields").show();
}
else {
$(this).val(false);
$("#hiddenFields").hide();
}
})
}); // end Document.Ready functions
function validateJobNumber() {
var jobNumber = $("#JobNumber").val();
$.ajax({
type: "POST",
url: "#Url.Action("VerifyJobNumber")",
data: { jobNumber: jobNumber },
dataType: "text",
success: function (respdata) {
// alert(respdata);
const obj = JSON.parse(respdata);
var rmessage = obj.message;
$("#jobNumberValidationMessage").text(rmessage);
$("#jobNumberValidationMessage").css("color", "green");
}
});
}
</script>
</body>
</html>
if you have mutipule inputs like:
<input type="text" id="JobNumber1" name="JobNumber1" class="form-control" value="1">
<input type="text" id="JobNumber2" name="JobNumber2" class="form-control" value="2">
<input type="text" id="JobNumber3" name="JobNumber3" class="form-control" value="3">
and you want validate the value on blur ,just try as below:
$("[id^='JobNumber']").blur(function(e)
{
var jobnumber=$(this).val();
$.ajax({
type: "POST",
url: "#Url.Action("VerifyJobNumber")",
data: { "jobNumber": jobnumber },
dataType: "text",
success: function (respdata) {
alert(respdata);
}
});
});
With a controller :
[HttpPost]
public IActionResult VerifyJobNumber(string jobNumber)
{
return Ok(jobNumber);
}
The result:
I found setting the title a bit awkward, it's complicated to exaplain in 1 sentence.. Some of our pages use popups where the user can fill in fields and then send. This is based on some Kallyas stuff and works fine with just text fields. After submitting, user staus on the same page, the form stays open and in it the message appears that the form has been sent (or not). There is also recaptcha handling in it.
Now I need to give the possibility to upload a file and this is where I am stuck. There is a .js file that does the handling. It picks up the form and does a ajax submit. I can see the form field of my input type="file" here, but with a fakepath/empty. If, in this javascript I try to append the file to the form I can submit, but the the backend says the form field is not there.
First, let me share the code.
The form :
<!-- Application form pop-up element content -->
<div id="application_panel" class="mfp-hide contact-popup">
<div class="contact-popup-panel">
<div class="container-fluid">
<div class="row">
<div class="col-md-12 col-sm-12">
<!-- Application form pop-up element -->
<div class="applicationForm pop-up-form" style="padding:50px;">
<!-- Title -->
<div id="jatitlewrapper">
<h3 class="m_title m_title_ext text-custom contact-popup-title c_title">
Some title
</h3>
<h4 class="tbk__subtitle fw-thin dark">
</h4>
</div>
<form id="appform" action="#request.projectname#/scripts/ajax/save/processform.cfm" method="post" class="contact_form row mt-40" enctype="multipart/form-data">
<div id="jafldwrapper">
<div class="col-sm-6 kl-fancy-form">
<input type="text" name="firstname" id="cf_firstname-pop-up" class="form-control" placeholder="Vul hier je voornaam in" value="" tabindex="1" required>
<label class="control-label">
VOORNAAM
</label>
</div>
<div class="col-sm-6 kl-fancy-form">
<input type="text" name="lastname" id="cf_lastname-pop-up" class="form-control" placeholder="Type je achternaam in" value="" tabindex="1" required>
<label class="control-label">
ACHTERNAAM
</label>
</div>
<div class="col-sm-12 kl-fancy-form">
<input type="text" name="place" id="cf_place-pop-up" class="form-control" placeholder="Voeg een onderwerp toe" value="" tabindex="1" required maxlength="78">
<label class="control-label">
WOONPLAATS
</label>
</div>
<div class="col-sm-12">
<label class="label_upl">
UPLOAD FILE
</label>
<input id="resume" style="padding-bottom:15px;" type="file" name="resume" id="cf_subject-pop-up" class="" placeholder="" value="" tabindex="1">
</div>
<cfif Application.isProductionURL>
<div class="col-sm-12" style="margin-left:15px;">
<div class="g-recaptcha" data-sitekey="somesitekey"></div>
</div>
<div class="col-sm-6">
<!-- Contact form send button -->
<button id="submitbtn" class="btn btn-fullcolor" type="submit" onClick="$('.g-recaptcha-response').attr('name','g_recaptcha_response');">
Send
</button>
</div>
<cfelse>
<div class="col-sm-6">
<!-- Contact form send button -->
<button id="submitbtn" class="btn btn-fullcolor" type="submit">
Send
</button>
</div>
</cfif>
<div class="col-sm-6" style="text-align:right;">
<button class="btn btn-fullcolor" type="button" onClick="closePopup();">
Cancel
</button>
</div>
</div>
<input type="hidden" name="fjobuuid" id="fjobuuid" value="">
</form>
</div>
<!--/ Application form pop-up element -->
</div>
<!--/ col-md-12 col-sm-12 -->
</div>
<!--/ .row -->
</div>
<!--/ .container -->
</div>
<!--/ .contact-popup-panel -->
<button title="Sluiten (Esc)" type="button" class="mfp-close">×</button>
</div>
<!--/ Application form pop-up element content -->
Some javascript for the popup to show :
window.onload = function() {
$('.abutton').magnificPopup({
closeBtnInside: true,
type: 'inline',
preloader: false
});
}
The standard js that handles the sumbit and works with all text fields on the form :
if(typeof($('.applicationForm form, .applicationForm.pop-up-form form, .contact_form form')) != 'undefined') {
$.each($('.applicationForm form, .applicationForm.pop-up-form form, .contact_form form'), function(index, el) {
var cform = $(el),
cResponse = $('<div class="cf_response col-sm-12"></div>');
cform.prepend(cResponse);
cform.h5Validate();
cform.submit(function(e) {
$('#g-recaptcha-response').attr('name','g_recaptcha_response');
e.preventDefault();
if(cform.h5Validate('allValid')) {
cResponse.hide();
$.post(
$(this).attr('action'),
cform.serialize(),
function(data){
console.log(data);
cResponse.html(data).fadeIn('fast');
if(data.match('success') != null) {
cform.get(0).reset();
}
}
); // end post
}
return false;
});
});
}
The backend does some handling of the fields and then produces a message, which is then visible in the popup :
<cfoutput><div class="alert alert-success alert-dismissible" role="alert"><p>Message sent, thank you</p></div></cfoutput>
or a message with class alert-danger if something went wrong.
Now I tried adding the file field 'resume' to the form by adding a cform.append, right after the cform.submit :
var files = $("#resume")[0].files;
for (var i = 0; i < files.length; i++) {
cform.append(files[i].name, files[i]);
}
It does loop and seems to append the file.
But the backend says form.resume is not there.
I tried writing my own submit :
$("#submitbtn").on("click", function(e) {
var form = $("#appform");
var params = form.serializeArray();
var files = $("#resume")[0].files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
formData.append(files[i].name, files[i]);
}
$(params).each(function (index, element) {
formData.append(element.name, element.value);
});
$.ajax({
type: "POST",
url: $(form).prop("action"),
data: formData,
processData: false,
error : function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);}
,
success : function(data){
console.log(data);
}
});
})
Then the backend has all fields needed, including the actual file. But then I don't know how to integrate staying on the same url with the popup still in place and the message from the backend in the right place.
Then I tried changing the button type from sumbit to button, but then it won't let me send the file with the ajax call.
$.ajax({
type: "POST",
url: 'proctname//scripts/ajax/save/processform.cfm',
data: formData,
processData: false,
contentType: false,
error : function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);}
,
success : function(data){
var obj = $.parseJSON( data );
console.log(data);
}
});
Giving form field 'resume' is undefined. Apparently it needs to be a form submit.
Can I add the file field 'resume' to the standard code after the cform.submit, keep page and popup open, have the message handling etetc and if so, how?
I have built a login form using below code.
I am using a CGI version CGIDEV2 native to IBMi series. I am Validating the userid and password in the flower.cgi program. If the userid and password are validated, I am loading another html file to show a table. This works flawlessly.
If the userid and password are wrong, I am returning out of the program without writing anything. This results in a 500 Internal server error.
I want to capture this 500 Internal server error using javascript. I have tried using ajax but was not successful as I have limited understanding of javascript.
What could be the best way to achieve this?
<form method="POST" action="/nature/flower.cgi">
<!-- Username input -->
<div class="form-outline mb-4">
<input type="text" name="userid" id="form3Example3" class="form-control form-control-lg" style="text-transform:uppercase" placeholder="Enter a valid IBMi UserID" />
<label class="form-label" for="form3Example3">IBMi UserID</label>
</div>
<!-- Password input -->
<div class="form-outline mb-3">
<input type="password" name="passwd" id="form3Example4" class="form-control form-control-lg" placeholder="Enter password" />
<label class="form-label" for="form3Example4">Password</label>
<br>
</div>
<div class="d-flex justify-content-between align-items-center">
<!-- Checkbox -->
<div class="form-check mb-0">
<input class="form-check-input me-2" type="checkbox" value="" id="form2Example3" />
<label class="form-check-label" for="form2Example3">Remember me</label>
</div>
Forgot password?
</div>
<div class="text-center text-lg-start mt-4 pt-2">
<button type="submit" class="btn btn-primary btn-lg" style="padding-left: 2.5rem; padding-right: 2.5rem;">Login</button>
</div>
</form>
You can't capture an error from a URL the browser is navigating to.
The only way you could would be if you replaced the normal form submission with Ajax (in which the request is made and the response processed with JavaScript).
Generally speaking, if you were going to do that you would also want to rewrite the CGI program so it output structured data (e.g. as JSON) instead of semantic data (HTML).
It would not be a particularly small undertaking. You said you had tried it, which probably gives you some idea of the scope of it (i.e. far outside the scope of a Stackoverflow question).
A more sensible approach would almost certainly be to track down the cause of the 500 error and change the CGI program so it would capture it itself.
yes, the fetch api in javascript can post form data to your CGI program and check for the 500 response code. Then the web page can either display an error message or run the form.submit() method to actually submit the form up to the server.
Here is PHP and javascript code that simulates the whole thing. Should work similar with CGI. The key is you change the form submit button from type 'submit' to type 'button'. That way, clicking the submit button can run javascript code instead of the form being submitted to the server.
<?php
// site/tester/php/submit-form.php
header("Content-type: text/html; charset:utf-8;");
?>
<?php
$userid = isset($_POST["userid"]) ? $_POST["userid"]: '' ;
$passwd = isset($_POST["passwd"]) ? $_POST["passwd"]: '' ;
$remember = isset($_POST["remember"]) ? $_POST["remember"]: 'off' ;
if ( strtolower($userid) == 'alex')
{
http_response_code( 500 );
echo "$userid - invalid user name";
exit ;
}
?>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row mt-3">
<div class="col-auto">
<h1>submit form demo</h1>
</div>
</div>
</div>
<div class="container">
<div class="row mt-3">
<div class="col-4">
<form method="POST" id="main-form" action="./index.php">
<!-- Username input -->
<div class="form-outline mb-4">
<input type="text" name="userid" id="userid"
class="form-control form-control-lg"
value="<?= $userid ?>"
style="text-transform:uppercase" placeholder="Enter a valid IBMi UserID" />
<label class="form-label" for="userid">IBMi UserID</label>
</div>
<!-- Password input -->
<div class="form-outline mb-3">
<input type="password" name="passwd" id="passwd" class="form-control form-control-lg"
placeholder="Enter password" />
<label class="form-label" for="passwd">Password</label>
<br>
</div>
<div class="d-flex justify-content-between align-items-center">
<!-- Checkbox -->
<div class="form-check mb-0">
<input class="form-check-input me-2" type="checkbox"
<?= ($remember == 'on' ? 'checked' : '' ) ?>
name="remember" id="form2Example3" />
<label class="form-check-label" for="form2Example3">Remember me</label>
</div>
Forgot password?
</div>
<div class="text-center text-lg-start mt-4 pt-2">
<button id="login-button" type="button" class="btn btn-primary btn-lg"
style="padding-left: 2.5rem; padding-right: 2.5rem;">
Login</button>
</div>
</form>
</div>
</div>
<div id="login-errmsg-collapse" class="collapse row mt-3">
<div class="alert alert-warning" role="alert">
<p id="login-errmsg">Invalid login. User name does not exist.</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-3">
<div class="col-auto">
<p>userid: <?= $userid ?></p>
<p>passwd: <?= $passwd ?></p>
<p>remember: <?= $remember ?></p>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="./app.js"></script>
</body>
// ./submit-form/app.js
// enable the submit button click handler.
{
const elem = document.getElementById('login-button');
elem.addEventListener('click', event =>
{
login_click();
});
}
// -------------------------------- login_errmsg_show ---------------------
function login_errmsg_show( respText )
{
// show the response message in the bootstrap collapse alert box.
{
const elem = document.getElementById('login-errmsg') ;
elem.textContent = respText ;
}
const myCollapse = document.getElementById('login-errmsg-collapse')
const bsCollapse = new bootstrap.Collapse(myCollapse, {
toggle: false
});
bsCollapse.show( ) ;
}
// -------------------------------- login_click -------------------
async function login_click()
{
const elem = document.getElementById('main-form');
if (elem)
{
const {respText, status} = await webpage_post( ) ;
if ( status != '500')
{
elem.submit();
}
else
{
login_errmsg_show( respText ) ;
}
}
}
// --------------------------------- webpage_post -----------------------
async function webpage_post( )
{
const userid = document.getElementById('userid').value ;
const passwd = document.getElementById('passwd').value ;
const remember = 'on' ;
const url = "./index.php";
const params = { userid, passwd, remember } ;
const query = object_toQueryString(params);
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: query
});
const respText = await response.text();
const status = response.status ;
console.log( respText ) ;
return {respText, status} ;
}
// ------------------------- object_toQueryString ------------------------
function object_toQueryString(obj)
{
const qs = Object.keys(obj)
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
.join('&');
return qs;
}
I'm trying to pass form values, check them and then return the response with jquery, everything gets passed correctly, the image gets uploaded and the path gets added to the database, but instead of returning the message on the same page, it redirects to the addmember.php, doesn't even go through the checks - like the javascript file doesn't even exist and it has been bothering me for quite a while... I've tried searching but I didn't find anything relatable to me since the problem lies in the picture/image...
Uncaught TypeError: Cannot read property 'val' of null
addmember.js and the **form
$(document).ready(function() {
$("#submit").click(function() {
var membershipnumber = $("#membershipnumber").val();
var membername = $("#membername").val();
var membersurname = $("#membersurname").val();
var memberdate = $("#memberdate").val();
var memberphonenumber = $("#memberphonenumber").val();
var memberemail = $("#memberemail").val();
var memberpicture = document.getElementById("#memberpicture").val();
if ((membershipnumber == "") || (membername == "") || (membersurname == "") || (memberdate == "") || (memberphonenumber == "")) {
$("#message").html("<div class=\"alert alert-danger alert-dismissable fade in\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>Polja označena sa * ne smeju biti prazna.</div>");
} else {
$.ajax({
type: "POST",
url: "addmember.php",
data: {
"membershipnumber": membershipnumber,
"membername": membername,
"membersurname": membersurname,
"memberdate": memberdate,
"memberphonenumber": memberphonenumber,
"memberemail": memberemail,
"memberpicture": memberpicture
},
success: function(html) {
var text = $(html).text();
var response = text.substr(text.length - 4);
$("#message").html(html);
},
error: function() {
},
beforeSend: function() {
$("#message").html("<p class='text-center'><img src='images/ajax-loader.gif'></p>")
}
});
}
return false;
});
});
<form name="createnewmember" id="createnewmember" method="post" action="addmember.php" class="form-horizontal" enctype="multipart/form-data">
<div class="form-group">
<!-- name and surname -->
<label for="membername" class="col-xs-2 control-label">Ime i prezime:<font color="#d9534f">*</font></label>
<div class="col-xs-10">
<div class="form-inline">
<input name="membername" id="membername" type="text" class="form-control" placeholder="Ime" autofocus />
<input name="membersurname" id="membersurname" type="text" class="form-control" placeholder="Prezime" />
</div>
</div>
</div>
<!-- /name and surname -->
<div class="form-group">
<!-- date of birth -->
<label for="memberdate" class="col-xs-2 control-label">Datum rođenja:<font color="#d9534f">*</font></label>
<div class="col-xs-3">
<input name="memberdate" id="memberdate" type="date" class="form-control" value="1990-01-01" />
</div>
</div>
<!-- /date of birth -->
<div class="form-group">
<!-- membership number (scanned with barcode scanner) -->
<label for="membershipnumber" class="col-xs-2 control-label">Članski broj:<font color="#d9534f">*</font></label>
<div class="col-xs-3">
<input name="membershipnumber" id="membershipnumber" type="text" class="form-control" placeholder="Članski broj" data-toggle="tooltip" data-placement="right" title="Očitajte bar-kod sa nekorišćene kartice." />
</div>
</div>
<!-- /membmership number -->
<div class="form-group">
<!-- phone number -->
<label for="memberphonenumber" class="col-xs-2 control-label">Broj telefona:<font color="#d9534f">*</font></label>
<div class="col-xs-3">
<input name="memberphonenumber" id="memberphonenumber" type="text" class="form-control" placeholder="Broj telefona" />
</div>
</div>
<!-- /phone number -->
<div class="form-group">
<!-- email -->
<label for="memberemail" class="col-xs-2 control-label">Email adresa:</label>
<div class="col-xs-3">
<input name="memberemail" id="memberemail" type="text" class="form-control" placeholder="Email adresa" />
<div class="checkbox">
<label><input name="memberemailinglist" id="memberemailinglist" type="checkbox" disabled/> Prijavi na mailing listu?</label>
</div>
</div>
</div>
<!-- /email -->
<div class="form-group">
<!-- picture -->
<label for="memberpicture" class="col-xs-2 control-label">Slika:</label>
<div class="col-xs-10">
<label class="btn btn-default" for="memberpicture">
<input id="memberpicture" name="memberpicture" type="file" style="display:none;" onchange="$('#memberpicture-info').html($(this).val());" accept=".jpg,.png,.jpeg" class="form-control" />
<span class="glyphicon glyphicon-camera"></span> Traži...
</label>
<span class="label label-danger" id="memberpicture-info">Nije izabrana ni jedna slika...</span>
</div>
</div>
<!-- /picture -->
<div class="form-group">
<span class="pull-right">Polja označena sa <font color="#d9534f">*</font> su obavezna!  </span>
<!-- required fields text -->
</div>
<button name="Submit" id="submit" class="btn btn-default pull-right" type="submit">Podnesi</button>
<!-- submit button -->
</form>
<!-- /form -->
addmember.php
<?php
require 'includes/functions.php';
include_once 'config.php';
$membershipnumber = $_POST['membershipnumber'];
$membername = $_POST['membername']." ".$_POST['membersurname'];
$membersurname = $_POST['membersurname'];
$memberdate = $_POST['memberdate'];
$memberphonenumber = $_POST['memberphonenumber'];
$memberemail = $_POST['memberemail'];
$memberpicture_dir = '/images/members';
if(isset($_FILES['memberpicture'])) {
$memberpicture_temp = $_FILES['memberpicture']['tmp_name'];
$ext = pathinfo(basename($_FILES['memberpicture']['name']), PATHINFO_EXTENSION);
$memberpicture = $membershipnumber.".".$ext;
move_uploaded_file($memberpicture_temp , $_SERVER['DOCUMENT_ROOT'] . '/spartangym/images/members/' . $memberpicture);
} else {
$memberpicture = "nopicture.jpg";
}
$regdate = new DateTime();
$memberregdate = $regdate->getTimestamp();
$memberexpires = $memberregdate + 2592000;
if (strlen($memberemail) > 0 && !filter_var($memberemail, FILTER_VALIDATE_EMAIL) == true) {
echo '<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>Email adresa nije validna.</div><div id="returnVal" style="display:none;">false</div>';
} else {
$a = new AddMemberForm;
$response = $a->createMember($membershipnumber, $membername, $memberdate, $memberphonenumber, $memberemail, $memberpicture, $memberregdate, $memberexpires);
if ($response == 'true') {
echo '<div class="alert alert-success"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>Član '. $membername .' je uspešno dodat u bazu.</div><div id="returnVal" style="display:none;">true</div>';
} else {
mySqlErrors($response);
}
};
?>
Your problem is here
var memberpicture = document.getElementById("#memberpicture").val();
Native methods don't have val(), nor should you include the hash.
As val() is a jQuery method, you probably wanted to do
var memberpicture = $("#memberpicture").val();
The native alternative would be
var memberpicture = document.getElementById("memberpicture").value;
Your validation looks fine, but on-click you should use event.preventDefault() to keep the form from submitting and only allow the submission in the event of all fields being valid.
Usage here:
https://api.jquery.com/event.preventdefault/
at first check
before check
var membershipnumber = $("#membershipnumber").val();
after check
var membershipnumber='none object';
if(typeof($('#membershipnumber'))!="undefined")
{
membershipnumber= $('#membershipnumber').val();
}
alert(membershipnumber);
I'm trying to collect errors from js and send to email, but I'm not receving any email upon form submission. Here's my code:
<form id="vm-user-form" class="pure-form pure-form-aligned vm-user-form form-horizontal">
<div class="vm-modal-body">
<h4>Please provide us with these details.</h4>
<fieldset class="form-group">
<!-- <div class="pure-control-group"> -->
<label for="username">Name:</label>
<input id="vm-username" class="pure-input-1" name="username" type="text" placeholder="Your Names" pattern="[\w]{3,20}(\s)?[\w]{3,20}" title="eg. John Don" aria-required="true" required>
<!-- </div> -->
<!-- <div class="pure-control-group"> -->
<label for="phoneno">Phone Number:</label>
<input id="vm-phoneno" class="pure-input-1" name="phoneno" type="text" placeholder="Your Phone No." pattern="^(\+)?[\d]{6,14}$" title="eg. 0203001575, 023001575" aria-required="true" required>
<!-- </div> -->
<!-- <div class="pure-control-group"> -->
<label for="email">Email Address:</label>
<input id="vm-email" class="pure-input-1" name="emailaddress" type="email" placeholder="example-name#gmail.com" aria-required="true" required>
<!-- </div> -->
<!-- <div class="pure-controls">
<button type="submit" class="pure-button pure-button-primary">Submit</button>
</div> -->
</fieldset>
</div>
<div class="vm-modal-footer">
<!-- <div class="pure-controls"> -->
<button type="button" class="vm-close-form hide pure-button button-danger" data-dismiss="modal">Close</button>
<button type="submit" id="vm-submit-btn" class="pure-button button-vm">Submit</button>
<!-- </div> -->
<!-- <button type="button" class="btn btn-primary">Save changes</button> -->
</div>
</form>
Below is the Javascript code that is supposed to work with the Html code.
JavaScript:
var politeErrorResponse = function(reason) {
var waitToLoad = setTimeout(function() {
// Save the details for later use
status.reason = reason;
// Load up the form
$('.vm-popup-form').on('hidden.bs.modal', function(e) {
// do something...
// $('.vm-popup-form').modal('toggle');
// alert("previous modal hidden.");
$(".vm-close-form").show(300).addClass("hide").next().show(300);
});
$('.vm-popup').parent().load(chrome.extension.getURL('resources/view/form.html'), function() {
$('.vm-popup-form').modal('toggle')
$("#vm-user-form").on("submit", function(event) {
// prevent default form submit
event.preventDefault();
if ($('#vm-username').attr('value') != "" && $('#vm-phoneno').attr('value') != "" && $('#vm-email').attr('value') !== "") {
// reason carries the following:
// reason = ["caught", "isPostFunction", "responseText", "part_html"];
// On ERROR collect these DATA
var errorDetails = {
"username": $('#vm-username').attr('value'),
"phoneno": $('#vm-phoneno').attr('value'),
"emailaddress": $('#vm-email').attr('value')
}
// add this data to reason
$.extend(true, errorDetails, status.reason);
console.log(errorDetails);
$('.vitumob-popup-form .vm-modal-body').html(function() {
// Submit the details and error, and return Response
submitErrors(errorDetails, errorDetails.isPostFunction);
$(".vm-close-form").hide(300).removeClass("hide").next().fadeToggle().prev().show(300).on("click", function() {
// $('.vm-modal').modal("hide");
document.getElementById("vitumob-user-form").submit();
});
return '<h2> Your order has been submitted. We shall contact you. Thank you.</h2>'
})
} else {
// Focus on the 1st input
$('#vm-username').focus();
}
});
// alert("triggered the loading of the form");
});
}, 3000);
// Cancel the submission of the form
}
Please Help.