Send PHP POST using Javascript AJAX - javascript

My data is not inserting into database, I get a blank response from the console log and network. I'm kinda lost my javascript source code is mix with other stack overflow answers as well as my PHP code.
<form id="requestForm">
<input type="text" name="fName" id="name">
<input type="text" name="fAddress" id="address">
<input type="text" name="fComment" id="comment">
<input type="submit" value="Submit" name="nameSubmit">
</form>
<script>
document.querySelector('#requestForm').addEventListener('submit', postRequest);
function postRequest(e){
e.preventDefault();
const params = {
fName: document.querySelector('#name').value,
fAddress: document.querySelector('#address').value,
fComment: document.querySelector('#comment').value,
};
var xhr = new XMLHttpRequest();
xhr.open('POST', 'addRequest.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function(){
console.log(this.responseText);
}
xhr.send(params);
}
</script>
</body>
Here's the PHP code:
require_once 'Database.php';
var_dump($_POST); // returns `array(0) {}`
if (isset($_POST['nameSubmit'])) {
var_dump($_POST); // shows no response
$r = $_POST['fName'];
$o = $_POST['fAddress'];
$p = $_POST['fComment'];
$query = "INSERT INTO user_request(name, address, comment) VALUES(?,?,?)";
$stmt = $db->prepare($query);
$insert = $stmt->execute([$r, $o, $p]);
if($insert){
echo 'Success';
}else{
echo 'Error';
}
}

I believe the post parameter nameSubmit does not exsist.
Use the var_dump() function for dump all $_POST
From my prespective, the only parameter given was
fName
fAddress
fComment
Why not check for request method instead?
This is better than checking if a variable exsisted or not.
You can do the checks for required parameter later after you're sure this is a POST request.
if($_SERVER['REQUEST_METHOD'] === 'POST'){
// Do whatever you want when POST request came in
}
UPDATE :
Here is the answer you wanted!
<form id="requestForm">
<input type="text" name="fName" id="name">
<input type="text" name="fAddress" id="address">
<input type="text" name="fComment" id="comment">
<button onclick="sendData();" type="button">Submit</button>
</form>
<div id="testdiv"></div>
<script>
function sendData(){
var data = new FormData();
data.append('fName', document.getElementById("name").value);
data.append('fAddress', document.getElementById("address").value);
data.append('fComment', document.getElementById("comment").value);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'test.php', true);
xhr.onload = function () {
if(xhr.status !== 200){
// Server does not return HTTP 200 (OK) response.
// Whatever you wanted to do when server responded with another code than 200 (OK)
return; // return is important because the code below is NOT executed if the response is other than HTTP 200 (OK)
}
// Whatever you wanted to do when server responded with HTTP 200 (OK)
// I've added a DIV with id of testdiv to show the result there
document.getElementById("testdiv").innerHTML = this.responseText;
};
xhr.send(data);
}
</script>
</body>
The PHP code :
<?php
if($_SERVER['REQUEST_METHOD'] === 'POST'){
var_dump($_POST);
}else{
header('HTTP/1.0 403 Forbidden');
}
?>
To add another field, add another data.append function below data var.
The submit button MUST BE CLICKED. To allow the use of enter, add an event listener for it!.
What it looks like on my end : https://image.ibb.co/gfSHZK/image.png
Hope this is the answer you wanted.

