Reload url with variable from form field PHP/HTML/Javascript [duplicate] - javascript

Consider this form:
<form action="http://www.blabla.com?a=1&b=2" method="GET">
<input type="hidden" name="c" value="3" />
</form>
When submitting this GET form, the parameters a and b are disappearing.
Is there a reason for that?
Is there a way of avoiding this behaviour?

Isn't that what hidden parameters are for to start with...?
<form action="http://www.example.com" method="GET">
<input type="hidden" name="a" value="1" />
<input type="hidden" name="b" value="2" />
<input type="hidden" name="c" value="3" />
<input type="submit" />
</form>
I wouldn't count on any browser retaining any existing query string in the action URL.
As the specifications (RFC1866, page 46; HTML 4.x section 17.13.3) state:
If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type.
Maybe one could percent-encode the action-URL to embed the question mark and the parameters, and then cross one's fingers to hope all browsers would leave that URL as it (and validate that the server understands it too). But I'd never rely on that.
By the way: it's not different for non-hidden form fields. For POST the action URL could hold a query string though.

In HTML5, this is per-spec behaviour.
See Association of controls and forms - Form submission algorithm.
Look at "4.10.22.3 Form submission algorithm", step 17. In the case of a GET form to an http/s URI with a query string:
Let destination be a new URL that is equal to the action except that
its <query> component is replaced by query (adding a U+003F QUESTION
MARK character (?) if appropriate).
So, your browser will trash the existing "?..." part of your URI and replace it with a new one based on your form.
In HTML 4.01, the spec produces invalid URIs - most browsers didn't actually do this though...
See Forms - Processing form data, step four - the URI will have a ? appended, even if it already contains one.

What you can do is using a simple foreach on the table containing the GET information. For example in PHP :
foreach ($_GET as $key => $value) {
$key = htmlspecialchars($key);
$value = htmlspecialchars($value);
echo "<input type='hidden' name='$key' value='$value'/>";
}
As the GET values are coming from the user, we should escape them before printing on screen.

You should include the two items (a and b) as hidden input elements as well as C.

I had a very similar problem where for the form action, I had something like:
<form action="http://www.example.com/?q=content/something" method="GET">
<input type="submit" value="Go away..." />
</form>
The button would get the user to the site, but the query info disappeared so the user landed on the home page rather than the desired content page. The solution in my case was to find out how to code the URL without the query that would get the user to the desired page. In this case my target was a Drupal site, so as it turned out /content/something also worked. I also could have used a node number (i.e. /node/123).

If you need workaround, as this form can be placed in 3rd party systems, you can use Apache mod_rewrite like this:
RewriteRule ^dummy.link$ index.php?a=1&b=2 [QSA,L]
then your new form will look like this:
<form ... action="http:/www.blabla.com/dummy.link" method="GET">
<input type="hidden" name="c" value="3" />
</form>
and Apache will append 3rd parameter to query

When the original query has array, for php:
foreach (explode("\n", http_build_query($query, '', "\n")) as $keyValue) {
[$key, $value] = explode('=', $keyValue, 2);
$key = htmlspecialchars(urldecode($key), ENT_COMPAT | ENT_HTML5);
$value = htmlspecialchars(urldecode($value), ENT_COMPAT | ENT_HTML5);
echo '<input type="hidden" name="' . $key . '" value="' . $value . '"' . "/>\n";
}

To answer your first question yes the browser does that and the reason is
that the browser does not care about existing parameters in the action URL
so it removes them completely
and to prevent this from happening use this JavaScript function that I wrote
using jQuery in:
function addQueryStringAsHidden(form){
if (form.attr("action") === undefined){
throw "form does not have action attribute"
}
let url = form.attr("action");
if (url.includes("?") === false) return false;
let index = url.indexOf("?");
let action = url.slice(0, index)
let params = url.slice(index);
url = new URLSearchParams(params);
for (param of url.keys()){
let paramValue = url.get(param);
let attrObject = {"type":"hidden", "name":param, "value":paramValue};
let hidden = $("<input>").attr(attrObject);
form.append(hidden);
}
form.attr("action", action)
}

My observation
when method is GET and form is submitted, hidden input element was sent as query parmater. Old params in action url were wiped out. So basically in this case, form data is replacing query string in action url
When method is POST, and form is submitted, Query parameters in action url were intact (req.query) and input element data was sent as form data (req.body)
So short story long, if you want to pass query params as well as form data, use method attribute as "POST"

