Chrome Extension Development - POST to new tab - javascript

Is there an easy solution to POST dynamically aggregated data into a new tab?
chrome.tabs.create does not have a 'POST' option. Normally I would use
chrome.browserAction.onClicked.addListener(function (t) {
chrome.tabs.create(
{
"url" : "http://super.url",
"method" : "POST" // oops.. no option.
});
});

You can simply combine these two techniques:
You may execute JavaScript commands by adding javascript: prefix at your address bar or in href values of <a> tags.
Only with JavaScript, you can create a form element and fill it with your data then POST it.
function fakePost() {
var form = document.createElement("form");
// Create a POST dump at ptsv2.com and change the code
form.setAttribute("action", "http://ptsv2.com/t/dcgex-1614815819/post");
form.setAttribute("method", "post");
var params = { userId: 2, action: "delete" };
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
// Appending the form might not be necessary
document.body.appendChild(form);
form.submit();
};
const
source = fakePost.toString().replace(/(\n|\t)/gm,'').replace(/\s\s/gm,' '),
url = `javascript:${source}; fakePost();`;
chrome.browserAction.onClicked.addListener(() => chrome.tabs.create({ url }));
Of course, that's just a dirty hack. If you need something more elaborate you can use a XHR Object or #Xan's answer.

The code in cvsguimaraes' answer works for short data strings, that can fit into a URL.
As evidenced by this question, it's not always the case.
Kenny Evitt's answer hints at the solution. I made an implementation for that question, and took time to generalize it. I present it here.
The idea is to open a page bundled with the extension (post.html), supply it with required information via messaging, and perform the POST from that page.
post.html
<html>
<head>
<title>Redirecting...</title>
</head>
<body>
<h1>Redirecting...</h1>
<!-- Decorate as you wish, this is a page that redirects to a final one -->
<script src="post.js"></script>
</body>
</html>
post.js
var onMessageHandler = function(message){
// Ensure it is run only once, as we will try to message twice
chrome.runtime.onMessage.removeListener(onMessageHandler);
// code from https://stackoverflow.com/a/7404033/934239
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", message.url);
for(var key in message.data) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", message.data[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form.submit();
}
chrome.runtime.onMessage.addListener(onMessageHandler);
background.js (or other non-content script inside the extension)
function postData(url, data) {
chrome.tabs.create(
{ url: chrome.runtime.getURL("post.html") },
function(tab) {
var handler = function(tabId, changeInfo) {
if(tabId === tab.id && changeInfo.status === "complete"){
chrome.tabs.onUpdated.removeListener(handler);
chrome.tabs.sendMessage(tabId, {url: url, data: data});
}
}
// in case we're faster than page load (usually):
chrome.tabs.onUpdated.addListener(handler);
// just in case we're too late with the listener:
chrome.tabs.sendMessage(tab.id, {url: url, data: data});
}
);
}
// Usage:
postData("http://httpbin.org/post", {"hello": "world", "lorem": "ipsum"});
Note the double messaging: with chrome.tabs.create callback we can't be sure that the listener is ready, nor can we be sure it's not done loading yet (though in my testing, it's always still loading). But better safe than sorry.

From #Amman Cheval's comments on the question:
[send] your dynamic data to the background file, creating a new tab which includes a form. Fill up the form using your form using the content using the background file, and then submit the form.
Read up about content scripts on Google's docs first. Then read up on message passing. After you've understood all of that, it'd be fairly simple to send a message from the script, to the background, and to the script of a different tab.

Related

How to redirect to another page through JS (sending parameters)

I'm trying to redirect to another page through JS(sending parameters)
I made the following code to that purpose, it does redirect and the requested page loads up 'ok'
window.location.replace(`http://10.0.30.11:3000/ProteseWEB/pages/detail/${path}?id=${param}`)
The problem is: When the requested page opens, it display an 404 not found on the network tab.
I don't understand why this is occuring, since the page I want is loaded 'perfectly'
The error on the network tab:
Edit(1)
#jlemley and #James Thank you for your answer!!!
Indeed the 404 request and the URL that I requested were different. So I changed the function a little bit.
Here's the code:
openPageDetail = function (path, params, method = 'POST') {
let iplocal = 'http://10.0.30.11:3000/ProteseWEB/pages/detalhe/'
const form = document.createElement('form');
form.method = method;
form.action = iplocal + path;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
I tried to make it as a form submit, still, the error occurs
In addition, there's how I call for this function.
I have a DataTable and when the user double click a row, it opens up a detail page for the desired record.
$('.table').on('dblclick', function(e) {
if ((!(e.target.classList.contains('sorting_asc'))) && (!(e.target.classList.contains('sorting_desc')))) {
openPageDetail('contas-a-pagar', {
id: e.target.parentElement.id
});
}
});

Javascript form only seems to submit properly to new tab, not same tab

I know the title is weird, but I can't think of a succinct way of saying this:
This code creates a form and submits to a URL:
function post_to_url( path, params, method ) {
method = method || "post"; // Set method to post by default if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
//form.setAttribute("target", "_blank");
for ( var key in params ) {
if ( params.hasOwnProperty(key) ) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
As you can see, I've commented out the target attribute.
I have the following code that calls the function:
var params = new Array();
params["param1"] = param1;
params["param2"] = param2;
post_to_url('newTask.php', params, "get");
If I have the target attribute set to _blank so it opens a new tab, the function works just fine and I can see my params right there in the url bar.
But if I remove the target attribute (which I would prefer), it seems as if the page just refreshes. No params in the URL, and the page doesn't act as if it has received data.
Can someone help me track this down please?
Try using:
form.setAttribute("target", "_self");

dynamic form not submitting file

I am trying to upload image to server in summernote. below script is success to submit the form but file not received at backend. am i doing something wrong here?
var edit = function() {
$('.click2edit').summernote({
focus: true,
onImageUpload: function(files, editor, welEditable) {
sendFile(files[0],editor,welEditable);
}
});
};
function sendFile(file,editor,welEditable) {
alert(file.size);
var iframe = $('<iframe name="postiframe" id="postiframe" style="display: none" />');
$("body").append(iframe);
alert("1");
var form = $('#theuploadform');
form.attr("action", "UploadServlet");
form.attr("method", "post");
form.attr("enctype", "multipart/form-data");
form.attr("encoding", "multipart/form-data");
form.attr("target", "postiframe");
form.attr("file", file);
form.submit();
alert("2");
$("#postiframe").load(function () {
iframeContents = $("#postiframe")[0].contentWindow.document.body.innerHTML;
return iframeContent;
});
return false;
}
You can't set a default value to an HTML upload control.
You need to display the form for user choose the file, then you can post to server.
Some references:
http://www.w3schools.com/jsref/prop_fileupload_value.asp
How to set a value to a file input in HTML?
Set default value for a input file form
Thanks all. got an work around for this issue. I changed the summernote code to return a wrapping form and them posted that form. It posted successfully. I have some issue in loading the uploaded image to editor. but i will start another thread for that. thanks all.

Attempting to call a page using POST with JavaScript, failing to pass parameters

I was using the solution found here: Javascript Post on Form Submit open a new window
The code I've got opens the target page as if the submit worked properly. When I look at the form itself, all of the hidden fields are there, but the target doesn't see them - $_REQUEST is empty in the PHP code. Here's my function to create the view (heavily stolen from the post mentioned above):
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
form.setAttribute("target", "formresult");
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
window.open("", "formresult", '');
form.submit();
document.body.removeChild(form);
}
And here is the call:
post_to_url("test.php", { "username": "shaleth", "action": "login" }, "post");
I have to be missing something simple, but I can't see it. Any assistance would be appreciated.

How to check if page exists using JavaScript

I have a link: Hello.
When someone clicks the link I'd like to check via JavaScript if the page the href-attribute points to exists or not. If the page exists the browser redirects to that page ("www.example.com" in this example) but if the page doesn't exist the browser should redirect to another URL.
It depends on whether the page exists on the same domain or not. If you're trying to determine if a page on an external domain exists, it won't work – browser security prevents cross-domain calls (the same-origin policy).
If it is on the same domain however, you can use jQuery like Buh Buh suggested. Although I'd recommend doing a HEAD-request instead of the GET-request the default $.ajax() method does – the $.ajax() method will download the entire page. Doing a HEAD request will only return the headers and indicate whether the page exists (response codes 200 - 299) or not (response codes 400 - 499). Example:
$.ajax({
type: 'HEAD',
url: 'http://yoursite.com/page.html',
success: function() {
// page exists
},
error: function() {
// page does not exist
}
});
See also: http://api.jquery.com/jQuery.ajax/
A pretty good work around is to proxy. If you don't have access to a server side you can use YQL. Visit: http://developer.yahoo.com/yql/console/
From there you can do something like: select * from htmlstring where url="http://google.com". You can use the "REST query" they have on that page as a starting point for your code.
Here's some code that would accept a full URL and use YQL to detect if that page exists:
function isURLReal(fullyQualifiedURL) {
var URL = encodeURIComponent(fullyQualifiedURL),
dfd = $.Deferred(),
checkURLPromise = $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20htmlstring%20where%20url%3D%22' + URL + '%22&format=json');
checkURLPromise
.done(function(response) {
// results should be null if the page 404s or the domain doesn't work
if (response.query.results) {
dfd.resolve(true);
} else {
dfd.reject(false);
}
})
.fail(function() {
dfd.reject('failed');
});
return dfd.promise();
}
// usage
isURLReal('http://google.com')
.done(function(result) {
// yes, or request succeded
})
.fail(function(result) {
// no, or request failed
});
Update August 2nd, 2017
It looks like Yahoo deprecated "select * from html", although "select * from htmlstring" does work.
Based on the documentation for XMLHttpRequest:
function returnStatus(req, status) {
//console.log(req);
if(status == 200) {
console.log("The url is available");
// send an event
}
else {
console.log("The url returned status code " + status);
// send a different event
}
}
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == 4)
returnStatus(this, this.status);
}
client.open("HEAD", address);
client.send();
}
fetchStatus("/");
This will however only work for URLs within the same domain as the current URL. Do you want to be able to ping external services? If so, you could create a simple script on the server which does your job for you, and use javascript to call it.
If it is in the same domain, you can make a head request with the xmlhttprequest object [ajax] and check the status code.
If it is in another domain, make an xmlhttprequest to the server and have it make the call to see if it is up.
why not just create a custom 404 handler on the web server? this is probably the more "good-bear" way to do this.
$.ajax({
url: "http://something/whatever.docx",
method: "HEAD",
statusCode: {
404: function () {
alert('not found');
},
200: function() {
alert("foundfile exists");
}
}
});
If you are happy to use jQuery you could do something like this.
When the page loads make an ajax call for each link. Then just replace the href of all the links which fail.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
<!--
$.fn.checkPageExists = function(defaultUrl){
$.each(this, function(){
var $link = $(this);
$.ajax({
url: $link.attr("href"),
error: function(){
$link.attr("href", defaultUrl);
}
});
});
};
$(document).ready(function(){
$("a").checkPageExists("default.html");
});
//-->
</script>
You won't be able to use an ajax call to ping the website because of same-origin policy.
The best way to do it is to use an image and if you know the website you are calling has a favicon or some sort of icon to grab, you can just use an html image tag and use the onerror event.
Example:
function pingImgOnWebsite(url) {
var img = document.createElement('img');
img.style.visibility = 'hidden';
img.style.position = 'fixed';
img.src = url;
img.onerror = continueBtn; // What to do on error function
document.body.appendChild(img);
}
Another way to do this is is with PHP.
You could add
<?php
if (file_exists('/index.php'))
{
$url = '/index.php';
} else {
$url = '/notindex.php';
}
?>
And then
<a href="<?php echo $url; ?>Link</a>

Categories