Two issues:
1.) Params not sent properly/at all because lack of serialization. When you use form content-type your params object need to be in a particular format name=value&name2=value2. So to facilitate that you need to transform your ojbect using something like:
function getReadyToSend(object) {
var objList = [];
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
objList.push(encodeURI(prop + '=' + object[prop]));
}
}
return objList.join("&");
}
So your sending becomes: xhr.send(getReadyToSend(params));
2) Your php is expecting the submit button to be sent. if (isset($_POST['nameSubmit'])) {
You don't have a variable being sent called nameSubmit you can fix this by either including it or check that each variable is set instead. I would suggest the latter that way you can error handle should 1 or more are not passed.
Suggestion: Update your onload to check status:
if (xhr.status === 200)
{
console.log(xhr.responseText);
}
else if(xhr.status !== 200)
{
console.log('Request failed. Returned status of ', xhr.status);
}
Example fiddle: http://jsfiddle.net/qofrhemp/1/, open network tab and inspect the call you will now see the params in form data for the call that fires when submit clicked.

Related

Ajax Vanilla JS - ajax async continuing without waiting for readyState 4, status 200

TLDR: I would like to wait for the 1st request to be done, before continuing to the 2cnd etc.
Hello,
I am currently working on a HotSpot page. The user needs to input his email, and Voila! he gets internet access.
The thing that is SUPPOSED to happen in the background, is that when the user inserts his email and presses send;
an AJAX async POST is made to the router, with username and password,
then the js/html page waits for the readyState === 4 (DONE) response from the router,
an AJAX async POST is made to a server on a different network (which requires the user to have internet connection), which sends the users email,
then the js/html page waits for the DONE response
the user is redirected.
Thats basically what should happen. What is actually happening, is that the JS does not wait for the readyState === 4 and Status === 200. Once the user clicks Submit, he is redirected right away.
I can't use JQuery, as the router (Mikrotik) is using $ for it's own purpose.
After inspecting the network with the F12 tool, I can see that the POST to router has a status of 200, and is carrying the correct Parameters (username=HSuser&password=SimpleUserPassword) and I can see that the POST to the server has a status of 200 and also has the correct Parameters (email address ie: Email=Ba%40loo.ns).
I guess my JS code is somehow wrong, as it does not wait.
Also, for some reson after fiddling with the code, no more emails are inserted into the Database (they were before, don't know what the is problem now.)
Below is the current code. I'll also post a previous version (which also didn't work) in case someone can spot the problem there.
In case anyone requires any additional information, let me know.
Thank you.
Edit 3.:
I continued to read Stack Overflow and I've stumbled onto this piece of information...
The server is responsible for providing the status, while the user agent provides the readyState.
Is this done server side automatically, or do I need to implement it somehow?
Edit 1.:
I tried console log here
if (xhr.readyState === DONE){
console.log("XHR1" + xhr.readyState);
console.log("XHR1" + xhr.status);
if (xhr.status === OK){
and here
if (xhr2.readyState === DONE){
console.log("XHR2" + xhr2.readyState);
console.log("XHR2" + xhr2.status);
if (xhr2.status === OK){
and I only got XHR1 (XHR14 and XHR1200), I didn't get anything from XHR2.
Edit 2.:
Tried replacing onreadystatechange with onload, still does the same thing.
Current HTML code:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html" />
<meta charset="utf-8" />
<title>HotSpot</title>
</head>
<body>
<!-- Email form which is saved into the DB -->
<form accept-charset="utf-8" name="mail" onsubmit="return false;" method="post" id="mail">
<h1>Hotspot</h1>
<h2>To gain internet access, enter your email.</h2>
<br />
<input type="text" id="email" name="email" autofocus="autofocus" />
<br />
<input type="submit" value="Submit" id="submit_ok" name="submit_ok" /> <br />
</form>
<script type="text/javascript">
document.getElementById("submit_ok").addEventListener("click", SendAjax);
function SendAjax() {
var email = document.getElementById("email").value;
console.log(email);
// Check if fields are empty
if (email=="") {
alert("Please enter your email.");
}
// AJAX code to submit form
else{
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://router/login', true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
xhr.onreadystatechange = function () {
var DONE = 4;
var OK = 200;
if (xhr.readyState === DONE){
if (xhr.status === OK){
var xhr2 = new XMLHttpRequest();
xhr2.open('POST', 'http://server/insertDB.php', true);
xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
var useremail = document.getElementById("email").value;
xhr2.onreadystatechange = function () {
if (xhr2.readyState === DONE){
if (xhr2.status === OK){
location.href = "http://server/redirected.html";
}
}
}
}
xhr2.send("Email="+encodeURIComponent(useremail));
}
}
xhr.send("username=HSuser&password=SimpleUserPassword");
}
};
</script>
</body>
</html>
Current PHP code:
<?php
require ('connect.php');
$clean_email = "";
$cleaner_email = "";
if(isset($_POST['email']) && !empty($_POST['email'])){
//sanitize with filter
$clean_email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
//sanitize with test_input
$cleaner_email = test_input($clean_email);
//validate with filter
if (filter_var($cleaner_email,FILTER_VALIDATE_EMAIL)){
// email is valid and ready for use
echo "Email is valid";
//Email is a column in the DB
$stmt = $DB->prepare("INSERT INTO addresses (Email) VALUES (?)");
$stmt->bind_param("s", $cleaner_email);
$stmt->execute();
$stmt->close();
} else {
// email is invalid and should be rejected
echo "Invalid email, try again";
}
} else {
echo "Please enter an email";
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
$DB->close();
?>
Previous HTML/JS code:
function SendAjax() {
var email = document.getElementById("email").value;
console.log(email);
// Check if fields are empty
if (email=="") {
alert("Please enter your email.");
}
// AJAX code to submit form
else{
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://router/login', true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
xhr.onreadystatechange = function () {
var DONE = this.DONE || 4;
if (xhr.readyState === XMLHttpRequest.DONE){
var xhr2 = new XMLHttpRequest();
xhr2.open('POST', 'http://server/insertDB.php', true);
xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
var useremail = document.getElementById("email").value;
xhr2.onreadystatechange = function () {
var DONE = this.DONE || 4;
if (xhr2.readyState === XMLHttpRequest.DONE) {
location.href = "http://server/redirected.html";
}
};
xhr2.send("Email="+encodeURIComponent(useremail));
}
}
xhr.send("popup=true&username=HSuser&password=SimpleUserPassword");
}
}
If it makes your life easier (and it WILL), you can put jQuery into no conflict mode.
<!-- Putting jQuery into no-conflict mode. -->
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script>
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
$j(document).ready(function() {
$j( "div" ).hide();
});
// The $ variable now has the prototype meaning, which is a shortcut for
// document.getElementById(). mainDiv below is a DOM element, not a jQuery object.
window.onload = function() {
var mainDiv = $( "main" );
}
</script>
https://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/
Then you can make your AJAX call, and the stuff that should wait can go in the success function:
$j.ajax({
url: '/your-form-processing-page-url-here',
type: 'POST',
data: yourVariables,
mimeType: 'multipart/form-data',
success: function(data, status, jqXHR){
alert('Hooray! All is well.');
console.log(data);
console.log(status);
console.log(jqXHR);
},
error: function(jqXHR,status,error){
// Hopefully we should never reach here
console.log(jqXHR);
console.log(status);
console.log(error);
}
});

$_POST not returning a value

I've been searching for an answer to this for several days now, but if I missed the answer in another post, let me know.
I'm trying to get into Ajax, so I have a very simple form in my index.php, with separate php and javascript files:
index.php
<div id="ajax-test">
<form action="ajax/ajax.php" method="POST">
<textarea name="someText" id="some-text" placeholder="Type something here"></textarea>
<button type="button" onclick="loadDoc()">Submit</button>
</form>
<div id="ajax-text"></div>
</div>
main.js:
function getXMLHttpRequestObject() {
var temp = null;
if(window.XMLHttpRequest)
temp = new XMLHttpRequest();
else if(window.ActiveXObject) // used for older versions of IE
temp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
return temp;
}// end getXMLHttpRequestObject()
function loadDoc() {
var ajax = getXMLHttpRequestObject();
ajax.onreadystatechange = function() {
if(ajax.readyState == 4 && ajax.status == 200) {
document.getElementById('ajax-text').innerHTML = ajax.responseText;
console.log(ajax.responseText);
}
};
ajax.open("POST", "ajax/ajax.php", true);
ajax.send();
}
ajax.php:
<?php
print_r('\'' . $_POST['someText'] . '\' is what you wrote');
?>
Whenever I try to print, it prints: " '' is what you wrote " - what am I missing/not doing/doing incorrectly that isn't allowing me to access the content of someText? I've changed my naming convention, swapped from single quote to double quote, tried GET instead of POST, but nothing worked.
You can try to set a header request and also put the data inside the send. Here an example as like as-
ajax.open("POST", "ajax/ajax.php", true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.send("someText="+document.getElementById('some-text').value);
This is probably beacuse of the error
Undefined index: someText in C:\xampp\htdocs\ssms\sandbox\ajax\ajax.php on line 3
You had a couple of issues with your code which i don't have time to list out now. This should work fine, plus i used the onkeyup() function to display the text live without even clicking on the submit button.
The Index File
<div id="ajax-test">
<form method="POST" onsubmit="return false;">
<textarea onkeyup="loadDoc()" name="someText" id="someText" placeholder="Type something here"></textarea>
<button type="button" onclick="loadDoc()">Submit</button>
</form>
<div id="ajax-text"></div>
</div>
<script type="text/javascript" src="main.js"></script>
The Main Javascript file
function _(x) {
return document.getElementById(x);
}
function ajaxObj ( meth, url ) {
var x = new XMLHttpRequest();
x.open( meth, url, true );
x.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
return x;
}
function ajaxReturn(x){
if(x.readyState == 4 && x.status == 200) {
return true;
}
}
function loadDoc() {
var someText = _("someText").value;
var ajax = ajaxObj("POST", "ajax/ajax.php");
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
_('ajax-text').innerHTML = ajax.responseText;
console.log(ajax.responseText);
}
}
ajax.send("someText="+someText);
}
The PHP AJAX File
if(isset($_POST['someText'])){
$someText = $_POST['someText'];
echo "\"$someText\"" . ' is what you wrote';
exit();
} else {
echo "An error occured";
exit();
}

error while sending POST request via ajax

I want to send a post request and get an echo from a php file. But i cannot find my mistake, always get a notice:undefined index...
please not jquery...
<form id="register" method="POST" action="register-action.php">
<input type="text" name="first_name" placeholder="Onoma"><br>
<input type="text" name="last_name" placeholder="Epitheto"><br>
<input type="text" name="mail" placeholder="E-mail"><br>
<input type="password" name="pass" placeholder="password"><br>
<select name="eidikotita_id">
<?php while($eid = $eidikotites->fetch( PDO::FETCH_ASSOC )):
echo "<option value={$eid['id_eidikotitas']}>{$eid['titlos']}</option>";
endwhile; ?>
</select>
<input type="submit" value="Register"><br>
</form>
///////////////////////////////////////////////////////////////
var mail_input = document.querySelector("#registerinput[name='mail']").value;
alert(mail_input);
document.querySelector("#register input[name='first_name']").focus();
document.querySelector("#register input[name='mail']").onblur = function() {
var request = new XMLHttpRequest();//instantiate an XMLHttpRequest object
request.open("POST", "register-action.php", true);//Specifying the Request
request.setRequestHeader("Content-Type", "text/plain");//POST requests,for example, need a “Content-Type” header
request.send(mail_input);//specify the optional request body. GET requests never have a body, so you should pass null or omit the argument.
};
/////////////////////////////////////////////////////////////////////////////
<?php
echo $_POST['mail'];
?>
Just print_r() POST data to see what is the problem.
xhr.send() should look like this: xhr.send('mail=' + encodeURIComponent(email)) because you want $_POST['mail']. Also there is a problem with your selector which should be "#register input[name='mail']".
document.querySelector("#register input[name='first_name']").focus();
document.querySelector("#register input[name='mail']").onblur = function() {
var mail_input = document.querySelector("#register input[name='mail']").value;
var request = new XMLHttpRequest();//instantiate an XMLHttpRequest object
request.open("GET", "register-action.php?mail="+mail_input, true);//Specifying the Request
request.setRequestHeader("Content-Type", "text/plain");//POST requests,for example, need a “Content-Type” header
request.send(encodeURIComponent(mail_input));//specify the optional request body. GET requests never have a body, so you should pass null or omit the argument.
//////send succcess
if (request.readyState === 4 && request.status === 200) {
request.onreadystatechange = function(){
console.log(request.responseText);
}
}
};

JavaScript/AJAX is saying "undefined" when it should show a picture

On my register page, I am trying to set it up so that when somebody enters a username into the username box, it will either show a green check mark if the username doesn't exist, or a red 'X' if the username already exists. When the page loads though (the body tag is <body on_load="process();">), it doesn't come up with a picture, it comes up with the word "undefined".
JavaScript code:
var xmlHttp = createXmlHttpRequestObject();
//Create object for function
function createXmlHttpRequestObject(){
var xmlHttp;
//Check if IE
if(window.ActiveXObject){
try{
//Setting variable equal to object for IE
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
//Can't set variable equal to something
xmlHttp = false;
}
}else{
//Anything not IE
try{
//Want to use this object if not IE
xmlHttp = new XMLHttpRequest;
}catch(e){
//Can't set variable equal to something
xmlHttp = false;
}
}
//If couldn't set object
if(!xmlHttp){
//Tell people that JS couldn't create the object (new XMLHttpRequest or ActiveXObject)
alert("Couldn't create an object with JavaScript!");
}else{
//Return object
return xmlHttp;
}
}
//Use this attribute for body tag: <body onload="process()">
function process(){
/*readyState:
0: request not initialized
1: server connection established
2: request received
3: processing request
4: request finished and response is ready
*/
try{
//Check if ready to communicate
if(xmlHttp.readyState==0 || xmlHttp.readyState==4){
//<input type="text" id="userInput" /> relates to this
//Set variable to value they typed in
username = encodeURIComponent(document.getElementById("register_name").value);
//Creates request to send to server
//Need PHP file, GET would be in PHP file, also can be POST, etc.
xmlHttp.open("POST","functions/check_used.php",true);
//Doing something to make it pretend like it's a form, for POST
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//Handle server response when server responds to the request
xmlHttp.onreadystatechange = handleServerResponse;
//Send request (this is used for POST, use null when using GET)
xmlHttp.send("username="+username);
}else{
//Not ready to communicate, wait for 1 second and try again
setTimeout('process()',1000);
}
}catch(e){
//Something doesn't work, tell them what happened
alert(e.toString());
}
}
//When response received, tells what to do with it
function handleServerResponse(){
//Response done communicating
if(xmlHttp.readyState==4){
//Communication went OK
if(xmlHttp.status==200){
//Put response into variable
xmlResponse = xmlHttp.responseXML;
//Get document element
xmlDocumentElement = xmlResponse.documentElement;
//Get data from XML file
message = xmlDocumentElement.firstChild.data;
//Access document, put it in element on page, innerHTML is stuff shown on webpage
document.getElementById("checkedUser").innerHTML = message;
//Pause 1 second before communicating with server again
setTimeout('process()',1000);
}else{
//There was an error with data
alert('Something went wrong!');
}
}
}
On the register page, I have an input box with the div next to it:
<input type="text" id="register_name" name="username" /><div id="checkedUser"></div>
Finally, I have the PHP file that it is posting to:
<?php
require_once('../includes/db.php');
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
echo '<username>';
$check_username = $db->prepare("SELECT COUNT(*) FROM `users` WHERE `username` = :username");
$check_username->bindValue(":username",$_POST['username'],PDO::PARAM_STR);
$check_username->execute();
$check_username = $check_username->fetch();
if($check_username[0] == 0){
echo '<img src="images/success.png" />';
}else{
echo '<img src="images/error.png" />';
}
echo '</username>';
?>
I have tried troubleshooting it, but I couldn't figure out what was wrong.
Listen for keystrokes in input, and check username when the input changes :
$(function() {
$('#register_name').keyup(function() {
$.ajax({
type: 'POST',
url : 'functions/check_used.php',
data: {username : this.value},
success: function(result) {
$('#checkedUser').html(result);
}
});
});
});
And there's no need to return XML:
<?php
require_once('../includes/db.php');
header('Content-Type: text/html');
$check_username = $db->prepare("SELECT COUNT(*) FROM `users` WHERE `username` = :username");
$check_username->bindValue(":username",$_POST['username'],PDO::PARAM_STR);
$check_username->execute();
$check_username = $check_username->fetch();
if($check_username[0] == 0){
echo '<img src="images/success.png" />';
}else{
echo '<img src="images/error.png" />';
}
?>
if(xmlHttp.readyState==0 || xmlHttp.readyState==4){
should be
if(xmlHttp.readyState== 4 && xmlHttp.status == 200){

Can I test XMLHttpRequest() in SDK with localhost?

The following code does not seem to work because when I try to get the "chooser" in Google App Engine (Python) it is undefined:
chooser = self.request.get("chooser")
self.response.out.write("chooser: %s " % chooser)
#returns "chooser:" without any value
Is this valid javascript?
var formData = new FormData();
formData.append("chooser", user);
var xhr = new XMLHttpRequest();
//is it ok to test this with localhost?
xhr.open("POST", "http://localhost:8086/g/choicehandler", true);
xhr.onreadystatechange = function (aEvt) {
if (xhr.readyState == 4 && xhr.status == 200){
console.log("request 200-OK");
}
else {
console.log("connection error");
}
};
xhr.send(formData);
Is the problem with the XHR call or with the App?
UPDATE
I am including the code in /choice to clarify what "chooser" is as per Daniel Roseman's comment:
In /choice handler I have writeToStorage() which assigns a username in the form user1, user2 and so on, and writes that to localStorage.
After writing user name to localStorage I also need to write it to database in the app, and I use xhr to send it to /g/choicehandler handler.
So, "chooser", I believe is a string, made of
var user = "user" + count;
I copy /choice handler below:
class Choice(webapp.RequestHandler):
def get(self):
self.response.out.write("""
<html>
<head>
<script type="text/javascript">
var count = 0;
function writeToStorage()
{
var user = "user" + count;
count++;
localStorage.setItem("chooser", user);
var formData = new FormData();
formData.append("chooser", user);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8086/g/choicehandler", true);
xhr.onreadystatechange = function (aEvt) {
if (xhr.readyState == 4 && xhr.status == 200){
console.log("request 200-OK");
}
else {
console.log("connection error");
}
};
xhr.send(formData);
};
</script>
</head>
<body>
<form name="choice_form" id="choice_form" action="/g/choicehandler" method="post" onsubmit="writeToStorage()">
<textarea name="choice" rows="7" cols="50"></textarea><br />
<input type="submit" value="submit your choice">
</form>
</body>
</html>""")
UPDATE 2
I noticed in the logs that the text from textarea which is "choice" and "chooser" which is sent with xhr are not shown together, one of them is always without a value:
INFO ... chooser: user0 choice:
INFO ... chooser: choice: abcd
INFO ... chooser: user0 choice:
INFO ... chooser: choice: efgh
This is the code for the above log:
chooser = self.request.get("chooser")
choice = self.request.get("choice")
logging.info("chooser: %s choice: %s" % tuple([chooser, choice]))
new_choice = User(
choice = choice,
owner = chooser)
new_choice.put()
so in the datastore i see "chooser" and "choice" written in 2 different rows. What am I doing wrong?
Actually you're submitting the form twice. Once in writeToStorage via AJAX and also with the normal way with the the form. You will have to change two things.
writeToStorage has to return false as the last action
Change your onsubmit to onsubmit="return writeToStorage()"
This way you will prevent the default submission of your form, as it will be done via AJAX in writeToStorage

Categories

Resources