I want to create a HTML page which offers a button (link, some other clickable element, etc.) which, when pressed, sends a specific constant POST request to a specific constant server. The value I need to post is a specific constant JSON-encoded value ({"key":"value"}), so for HTTP it is just a very short constant string.
The value and the URL I have to use are constant. In order to make something happen, I have to send exactly this constant POST request. There is no need to parameterize this request or to "set a value" or similar. Also, I have no parameter name or similar. I must not send a parameter list with a parameter whose value is the JSON-encoded value, but I must send the JSON-encoded value by itself. The complete POST request can look like this:
POST /post/path/to/action HTTP/1.1
Host: the.specific.server
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
{"key":"value"}
(NOT parameter={"key":"value"} or similar as body!)
The server is not under my authority but a service I want to use.
With pure shell means I can do this very simply using curl:
curl http://the.specific.server/post/path/to/action -d '{"key":"value"}'
I imagined something like
<button url="http://the.specific.server/post/path/to/action"
value="{%22key%22:%22value%22}">visible text</button>
but I found nothing appropriate.
Based on questions like this or this or this I tried various approaches like this one:
<form method="POST" action="http://the.specific.server/post/path/to/action">
<input type="text" id="key" key="value">value</input>
<button type="submit" value="{%22key%22:%22value%22}">visible text</button>
</form>
With or without the input field, the button, with other arguments, other values, etc. but nothing finally sent anything useful to the server when pressed. At best I got something which was also transmitting a parameter name (thus the payload was not just the Json-encoded value).
I guess I'm just missing something basic in this :-}
There is no way in HTML to generate JSON from forms. You need here to implement this using an AJAX request.
Using jQuery it could be something like that:
$.ajax({
type: 'POST',
url: 'http://the.specific.server/post/path/to/action',
data: '{"key":"value"}',
success: function() {
// Successful response received here
},
dataType: 'json',
contentType : 'application/json'
});
This will be trigger when clicking on a button or a link, as described below:
$('#myButtonId').click(function() {
$.ajax({
(...)
});
});
This can be put for example in a script in your page after including jQuery library, as described below:
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
// Waiting for the DOM to be loaded
$(document).ready(function() {
$('#myButtonId').click(function() {
// When button is clicked
$.ajax({
(...)
});
});
});
</script>
<body>
<button id="myButtonId">CLICK ME</button>
</body>
</head>
Edited
Here is the way to send an HTTP request using raw JavaScript API: http://www.quirksmode.org/js/xmlhttp.html.
I adapted this code to work for your use case:
function sendRequest(url, callback, postData, contentType) {
var req = createXMLHTTPObject();
if (!req) return;
var method = (postData) ? "POST" : "GET";
req.open(method,url,true);
req.setRequestHeader('User-Agent','XMLHTTP/1.0');
if (postData) {
if (contentType) {
req.setRequestHeader('Content-type', contentType);
} else {
req.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
}
}
req.onreadystatechange = function () {
if (req.readyState != 4) return;
if (req.status != 200 && req.status != 304) {
return;
}
callback(req);
}
if (req.readyState == 4) return;
req.send(postData);
}
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0;i<XMLHttpFactories.length;i++) {
try {
xmlhttp = XMLHttpFactories[i]();
} catch (e) {
continue;
}
break;
}
return xmlhttp;
}
To execute your request, simply use the function sendRequest:
sendRequest(
'http://the.specific.server/post/path/to/action',
function() {
// called when the response is received from server
},
'{"key":"value"}',
'application/json');
Hope it helps you,
Thierry
A simple, customisable an no dependencies solution based on : https://gist.github.com/Xeoncross/7663273
May works on IE 5.5+, Firefox, Opera, Chrome, Safari.
<html>
<body>
<button id="myButtonId" onclick='post("http://the.specific.server/post/path/to/action", "{\"key\":\"value\"}");'>CLICK ME</button>
</body>
<script>
function post(url, data, callback) {
try {
var req = new(this.XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
req.open('POST', url, 1);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.send(data)
} catch (e) {
window.console && console.log(e);
}
}
</script>
</html>
You are looking for FORM encoding algorithm which enables form data to be transmitted as json.
Have a look at W3C HTML JSON form submission. It is not active and not likely to be maintained.
So, you are better off using the above JS or Jquery solution or use a server side forwarding. My suggestion is to use jquery as most websites point to google cdn these days and jquery is mostly browser cached. With below code, you neatly fire a POST request without worrying about underlying browser variants.
$.ajax({
type: 'POST',
url: 'http://the.specific.server/post/path/to/action',
data: '{"key":"value"}',
success: function() {
// Successful response received here
},
dataType: 'json',
contentType : 'application/json'
});
Try this suggestion using JQuery methods and Ajax:
$(document).ready(function(){
$("#myForm").submit(function(){
$.ajax({type:"POST",
data: $(this).serializeObject(),
url:"http://the.specific.server/post/path/to/action",
contentType: "application/json; charset=UTF-8",
success: function(data){
// ... OK
},
error: function(){
// ... An error occured
}
});
return false;
});
});
Note : serializeObject method converts form elements to a JSON string.
I now went for a simplistic solution (because that's what I wanted) I found myself by searching for more answers. It seems there is no way around using JS for this task.
<button onClick="postCommand('mypath', 'mykey', 'myvalue')">Click</button>
<script>
function postCommand(path, key, value) {
var client = new XMLHttpRequest();
var url = "http://the.specific.server/" + path;
client.open("POST", url, true);
client.send("{\"" + key + "\":\"" + value + "\"}");
}
</script>
This is in general #aprovent's answer, so I accepted his and granted him the bounty.
I am developing a web application using the Spring framework and Thymeleaf.
I have created a drop down menu, but I want something else on the page to appear when a certain option in the drop down menu is selected. By selected I mean when the option in the menu is clicked on and nothing more. I do not mean complete form submission.
I have read through the docs but found no solution.
Any ideas?
Thanks
You ca use JS using th:inline like this, explanation is on comment
JS code
<script th:inline="javascript">
//Declare the URL of RequestMapping to use
//Do no change format
/*[+
var urlToload = [[#{/path/spring}]];
var anotherUrlToUse = [[#{/another/url?param=}]];
+]*/
//Handle you jquery event
$('body').on('click', '.dropdown-menu', function (e) {
var t = $(this);
//Sending your ajax request
$.ajax({
url: urlToload,
method: 'POST',
data: {
optionSelected: t.val()
}
})
/**
* Execute when your request is done
* #param {type} data : the page result of your Request *
*/
.done(function (data) {
$("#receiver").html(data);
})
//Execute on fail
.fail(function (xhr, ajaxOptions, thrownError) {
console.log("ERROR");
//Use anotherUrlToUse with GET METHOD to redirect
window.location.replace(anotherUrlToUse+404);
});
});
</script>
Controller code
#RequestMapping(value = "/path/spring", method = RequestMethod.POST)
public String controllerMethod(Model model, #RequestParam("optionSelected") String optionSelected) {
/**
* Do your job
* Your code
*/
return "page/result";
}
I can successfully serialize the form and submit it to a text area in the form, but don't know how to send it to a Servlet that I have already created/defined:
// Prepare form for Serialize
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
// Send JSON Data to ResultSet
$(function() {
$('form').submit(function() {
//submitting to textarea "resultset"
//needs to submit to servlet "SftpConnTest" as defined in web.xml
//$('#ResultSet').text(JSON.stringify($('form').serializeObject()));
//?? HOW DO I SEND TO "SftpConnTest" SERVLET instead??
return false;
});
});
Use following to send form data via ajax to server:
$.post("path/to/servlet", $("#formId").serializeArray(), function (result) {
// do something
});
By the way:
serializeArray() will convert a form to an array, which could be used directly as the "data" param of a jquery ajax request, only element that has a name property in the form will be included into the data,for details please check jquery api, it's very clear there.
Assuming you are sending this to the servlet using an HTTP POST, you can use ajax:
$(function() {
$('form').submit(function(evt) {
evt.preventDefault(); // prevent the default form submit behavior
var data = $('form').serializeObject();
$.post(
'/',
data,
function(resData, status, req) {
$('#ResultSet').text(JSON.stringify(resData));
}
);
}
}
If the servlet is not mapped to be located at the root of the web app, replace 'SftpConnTest' in the $.post function with the relative path to the servlet. For example, if the servlet is mapped to /foo/bar/SftpConnTest, then you should have '/foo/bar/SftpConnTest' instead of 'SftpConnTest'.
See the jQuery docs for more information on the $.post function.
Updated code and issue:
I am creating a test harness for my RPC server. Currently it consists of a page which immeadiately fires off an AJAX request to retrieve all functions on the server. Once that is returned it creates a list of buttons so I can click to test. Eventually I will add dialog boxes to test parameter passing to the functions but currently I want to just fire off the basic request when I click the button. The issue I am seeing is that the onclick function is always firing the last function in the list presumably because when the click is fired key is set to the last value in the array. I thought to pass button.innerHTML value but that too suffers that the last button.innerHTML is that of the final key.
What do I need to do to fire off the action correctly?
Here is the business end of the code:
$(document).ready(function() {
$.jsonRPC.setup({
endPoint: '//api.localhost/index.php'
});
$.jsonRPC.request('getExampleData', {
params: [],
success: function(result) {
for (var key in result.result) {
console.log(key+' => '+result.result[key]);
var button = document.createElement('button');
button.innerHTML = result.result[key];
button.onclick = function() { callRPCFunction(result.result[key]); return false; }
var foo = document.getElementById("page");
foo.appendChild(button);
}
},
error: function(result) {
console.log(result);
}
});
});
function callRPCFunction(target) {
$.jsonRPC.request(target, {
params: [],
success: function(result) {
console.log(result);
},
error: function(result) {
console.log(result);
}
});
}
Assignment to element.onClick will not work until the element is added to the DOM. You may call element.onClick(callRPCFunction(result.result[key])); after foo.appendChild(element);. That might work!
You may use jQuery's live() here, it was created for these purposes:
$(element).live('click', callRPCFunction(result.result[key])
I have two forms, which I have combined into one; parts of the form change depending on the drop down menu choice the user has selected (tech support or sales). I would like to use the $.ajax function however I noticed there is only one url: used. Can I use an if condition here??
Build the url first and then pass it to $.ajax
var postURL = "";
if (Whatever)
{
postURL = "URL1";
}
else
{
postURL = "URL2";
}
$.ajax({
url: postURL,
context: document.body,
success: function(){
$(this).addClass("done");
}
});
Wrap your call to $.ajax in a coditional like so:
if (condition) {
$.ajax() // page 1
} else {
$.ajax() // page 2
}