I am using Fine Uploader (v5.0.1) with jQuery, jQuery.validate and jQuery.form plugins for a multi-field form for new events which can have zero to two file attachments.
I have it working, but I have a few questions before I go further.
My client-side code is generating one POST request for each file (including the other form elements) plus one additional POST request for only the other form elements. So, if my form has two file attachments, I am getting three POST requests. Is this normal behavior? Can I get everything in one POST request?
If multiple POST requests is normal behavior, I will have to generate some sort of unique identifier at the client prior to the first POST request, so I can avoid duplication of event records in my database and to associate each file upload with the correct event. If this is the direction I need to go, are there any examples of this type of implementation I can look at?
If no files are attached, I am getting an alert dialog: "No files to upload." The form can be submitted with no file attachments, so I don't want to imply to the user that he/she must attach files. How can I get rid of this dialog?
I am currently getting one POST response for the form data plus one POST response for each file uploaded. Is there a way to handle only the final POST response (e.g., form.onAllComplete)? What if the form has no file attachments?
I am using one server endpoint for the form, including file uploads. Should I be using two separate endpoints, one for the other form fields and one for file uploads?
Here is my form: http://www.paulrachal.com/test/fineuploader-test.htm
Here is my code:
Client:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<title>New Event</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
<!-- Fine Uploader -->
<link rel="stylesheet" href="../css/custom.fineuploader-5.0.1.min.css" />
<script src="../js/custom.fineuploader-5.0.1.min.js"></script>
<!-- document.ready -->
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
<!-- event handlers -->
// hide the file upload button when the page loads
$( '#manual-fine-uploader' ).hide();
// show the file upload button on change in attachments checkbox
$("#hasattachments").change(function() {
if ($('#hasattachments:checked').length) {
$('#manual-fine-uploader').show();
}
else {
$('#manual-fine-uploader').hide();
}
})
<!-- Fine Uploader setup -->
var manualuploader = $('#manual-fine-uploader').fineUploader({
request: {
endpoint: 'fineuploader-test.php'
},
form: {
element: 'new-event'
},
template: "qq-template-manual-noedit",
validation: {
allowedExtensions: ['txt', 'pdf'],
itemLimit: 2,
sizeLimit: 256000 // 250 kB = 250 * 1024 bytes
},
autoUpload: false
});
<!-- form validation -->
// setup form validation on the form element
$("#new-event").validate({
// validation rules
rules: {
description: {
required: {
depends: function(element) {
if ( $("input[name='eventtype']:checked").val() == "3" || $("input[name='eventtype']:checked").val() == "4" || $("input[name='eventtype']:checked").val() == "5" )
return true;
}
}
},
},
// validation error messages
messages: {
description: "Please enter a description"
},
// submit handler
submitHandler: function(form) {
$("#send").attr("value", "Sending...");
$(form).ajaxSubmit({
target: "#response",
dataType: "json",
success: function processJson(response) {
if (response.success)
{
$(form).slideUp("fast");
$("#response").html("<span class='success'>" + response.success + "</span>").hide().slideDown("fast");
} // end if
else if (response.failure)
{
$("#response").empty();
$(".error").removeClass("error");
$errors = response.failure;
for ($i = 0; $i < $errors.length; $i++) {
$error = $errors[$i];
$.each($error, function(key, value) {
// append error text to div#response
$("#response").append("<li class='failure'>" + value + "</li>").hide();
// set form elements based on the error
switch(key) {
case "description-isempty":
$("#description").addClass("error");
break;
case "eventname-isempty":
$("#eventname").addClass("error");
break;
case "eventtype-isinvalid":
$("#eventtype-input").addClass("error");
break;
default:
// default statements if no cases are true
} // end switch
}); // end $.each
} // end for
$("#response").addClass("failure");
$("#response").slideDown("fast");
$("html, body").animate({ scrollTop: 0 }, "fast");
} // end else if
} // end processJson
});
return false;
}
}); // end #new-event.validate
<!-- validate individual fields on change -->
// #description
$('#description').on('change', function() {
$('#new-event').validate().element('#description');
});
}); // end document.ready
</script>
<!-- Fine Uploader Template -->
<script type="text/template" id="qq-template-manual-noedit">
<div class="qq-uploader-selector qq-uploader">
<div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
<span>Drop files here to upload</span>
</div>
<div class="qq-upload-button-selector qq-upload-button">
<div>Browse...</div>
</div>
<span class="qq-drop-processing-selector qq-drop-processing">
<span>Processing dropped files...</span>
<span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
</span>
<ul class="qq-upload-list-selector qq-upload-list">
<li>
<div class="qq-progress-bar-container-selector">
<div class="qq-progress-bar-selector qq-progress-bar"></div>
</div>
<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
<span class="qq-upload-file-selector qq-upload-file"></span>
<span class="qq-upload-size-selector qq-upload-size"></span>
<a class="qq-upload-cancel-selector qq-upload-cancel" href="#">Cancel</a>
<span class="qq-upload-status-text-selector qq-upload-status-text"></span>
</li>
</ul>
</div>
</script>
<!-- styles -->
<style type="text/css">
.qq-upload-button-selector {
background: #0080FF;
}
#response {
margin-bottom: 20px;
text-align: center;
}
#response .success {
color: #08a300;
}
#response .failure {
color: #dc0000;
}
div.failure {
background-color: #FF0;
}
.error {
border: 2px solid red;
}
input.error {
border: 2px solid red;
}
select.error {
border: 2px solid red;
}
</style>
</head>
<body>
<!-- new-event-form -->
<div id="new-event-form" data-role="page">
<!-- header -->
<div data-role="header"><h1>NEW EVENT</h1></div>
<div class="content" data-role="content">
<div id="response"></div>
<form id="new-event" action="fineuploader-test.php" method="post">
<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>Event Type:</legend>
<div id="eventtype-input">
<input type="radio" name="eventtype" id="eventtype_1" value="1" checked="checked" />
<label for="eventtype_1">Ride</label>
<input type="radio" name="eventtype" id="eventtype_2" value="2" />
<label for="eventtype_2">Clinic</label>
<input type="radio" name="eventtype" id="eventtype_3" value="3" />
<label for="eventtype_3">Social Event</label>
<input type="radio" name="eventtype" id="eventtype_4" value="4" />
<label for="eventtype_4">Meeting</label>
<input type="radio" name="eventtype" id="eventtype_5" value="5" />
<label for="eventtype_5">Non-Club Event</label>
</div>
</fieldset>
</div>
<div data-role="fieldcontain">
<label for="eventname">Event Name:</label>
<input type="text" name="eventname" id="eventname" value="" maxlength="40" required />
</div>
<div id="descriptioninput" data-role="fieldcontain">
<label for="description">Description:</label>
<input type="text" name="description" id="description" value="" maxlength="40" />
</div>
<div id="attachments" data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>Attachments:</legend>
<input type="checkbox" name="hasattachments" id="hasattachments" value="1" />
<label for="hasattachments">Attachments</label>
</fieldset>
</div>
<div id="manual-fine-uploader">Browse...</div>
<div class="ui-body ui-body-b">
<fieldset class="ui-grid-a">
<div class="ui-block-a"><input type="reset" data-theme="d" value="Cancel"></div>
<div class="ui-block-b"><input type="submit" data-theme="a" value="Submit"></div>
</fieldset>
</div>
</form>
</div> <!-- /content -->
</div> <!-- /page -->
</body>
</html>
Server:
<?php
// get values from POST request
$eventtype = $_POST['eventtype']; // eventtype field
$eventname = $_POST['eventname']; // eventname field
$description = $_POST['description']; // description field
$hasattachments = $_POST['hasattachments']; // hasattachments field
$qqfile = $_POST['qqfile']; // file upload field
$qquuid = $_POST['qquuid']; // file upload uuid
$qqfilename = $_POST['qqfilename']; // file upload filename
// include the upload handler class
require_once "handler.php";
// initialize errors array
$errors = array();
// validate elements
// eventtype
$eventtypes = array_flip(array('1', '2', '3', '4', '5'));
if (!isset($eventtypes[$eventtype])) $errors = addError("eventtype-isinvalid");
// eventname
$eventname = filter_var($eventname, FILTER_SANITIZE_STRING);
if(empty($eventname)) $errors = addError("eventname-isempty");
// description
$description = filter_var($description, FILTER_SANITIZE_STRING);
if (empty($description)) $errors = addError("description-isempty");
// file uploads
if ($hasattachments == 1) uploadFiles();
// functions
// add error
function addError($error) {
switch ($error)
{
case "description-isempty":
$errors[] = array("description-isempty" => "Please enter a description.");
break;
case "eventname-isempty":
$errors[] = array("eventname-isempty" => "Please enter an event name.");
break;
case "eventtype-isinvalid":
$errors[] = array("eventtype-isinvalid" => "Please select an event type.");
break;
} // end switch($error)
return $errors;
} // end function addError()
// file uploads
function uploadFiles() {
$uploader = new UploadHandler();
// specify the list of valid extensions
$uploader->allowedExtensions = array("txt", "pdf");
// specify max file size in bytes
$uploader->sizeLimit = 250 * 1024; // 250 kB
// specify the input name set in the javascript.
$uploader->inputName = "qqfile"; // matches Fine Uploader's default inputName value by default
// specify the folder to temporarily save parts to use the chunking/resume feature
$uploader->chunksFolder = "chunks";
$method = $_SERVER["REQUEST_METHOD"];
if ($method == "POST") {
header("Content-Type: text/plain");
// call handleUpload() with the name of the folder, relative to PHP's getcwd()
$result = $uploader->handleUpload("uploads/");
// get the name used for uploaded file
$result["uploadName"] = $uploader->getUploadName();
} // end if
} // end function uploadFiles()
// return response
if (!empty($errors)) $response = array("failure" => $errors);
else $response = array("success" => "Success! Your event has been posted.");
echo json_encode($response);
?>
Answering your questions in order:
Fine Uploader sends each file in a separate request, and there is no way to change this.
Fine Uploader already generates a unique ID (UUID) for each file. This ID is sent with the upload request. If you want to send additional data for a file, you can do so via the setParams API method. This will send additional, custom parameters of your choice along with the file. You can specify new params for all files, or a specific file.
In form mode, Fine Uploader intercepts the submit request and sends the file(s) and all form fields via ajax/XHR. Currently, it expects at least one file to be selected, as the form fields are sent as parameters for each selected file. A lack of selected files means that, in its current state, the form fields cannot be sent. Changing this will require adjustments to Fine Uploader's internal code. You can work around this by not utilizing form mode. Instead, you'll need to submit your form data in one request, and then have Fine Uploader send any selected files via the API.
Fine Uploader should intercept the form submit, so there should only be one response per file. The form fields are sent with each file.
This may be the required approach if you want to make the file field optional for your users.
Related
I have a form with file upload. I want to perform to two task: one is data submit to the database and upload file through ajax and after ajax successful another is going to form action.ajax are work properly but after ajax successful form action is not working
Kindly help
main.php
<!doctype html>
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">
function mycall() {
//disable the default form submission
event.preventDefault();
//grab all form data
var formData = new FormData(document.getElementById('data'));
$.ajax({
url: 'addToMySQL.php',
type: 'POST',
data: formData,
async: false,
cache: false,
contentType: false,
processData: false,
success: function (returndata) {
alert(returndata);
}
});
return false;
}
</script>
</head>
<body>
<form method='post' enctype="multipart/form-data" id="data" action="try.php" >
<div class="form-input">
<label for="exampleSelect1" class="col-md-3 control-label">Type of Paper</label>
<div class="col-md-9">
<select class="form-control" id="Otop" name="Otop" required>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
</div>
<div class="col-md-12">
<div class="form-input">
<label for="exampleSelect1" class="col-md-3 control-label">Paper upload</label>
<div class="col-md-9">
<input type="file" id="file" name="profileImg" >
</div>
</div>
</div>
<div class="form-input">
<div class="col-sm-12">
<input type="submit" class="btn btn-primary btn-lg btn-block" onclick="mycall()" name="OrderSubmit" value="Order">
</div>
</div>
</form>
</body>
</html>
addToMySQL.php
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include("dbconfig.php");
include('class/userClass.php');
$userClass = new userClass();
$Otop = $_POST['Otop'];
$Odiscipline = $_FILES['profileImg']['name'];
$target = "uploads/";
$fileTarget = $target.$Odiscipline;
$result = move_uploaded_file($_FILES['profileImg']['tmp_name'], "uploads/".$_FILES['profileImg']['name']);
$id = $userClass->userOrderInfo($Otop,$Odiscipline, $fileTarget);
if ($id) {
echo "done";
} else {
echo "Notdone";
}
userOrderInfo fuction in userClass.php
/* User Payment */
public function userOrderInfo($Otop, $Odiscipline, $fileTarget)
{
try {
$db = getDB();
$stmt = $db->prepare("INSERT INTO orderinfo(Otop, Odiscipline, fileTarget) VALUES (:Otop, :Odiscipline, :fileTarget)");
$stmt->bindParam("Odiscipline", $Odiscipline) ;
$stmt->bindParam("Otop", $Otop) ;
$stmt->bindParam("fileTarget", $fileTarget) ;
$stmt->execute();
$db = null;
return true;
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
Ok to get this clear in my head, what your code is doing is this:
The form is filled out and you click "submit" which prevents form
default action from being submitted. Instead this takes the form
data and submits it via ajax to addToMySQL.php
addToMySQL.php then handles the upload of the file and calls userOrderInfo() on userClass.php
userOrderInfo will return either a (string) or (boolean) true both of which PHP will treat as true for the purposes of an if() statement.
addToMySQL.php returns a response of (string) "done" to main.php
The ajax call main.php takes the response from addToMySQL.php and triggers a javascript alert with the content of "done".
Because of the way this has been written, the form will never use it's action property and instead will just constantly try to ajax the content of the form to addToMySQL.php because you are using event.preventDefault();.
Solution
A quick solution would be to either add a javascript redirect to the ajax success method, or add hidden <form> with the action you want to send your user to do and then populate and send it with javascript once the file has uploaded.
Whatever way you decide to do it, I would recommend fixing addToMySQL.phpso it won't constantly send back "done"!
I want to know how can I convert a normal php coded cc validator to a bulk.I have basic code with stipe merchant API working perfectly,but I want to make in bulk so I can check as many as possible help me out and tell me also how can I separate the not working and not working ccs in different boxes.
<?php
require 'path-to-Stripe.php';
if ($_POST) {
Stripe::setApiKey("YOUR-API-KEY");
$error = '';
$success = '';
try {
if (!isset($_POST['stripeToken']))
throw new Exception("The Stripe Token was not generated correctly");
Stripe_Charge::create(array("1" => 1000,
"currency" => "usd",
"card" => $_POST['stripeToken']));
$success = 'Your payment was successful.';
}
catch (Exception $e) {
$error = $e->getMessage();
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Stripe Getting Started Form</title>
<script type="text/javascript" src="https://js.stripe.com/v1/"></script>
<!-- jQuery is used only for this example; it isn't required to use Stripe -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
// this identifies your website in the createToken call below
Stripe.setPublishableKey('YOUR-PUBLISHABLE-API-KEY');
function stripeResponseHandler(status, response) {
if (response.error) {
// re-enable the submit button
$('.submit-button').removeAttr("disabled");
// show the errors on the form
$(".payment-errors").html(response.error.message);
} else {
var form$ = $("#payment-form");
// token contains id, last4, and card type
var token = response['id'];
// insert the token into the form so it gets submitted to the server
form$.append("<input type='hidden' name='stripeToken' value='" + token + "' />");
// and submit
form$.get(0).submit();
}
}
$(document).ready(function() {
$("#payment-form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('.submit-button').attr("disabled", "disabled");
// createToken returns immediately - the supplied callback submits the form if there are no errors
Stripe.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val()
}, stripeResponseHandler);
return false; // submit from callback
});
});
</script>
</head>
<body>
<h1>Charge $10 with Stripe</h1>
<!-- to display errors returned by createToken -->
<span class="payment-errors"><?= $error ?></span>
<span class="payment-success"><?= $success ?></span>
<form action="" method="POST" id="payment-form">
<div class="form-row">
<label>Card Number</label>
<input type="text" size="20" autocomplete="off" class="card-number" />
</div>
<div class="form-row">
<label>CVC</label>
<input type="text" size="4" autocomplete="off" class="card-cvc" />
</div>
<div class="form-row">
<label>Expiration (MM/YYYY)</label>
<input type="text" size="2" class="card-expiry-month"/>
<span> / </span>
<input type="text" size="4" class="card-expiry-year"/>
</div>
<button type="submit" class="submit-button">Submit Payment</button>
</form>
</body>
</html>
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
This is a jQuery Mobile question, but it also relates to pure jQuery.
How can I post form data without page transition to the page set into form action attribute. I am building phonegap application and I don't want to directly access server side page.
I have tried few examples but each time form forwards me to the destination php file.
Intro
This example was created using jQuery Mobile 1.2. If you want to see recent example then take a look at this article or this more complex one. You will find 2 working examples explained in great details. If you have more questions ask them in the article comments section.
Form submitting is a constant jQuery Mobile problem.
There are few ways this can be achieved. I will list few of them.
Example 1 :
This is the best possible solution in case you are using phonegap application and you don't want to directly access a server side php. This is an correct solution if you want to create an phonegap iOS app.
index.html
<!DOCTYPE html>
<html>
<head>
<title>jQM Complex Demo</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<style>
#login-button {
margin-top: 30px;
}
</style>
<script src="http://www.dragan-gaic.info/js/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="js/index.js"></script>
</head>
<body>
<div data-role="page" id="login" data-theme="b">
<div data-role="header" data-theme="a">
<h3>Login Page</h3>
</div>
<div data-role="content">
<form id="check-user" class="ui-body ui-body-a ui-corner-all" data-ajax="false">
<fieldset>
<div data-role="fieldcontain">
<label for="username">Enter your username:</label>
<input type="text" value="" name="username" id="username"/>
</div>
<div data-role="fieldcontain">
<label for="password">Enter your password:</label>
<input type="password" value="" name="password" id="password"/>
</div>
<input type="button" data-theme="b" name="submit" id="submit" value="Submit">
</fieldset>
</form>
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
</div>
</div>
<div data-role="page" id="second">
<div data-theme="a" data-role="header">
<h3></h3>
</div>
<div data-role="content">
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
<h3>Page footer</h3>
</div>
</div>
</body>
</html>
check.php :
<?php
//$action = $_REQUEST['action']; // We dont need action for this tutorial, but in a complex code you need a way to determine ajax action nature
//$formData = json_decode($_REQUEST['formData']); // Decode JSON object into readable PHP object
//$username = $formData->{'username'}; // Get username from object
//$password = $formData->{'password'}; // Get password from object
// Lets say everything is in order
echo "Username = ";
?>
index.js :
$(document).on('pagebeforeshow', '#login', function(){
$(document).on('click', '#submit', function() { // catch the form's submit event
if($('#username').val().length > 0 && $('#password').val().length > 0){
// Send data to server through ajax call
// action is functionality we want to call and outputJSON is our data
$.ajax({url: 'check.php',
data: {action : 'login', formData : $('#check-user').serialize()}, // Convert a form to a JSON string representation
type: 'post',
async: true,
beforeSend: function() {
// This callback function will trigger before data is sent
$.mobile.showPageLoadingMsg(true); // This will show ajax spinner
},
complete: function() {
// This callback function will trigger on data sent/received complete
$.mobile.hidePageLoadingMsg(); // This will hide ajax spinner
},
success: function (result) {
resultObject.formSubmitionResult = result;
$.mobile.changePage("#second");
},
error: function (request,error) {
// This callback function will trigger on unsuccessful action
alert('Network error has occurred please try again!');
}
});
} else {
alert('Please fill all nececery fields');
}
return false; // cancel original event to prevent form submitting
});
});
$(document).on('pagebeforeshow', '#second', function(){
$('#second [data-role="content"]').append('This is a result of form submition: ' + resultObject.formSubmitionResult);
});
var resultObject = {
formSubmitionResult : null
}
I have run into same issue where I am calling another .php page from my index.html.
The .php page was saving and retrieving data and drawing a piechart. However I found that when piechart drawing logic was added, the page will not load at all.
The culprit was the line that calls the .php page from my index.html:
<form action="store.php" method="post">
If I change this to:
<form action="store.php" method="post" data-ajax="false">
, it will work fine.
On using PHP and posting data
Use
data-ajax = "false" is the best option on <form> tag.
Problem is that JQuery Mobile uses ajax to submit the form. The simple solution to this is to disable the ajax and submit form as a normal form.
Simple solution: form action="" method="post" data-ajax="false"
I have a mobile website and everything is working fine except for the validation. Basically I'm looking to take values from the user and then process them on a separate page (process.php). However, before doing so I need to check to make sure the fields have been populated. I have looked at several ways to do this but none seem to be working. I have the below code at the moment. When I press the process button it brings me through to the process.php splash screen even though the item field is empty. It doesn't write to the database but I would rather it didn't bring the user to the process.php screen until all mandatory fields have been filled in. Any ideas?
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
<script>
$(document).ready(function(){
$("#formL").validate(); });
</script>
<div data-role="content">
<form id="formL" action="/website/process.php" method="post">
<div data-role="fieldcontain">
<label for="item">
<em>* </em> <b>Item:</b> </label>
<input type="text" id="item" name="item" class="required" />
</div>
<div class="ui-body ui-body-b">
<button class="buttonL" type="submit" data-theme="a">Process</button>
</div>
</form>
</div>
For a small form like that, I wouldn't bother using a plugin - is it even compatible with jQuery Mobile? Anyway, to get you started, here's a simple way to prevent submission when there are empty fields:
$("#formL").submit(function() {
// get a collection of all empty fields
var emptyFields = $(":input.required").filter(function() {
// $.trim to prevent whitespace-only values being counted as 'filled'
return !$.trim(this.value).length;
});
// if there are one or more empty fields
if(emptyFields.length) {
// do stuff; return false prevents submission
emptyFields.css("border", "1px solid red");
alert("You must fill all fields!");
return false;
}
});
You can try it/mess with it here.
I have ran across the same problem you have, I have my form validating correctly now.
The following is what I have done with Jquery Mobile -->
<link rel="stylesheet" href="css/jquery.mobile-1.0a4.1.css" />
<link rel="stylesheet" href="css/colors.css">
<link rel="stylesheet" href="css/list.css">
<!--For Icon to bookmark on phones-->
<link rel="apple-touch-icon-precomposed" href=""/>
<script>
var hdrMainvar = null;
var contentMainVar = null;
var ftrMainVar = null;
var contentTransitionVar = null;
var stateLabelVar = null;
var whatLabelVar = null;
var stateVar = null;
var whatVar = null;
var form1var = null;
var confirmationVar = null;
var contentDialogVar = null;
var hdrConfirmationVar = null;
var contentConfirmationVar = null;
var ftrConfirmationVar = null;
var inputMapVar = null;
// Constants
var MISSING = "missing";
var EMPTY = "";
var NO_STATE = "ZZ";
</script>
<div data-role="header" id="hdrMain" name="hdrMain" data-nobackbtn="true">
</div>
<div data-role="content" id="logo" align="center">
<img src="img/sam_mobile.png">
</div>
<div data-role="content" id="contentMain" name="contentMain">
<form id="form1">
<div id="userDiv" data-role="fieldcontain">
<label for="userName">User Name*</label>
<input id="userName" name="userName_r" type="text" />
</div>
<div id="passwordDiv" data-role="fieldcontain">
<label for="password" id="passwordLabel" name="passwordLabel">Password*</label>
<input id="password" name="password_r" type="password" />
</div>
<div id="submitDiv" data-role="fieldcontain">
<input type="submit" value="Login" data-inline="true"/>
</div>
</form>
</div><!-- contentMain -->
<div data-role="footer" id="ftrMain" name="ftrMain"></div>
<div align="CENTER" data-role="content" id="contentDialog" name="contentDialog">
<div>You must fill in both a user name and password to be granted access.</div>
<a id="buttonOK" name="buttonOK" href="#page1" data-role="button" data-inline="true">OK</a>
</div> <!-- contentDialog -->
<!-- contentTransition is displayed after the form is submitted until a response is received back. -->
<div data-role="content" id="contentTransition" name="contentTransition">
<div align="CENTER"><h4>Login information has been sent. Please wait.</h4></div>
<div align="CENTER"><img id="spin" name="spin" src="img/wait.gif"/></div>
</div> <!-- contentTransition -->
<div data-role="footer" id="ftrConfirmation" name="ftrConfirmation"></div>
<script>
$(document).ready(function() {
//Assign global variables from top of page
hdrMainVar = $('#hdrMain');
contentMainVar = $('#contentMain');
ftrMainVar = $('#ftrMain');
contentTransitionVar = $('#contentTransition');
stateLabelVar = $('#stateLabel');
whatLabelVar = $('#whatLabel');
stateVar = $('#state');
whatVar = $('#what');
form1Var = $('#form1');
confirmationVar = $('#confirmation');
contentDialogVar = $('#contentDialog');
hdrConfirmationVar = $('#hdrConfirmation');
contentConfirmationVar = $('#contentConfirmation');
ftrConfirmationVar = $('#ftrConfirmation');
inputMapVar = $('input[name*="_r"]');
hideContentDialog();
hideContentTransition();
hideConfirmation();
});
$('#buttonOK').click(function() {
hideContentDialog();
showMain();
return false;
});
$('#form1').submit(function() {
//Start with false to hide specific div tags
var err = false;
// Hide the Main content
hideMain();
// Reset the previously highlighted form elements
stateLabelVar.removeClass(MISSING);
whatLabelVar.removeClass(MISSING);
inputMapVar.each(function(index){
$(this).prev().removeClass(MISSING);
});
// Perform form validation
inputMapVar.each(function(index){
if($(this).val()==null || $(this).val()==EMPTY){
$(this).prev().addClass(MISSING);
err = true;
}
});
if(stateVar.val()==NO_STATE){
stateLabelVar.addClass(MISSING);
err = true;
}
// If validation fails, show Dialog content
if(err == true){
showContentDialog();
return false;
}
// If validation passes, show Transition content
showContentTransition();
// Submit the form
$.post("requestProcessor.php", form1Var.serialize(), function(data){
//DB Validation goes here when we link to the Db
confirmationVar.text(data);
hideContentTransition();
window.location="access.php";
});
return false;
});
function hideMain(){
hdrMainVar.hide();
contentMainVar.hide();
ftrMainVar.hide();
}
function showMain(){
hdrMainVar.show();
contentMainVar.show();
ftrMainVar.show();
}
function hideContentTransition(){
contentTransitionVar.hide();
}
function showContentTransition(){
contentTransitionVar.show();
}
function hideContentDialog(){
contentDialogVar.hide();
}
function showContentDialog(){
contentDialogVar.show();
}
function hideConfirmation(){
hdrConfirmationVar.hide();
contentConfirmationVar.hide();
ftrConfirmationVar.hide();
}
function showConfirmation(){
hdrConfirmationVar.show();
contentConfirmationVar.show();
ftrConfirmationVar.show();
}
</script>
This will not allow the form to be submitted if there is empty fields. Feel free to take this code and manipulate and play with it as much as you like. As you can see I used a .php file, just like you, to handle the validation of the user.