This is in response to the above post by Efx:
If the URL already contains the var you want to change, then it is added yet again as a hidden field.
Here is a modification of that code as to prevent duplicating vars in the URL:
foreach ($_GET as $key => $value) {
if ($key != "my_key") {
echo("<input type='hidden' name='$key' value='$value'/>");
}
}

Your construction is illegal. You cannot include parameters in the action value of a form. What happens if you try this is going to depend on quirks of the browser. I wouldn't be surprised if it worked with one browser and not another. Even if it appeared to work, I would not rely on it, because the next version of the browser might change the behavior.
"But lets say I have parameters in query string and in hidden inputs, what can I do?" What you can do is fix the error. Not to be snide, but this is a little like asking, "But lets say my URL uses percent signs instead of slashes, what can I do?" The only possible answer is, you can fix the URL.

I usually write something like this:
foreach($_GET as $key=>$content){
echo "<input type='hidden' name='$key' value='$content'/>";
}
This is working, but don't forget to sanitize your inputs against XSS attacks!

<form ... action="http:/www.blabla.com?a=1&b=2" method ="POST">
<input type="hidden" name="c" value="3" />
</form>
change the request method to' POST' instead of 'GET'.

Related

Insert Query from Cloned Form Field

I have a project in which I have to be able make a multiple input if needed. I'm really new to JavaScript and the insert method that I'm familiar with is only POST method which I parsed it from Form. My question is how do I do to use query in my script?
This is my code and the query is needed between Do...While at the bottom:
<div id="form" class="hidden">
Nama : <input type="text" name="nama"><br/>
Kuantitas : <input type="text" name="kuantitas"><br/>
Kategori : <select name="idKategori">
<?php
while ($rowKategori = mysqli_fetch_object($resultKategori)) {
echo "<option value='".$rowKategori->id."'>".$rowKategori->nama."</option>";
}
?>
</select>
<input type="hidden" name="hidden" value="bahan">
<input type="button" id="remove" value="Remove">
</div>
<form>
<input type="button" value="Tambah barang lain" id="add">
<input type="button" id="insert" value="Insert" style="margin-left: 50%;">
$(document).ready(function() {
var form_index = 0;
$("#add").click(function() {
form_index++;
$(this).parent().before($("#form").clone().attr("id", "form" + form_index));
$("#form" + form_index).css("display", "inline");
$("#form" + form_index + " :input").each(function() {
$(this).attr("name", $(this).attr("name") + form_index);
$(this).attr("id", $(this).attr("id") + form_index);
});
$("#remove" + form_index).click(function() {
$(this).closest("div").remove();
});
});
$("#insert").click(function() {
var i = 0;
do {
i++;
} while (i != 5);
});
im really bad at english , so let me explain it as simple as i can.
i wanted to make a form field with submit button, like the usual.
the difference is i wanted to make a clone button so i could add
more form field with single submit button.
the code that i write is something that i learn from another page and im not familiar with it.
i dont know how to get vallue from the cloned page, and i dont know how to handle the value itself in the script as i really noob at javascript
what i wanted to do is how do you get value from all cloned form field while i click the submit button? the method i familiran with is POST method, but i thinking about writedown all my query on the javascript since the POST method could not do the looping for all the formfield, thats why i make the loop on the javascript
and im sorry with my english, im not really good at it
Ok here you go, here is a fiddle of it.
https://jsfiddle.net/2ngjqxge/3/
HTML/PHP
<div id="form_block_wrapper" class="hidden"> <!-- added an outside wrapper -->
<div class="form_block" class="hidden">
Nama : <input type="text" name="nama[]"><br/>
Kuantitas : <input type="text" name="kuantitas[]"><br/>
Kategori : <select name="idKategori[]">
<?php while ($rowKategori = mysqli_fetch_object($resultKategori)): ?>
<option value="<?php echo $rowKategori->id; ?>">
<?php echo $rowKategori->nama; ?>
</option>
<?php endWhile; ?>
</select>
<input type="hidden" name="hidden[]" value="bahan">
<input type="button" name="remove" value="Remove">
</div>
</div> <!-- close #form_block_wrapper -->
<input type="button" value="Tambah barang lain" id="add">
<input type="button" id="insert" value="Insert" style="margin-left: 50%;">
Please note, I changed a number of things. Most importantly all the names of the inputs that would get submitted i added [], so nama becomes nama[] etc. Now if you were to submit this as a form, on the server side you would get arrays instead of single elements. Single elements would get overwritten by the next dynamically created "form_block" so this is what we would need to process them. The data you would expect on submission of the form would be like this ( assuming we had 3 "form_blocks" ):
$_POST['nama'] = [
0 => 'nama from first form block',
1 => 'nama from second form block',
2 => 'nama from third form block',
];
$_POST['kuantitas'] = [
0 => 'kuantitas from first form block',
1 => 'kuantitas from second form block',
2 => 'kuantitas from third form block',
];
//etc...
Next, I removed any ID's as we know ids in HTML elements must be unique, so there is no point messing with them when we are creating and destroying dynamic content. We could append an index as you originally did, but the selectors are simple enough so we don't really need to do this. And it's worth it to keep things simple, why over complicate it.
I also used the "alternative" PHP syntax for the while block. while(..): with a colon instead of while(..){ with a bracket. It just looks better to me when mixed with HTML to have the <?php endWhile; ?> insteadd of <?php } ?>. It doesn't matter much here as this is small. But after adding buches of PHP, you would have all these hanging } brackets everywhere. It's easier to keep track of the close of code blocks when they are like endIf; endWhile; etc. I also kept the HTML as HTML and not a big string that has to be echoed out, again because it looks better to me that way. It also makes dealing with the quotes " easier then having to concatenate PHP '<tag attr="'.$php.'">'.
These things you can do either way, just I'm a bit particular and a perfectionist when it comes to formatting and readability. Sort of set in my ways.
Javascript (jQuery)
(function($){
$(document).ready(function() {
//get and cache Outer HTML for .form_block
var selectHtml = $('.form_block:eq(0)')[0].outerHTML;
$("#add").click(function() {
$('#form_block_wrapper').append(selectHtml);
});
//use .on for events on dynamic content ( event delegation )
$("#form_block_wrapper").on('click', 'input[name="remove"]', function() {
$(this).closest(".form_block").remove();
});
$("#insert").click(function() {
//I have no idea what you want to do here?
//Are you trying to insert something into the page
//or Are you trying to insert the data into the DB, ie submit it to the server.
//you can serialze all the data https://api.jquery.com/serialize/
//$('#form_block_wrapper').serialize();
//you can get the selected options and get their value
var d = [];
$('select[name="idKategori[]"]').each( function(){
d.push($(this).val());
});
alert(d.join(','));
});
}); //document.ready
})(jQuery); //assign jQuery to $ - for compatibility reasons.
The first thing to do here is not clone the select but instead take a snapshot of it's html. Stored in selectHtml. There is several reasons why this is better.
if user changes the value of these fields, when we clone we have to reset all those values.
if we remove all form blocks, there is nothing to clone and we are struck on a page without our form elements, tell we refresh.
based just on the length of my code -vs- your orignal code, it should be obvious which method is simpler to handle. Simple is easy to read and maintain, do more with less.
Another thing to note, is you were attaching the remove button's event to each button as they are created. While this is ok, we can do better by using event delegation $.on to handle this element.
I still have no Idea what you want done with Insert,
do you mean insert something into the page
do you mean submit the form and insert the data somewhere.
but hopefully this helps

Getting values from html form as JavaScript variables

i want to capture input variables sent via form from one page to another.html page and obtain these values as JavaScript variables. Can this be done.
This is my form;
<form action='another.html' id='form' data-ajax='false'>
<input id='sent_by' value='tom'/>
<input type='submit' value='Submit'/>
</form>
And in my another.html i tried to get the values as;
var sent_by = $.session.get("sent_by");
But i am not able to get the values. All help is appreciated.
You can use the browser's localStorage to achieve this. Before submitting and going to the other page store all the values of the form in the localStorage and you can access it on the other page:
Page1.html
Field Name = "name" <input type="text" name="name" id="name" />
Read the value and store it to localStorage
localStorage.setItem('name', document.getElementById('name').value);
and so on.
You can make a function in JavaScript that saves all the fields of the form in localStorage on / before submit.
To read these values on the other page:
Page2.html
Value stored for key name can be get using the following JavaScript:
localStorage.getItem("name");
NOTE
the page1.html and page2.html should be in the same domain for you to access the localStorage.
Read more about localstorage at https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
Have you tried using Window.localStorage? It's similar to sessionStorage but with no expiration date. So, be sure to clear it once the browsing session ends.
I think the answer provided by #Shakti Phartiyal is probably the most practical and a sweet trick I might add. The main reason I'm writing this post is because I had also taken a long path of using javascript to pass along this kind of information. It resulted in me bewildered at how powerful PHP can be for some tasks that you dedicated javascript to do. (Yea I know some javascript wizards out there can do everything with it, I'm just talking about basic programming tho). So if you wondered what the PHP way of passing this around:
Your modified html form:
<form action='another.html' id='form' data-ajax='false' method='post'>
<input id='sent_by' value='tom' name='uname'/>
<input type='submit' value='Submit'/>
</form>
and then in "another.php" you would have this to retrieve the input from the form:
<?php
$uname= htmlspecialchars($_POST['uname'];
?>
Great. But how to make this php variable into javascript?
Ah, the fun part. You're going to write javascript to your webpage with php - you do something like this:
var uname = "<?php echo $uname; ?>";

Form submitting when clicked

I am having an issue with this login system, when ever I click the log in button, or the sign up button it re-directs me to a white page with writing on it, That being said it is interfering with my log in action.
Here is the code that I think is causing the issue,
<form method="POST" action="" accept-charset="UTF-8">
on line 16 of the HTML code, I tried to take that code out and it stopped the re-directing but the text boxes went out of place, and the white background/background-box was not there either,
Link, HERE
You want to use preventDefault() if this is a purely Javascript: you should be able to pass the button press event into the listener when you create it:
$('.login').on('click', function(e) {
e.preventDefault();
// Will be executed on press
}
<form method="POST" class="login" accept-charset="UTF-8">
If there's no JS involved in this scenario, then you want to get rid of the action parameter entirely – leaving it as the empty string will still cause it to redirect in some cases.
As Jonathan Lonowski explained above, when the log in / sign up button is clicked, the form will post the data to the page mentioned in the action= attribute. Since this attribute is empty in your form tags, it will re-load the same page, posting the data to itself.
The data will arrive in key=value variable pairs. The variable value will be the contents of the field, the variable name will be the value of the name="" attribute on the element.
For e.g., for this field:
<input id="fname" name="first" value="Bobby" />
The data will be received like this:
$fn = $_POST['first']; //value is Bobby, or whatever user enters
On your page containing the form, add a section at the top like this:
<?php
if (isset($_POST['fname']) == true){
$fn = $_POST['fname'];
echo "Received First Name: " . $fn;
die();
}else{
?>
//Your current page, in its entirety, goes here
<?php
} //close the PHP if statement
?>
That is how you deal with a normal HTML <form> construct.
However, if you wish to use AJAX to communicate with a PHP file without changing the page, then:
(1) There is no need to use a <form> construct, just use a DIV with an input button: <input type="button" id="sub_btn" value="Submit" />
(2) Trap the button press using standard js/jQuery:
$('sub_btn').click(function(){
var fn = $('#first').val();
//etc.
$.ajax(function(){
type: 'post',
url: 'my_php_processing_file.php',
data: 'fname=' +fn+ '&lname=' etc
});
});
In your PHP processor file, the data will be received thus:
<?php
$fn = $_POST['fname'];
$ln = $_POST['lname'];
//Do your MySQL lookup here...
echo 'Received ' .$fn. ' ' .$ln;
(3) IF you do use the form construct, you can still do everything as above, but you will need to suppress the default form action of navigating to the page specified in the action= attribute (an attribute setting of action="" will post data to and reload the same page you are on).
To suppress navigating to the page specified in action= (involves page refresh, even if just action=""), use event.preventDefault(), as follows:
$('#buttonID').click(function(event){
event.preventDefault();
//remainder of button click code goes here
});

Javascript - redirect to a page with POST data

I've got a page where the user can search (all in AJAX) in the database and select, let's say, different type of data on the page. When's he chosen them, what I need is to redirect the user to ANOTHER page (still on my website though), with POST data.
The new page where the user will arrive needs that POST data, and the user needs to go to the new page.
I've read that I could create a form before loading the page and simply submit it when I want to redirect, but the thing is that I don't have the data that will be included in the before hand.
I've tried doing something like this:
document.write('<form id="reviseCombi" method="post" action="otherPage.php"><input name="input1" type="hidden" value="ok" /><input type="input2" type="hidden" value="'+ mots +'" /></form>');
f=document.getElementById('reviseCombi');
if(f){
f.submit();
}
But the second input doesn't arrive to the new page when I check with Tamper Data. And it reloads the actual page first, which is weird too.
Is there a better way to do it?
EDIT: I got an answer for the input part. The page now gets the two inputs. But: it still reloads a blank page ONLY containing the form (and the html, body, etc.) and then it redirects. Any idea how I can have it directly?
Sorry if it's not very clear, it's tough to explain. I'll answer any comments to explain it better.
Thanks alot.
Q: "But the second input doesn't arrive to the new page"
A: Your second input does NOT have name! (type="input2" make it name="input2")
Q: "And it reloads the actual page first, which is weird too."
A: If you are using firefox and you echo data before the < DOCTYPE > and < HTML > tags, you get an auto refresh. if you wish to debug, echo data inside the < BODY >
A2: Its possible that the strange reload happens because you are doing that document.write of the form outside the < BODY > or maybe inside the < HEAD > ... if thats the case why not doing this:
html
<div id="myformcontainer"></div>
js
function CreateAFormInsideMyDivAndSubmitIt(mots)
{
var mydiv = document.getElementById('myformcontainer').innerHTML = '<form id="reviseCombi" method="post" action="otherPage.php"><input name="input1" type="hidden" value="ok" /><input name="input2" type="hidden" value="'+ mots +'" /></form>';
f=document.getElementById('reviseCombi');
if(f){
f.submit();
}
}
jsfiddle: http://jsfiddle.net/MDx8H/1/ (alerts instead of submits)

Copy field value and filter out all but the file name

I had an issue with copying a value from one form to another via JavaScript, which I was able to figure out with help from my previous question here: "How to copy a value from one form's file upload field to another form's text field?"
So, thank you!
But now I have a new issue. When the form field value is copied over, in some browsers (such as IE), the field contains the local path of the field on the user's computer (i.e. "C:\Users\username\Desktop\file.png"), which obviously won't work in the URL.
So: is there a way to filter out everything but the file name itself before it's copied to the new field? Or a way to do it after the fact?
Thanks for the help!
Here is my most recent simplified code for this:
<script>
$(function(){
bindGroups();
});
var bindGroups = function() {
// First copy values
$("input[name='logofile']").val($("input[name='logoname']").val());
// Then bind fields
$("input[name='logoname']").change(function() {
$("input[name='logofile']").val($(this).val());
});
};
</script>
<form action="/current-url" method="post" enctype="multipart/form-data">
<input type="file" name="logoname" value="1" />
<input type="submit" value="Upload" />
</form>
<form name="create_landing_page" action="/landing-page-url/" method="get">
<input type="hidden" name="logofile" />
<input type="submit" value="Generate Landing Page" /></form>
Try using a combination of split() and pop();
var basename = fullFileName.split('\\').pop();
Note the double backslash to escape the slash; this will only fix the problem for Windows browsers, because Linux/OS X uses a slash (/) as directory separator, so might try this (untested as I'm on my iPad at the moment)
var basename = fullFileName;
if (indexof('\\', basename) >= 0) {
basename = basename.split('\\').pop();
}
if (indexof('/', basename) >= 0) {
basename = basename.split('/').pop();
}
Try this:
var field = $(this).val();
var index = field.lastIndexOf("\");
field = field.substr( index, field.length-index );
I finally figured this out, and it was simpler than I had hoped. All I had to do was change the line:
$("input[name='logofile']").val($(this).val());
to:
$("input[name='logofile']").val($(this).val().split('\\').pop());
The problem with using a variable was that I had to refresh it when the upload field changed, which wasn't hard; I refreshed the variable when the upload button was clicked. But for some reason, when I replaced $("input[name='logoname']") with my variable name, the value wouldn't copy over. I couldn't figure it out.
This ended up being much simpler, no variables needed. Split/pop did the job, so thanks everyone who suggested it! You pushed me in the right direction.

Categories