I'm sure this is probably me being stupid but I want to confirm this issue. I am building a windows 8 app and loading in data from a mysql server and I can't seem to fix this issue. From a bit of reading I am guessing the issue is that the code is executing before the json request is this correct and is there a way to resolve it. The return is there because it is inside a function which returns the data and then displays it. The "SampleItems[0]" displays perfectly but the stuff inside the json wont but a console log shows it is getting data from the server. Thanks in advance for any help!
var sampleItems = [];
sampleItems[0] = { group: sampleGroups[count], title: "New Image", subtitle: "", description: "", content: "", backgroundImage: "/images/add.png" };
//this code calls to our cloud based service which gets the data which is needed and returns it in a JSON object back for this to handle
$.getJSON('http://pumpstationstudios.com/tumapics/services/getimages.php', function (data) {
var service_url = 'http://pumpstationstudios.com/tumapics/';
var count = 1;
images = data.items;
$.each(images, function (index, image) {
image.image = service_url + image.image;
sampleItems[count] = { group: sampleGroups[count], title: "Hello", subtitle: "", description: "", content: "", backgroundImage: image.image };
count++;
});
});
return sampleItems;
As it happens, I answered a similar question javascript code execution and ajax async some hours ago
Essentially, what happens is
$.getJSON('http://.../getimages.php', function(data) {
// process data
});
// this runs *before* "process data"
return sampleItems;
This means, you return sampleItems, before it is filled by the getJSON callback function.
To solve this problem, you must do your processing in the callback function.
Related
I'd like to create a group chat, and would like all the messages and there matching usernames to be stored in a JSON file.
However, this looks quite hard to do without using node.js or MySQLi.
As you can see below, i can already read the JSON and display it in "chat-wrap". The problem is to add messages to the json file with PHP and/or AJAX, and update the HTML automatically.
The input is where the user types the message, and I assume i'll have to use JS to notice when ENTER is pressed, because i do not want to use a form (unless you can convince me otherwise).
My HTML:
<div class="col chat">
<div class="messages" id="chat-wrap">
<?php include "chat/chat_process.php"; ?>
</div>
<input maxlength='100' type="search" name="type_message" id="type_message" placeholder="Type a message...">
</div>
JSON example:
{
"message_list": [{
"uname": "User 1",
"text": "Hello everyone!"
},
{
"uname": "User 2",
"text": "Hey!"
},
{
"uname": "User 1",
"text": "Hello!"
}
]
}
I've already tried messing with the following code, but i'm new to JS and AJAX so ofcourse the code below didn't really work out...
$("#type_message").keypress(function (event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == '13') {
var msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
var name = 'Username';
var data = {
uname: name,
text: msg
};
$.ajax({
type: "POST",
url: "chat.php",
data: {
data: JSON.stringify(data)
},
dataType: "json",
success: function (response) {
// display chat data stored in text file
}
});
}
});
When a message is typed and entered, it should add to the JSON file and display it live on every users screen.
Please excuse me if i forgot to clarify anything, i'm kinda new to stackoverflow and i'm not sure what y'all pros expect to know...
Thanks!
I added a bit of code to your success function as a result you should be able to add the new text dynamically to your html and also saves the changes to your file messages.json.
$("#type_message").keypress(function(event) {
let keycode = event.keyCode ? event.keyCode : event.which;
if (keycode == "13") {
let msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
let name = "Username";
let data = {
uname: name,
text: msg
};
currentjson.push(data); // Also added one global variable which allows you to push the new data into the old json array.
$.ajax({
type: "POST",
url: "chat/chat.php", // I changed the url slightly since i put the php files in another directory
data: {
data: JSON.stringify(currentjson)
},
dataType: "json",
success: function(response) {
$(".chat").html(""); // Reset the html of the chat
addNodes(response); // Add the new Data to the chat by calling addNodesfunction
},
error: function(err) {
console.log(err);
}
});
}
Here is the php file that saves the json :
<?php
$file = fopen('messages.json','w');
$data = $_POST['data'];
fwrite($file,$data);
fclose($file);
echo $data; // return the new data set
addNodes function :
function addNodes(messages) {
for (let message of messages) {
const chatDiv = $(".chat");
const user = document.createElement("h3");
const content = document.createElement("p");
user.textContent = message.uname;
content.textContent = message.text;
chatDiv.append(user);
chatDiv.append(content);
}
}
I also changed your json to make it a little easier to loop through : (json example)
[
{ "uname": "User 1", "text": "Hello everyone!" },
{ "uname": "User 2", "text": "Hey!" },
{ "uname": "User 1", "text": "Hello!" }
]
Finally the whole client.js code looks like this :
$(document).ready(() => {
let currentjson = undefined;
$.ajax("chat/chat_process.php", { // This gets the file the first time the user opens the page
success: function(data) {
const messages = JSON.parse(data);
currentjson = messages;
addNodes(currentjson);
},
error: function() {
alert("There was some error performing the AJAX call!");
}
});
$("#type_message").keypress(function(event) {
let keycode = event.keyCode ? event.keyCode : event.which;
if (keycode == "13") {
let msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
let name = "Username";
let data = {
uname: name,
text: msg
};
currentjson.push(data); // Also added one global variable which allows you to push the new data into the old json array.
$.ajax({
type: "POST",
url: "chat/chat.php",
data: {
data: JSON.stringify(currentjson)
},
dataType: "json",
success: function(response) {
$(".chat").html(""); // Reset the html of the chat
addNodes(response); // Add the new Data to the chat by calling addNodesfunction
},
error: function(err) {
console.log(err);
}
});
}
});
});
function addNodes(values) {
for (let message of values) {
const chatDiv = $(".chat");
const user = document.createElement("h3");
const content = document.createElement("p");
user.textContent = message.uname;
content.textContent = message.text;
chatDiv.append(user);
chatDiv.append(content);
}
}
But the final tasks that remains is that to display the new data to all the users currently using the website. To be able to do that i think you can use setInterval for like every 5 seconds and call a function which will detect if messages.json was changed by any user and then updates accordingly.
I hope my answers was useful :)
I believe you can, if you register the data into a variable or a text file in the server side.
You can trigger actions using server-sent events
https://www.w3schools.com/html/html5_serversentevents.asp
PS: someone has done it here:
https://www.developphp.com/video/JavaScript/Server-Sent-Events-Simple-Chat-Application-Example
Update sessions for chat directly
Advantages: It's much faster than passing files, storing information in DB. It's far less resource intensive. It avoids a lot of middle-man systems for handling the chat. It doesn't leave you holding onto increasing amounts of data. It avoids a LOT of legal issues with holding onto user data (because you aren't).
Disadvantages: You -have- to make sure it's secure in some way that best fits your use case. Also, troubleshooting session switching if something goes wrong can sometimes be a pain in the arse. Not useful if you're wanting to sell user data.
In php, store the information in session data. Then, fire off a child process (unconnected with the current session) that loads the session of the other user, and updates the other user's session data, having each session holding a variable in their session that stores the session IDs of the other users in the chat.
Mychat.php
$message = "" // Whatever's said
$groupids = implode(",", $other_users_ids); //Whatever your group's ids are.
$_SESSION["group_chat_users"]["my_id"] = session_id();
$_SESSION["my_chat_log"][]= $message;
exec("php my_group_update.php $groupids $_SESSION["group_chat_users"]["my_id"] $message");
my_group_update.php
$groupids = explode(",", $argv[1]);
$calling_user = $argv[2];
$message = $argv[3];
foreach ($groupids as $userid){
session_start($userid);
$_SESSION["my_chat_log"][]= $message");
}
As for outputing the JSON, it's as simple as:
fetch_log.php
header('Content-Type: application/json');
echo json_encode($_SESSION["my_chat_log"]);
Letting the user have their JSON log without it ever having to touch your Harddrive (or, alternatively, you can write it to your harddrive if you prefer.)
Notice: As should go without saying (but apparently needs to be said) As always, validate your inputs. Not doing so will leave you vulnerable to injection.
Ways suggestions on ways to prevent injection:
Have $message be a temporary file name written in Mychat.php and pulled in my_group_update.php
Convert $message to a hex string in Mychat.php and converted back in my_group_update.php
Alter my_group_update to pull the message from the first user's Session before switching to other users where it gets pasted.
Alert mychat to not include any variables other than the group_id in the exec call. Then have my_group_update just take the group ID, and cycle through all the shared chat session arrays, and find all new values, and update all the chats with it <---(probably the best).
Spin up a temporary very tiny VM that only handles the 1 chat, (maybe running with alpine linux or similar for a very small size that then self-destructs when the chat finishes.) This would be much higher overhead, but way more secure than anything else you'll even consider doing.
The list goes on.
So I'm grabbing the state of a jquery date picker and a dropdown select menu and trying to send those two variables to another php file using AJAX.
var_dump($_POST);
results in this on the webpage:
array(0) {
}
BUT, when I look at the Net panel in Firebug, I can see the POST and GET urls and it shows the Post, Response, and HTML all showing the variables that I sent to the PHP file, but when dumping, it shows nothing on the page.
I've been looking through other similar issues on SO that has led me to changing the php.ini file to increase the post size and to updating my ajax call to use json objects and then parse through it on the php side.
Currently I'm just trying to get passing a string to work, and my code looks like this:
AJAX:
$("#submit_button").click(function() {
// get date if selected
var selected_date = $("#datepicker").datepicker("getDate");
// get show id if selected
var selected_dj = $("#show-list").val();
// put the variables into a json object
var json = {demo : 'this is just a simple json object'};
// convert to json
var post_data = JSON.stringify(json);
// now put in variable for posting
var post_array = {json : post_data};
$.ajax({
type: "POST",
url: template_dir + "/get-show-logs.php",
data: post_array,
success: function(){
alert("Query Submitted");
},
error: function(xhr, ajaxOptions, thrownError){
alert(xhr.status);
alert(thrownError);
}
});
// clear div to make room for new query
$("#archived-posts-container").empty();
// now load with data
$("#archived-posts-container").load(template_dir + "/get-show-logs.php #get_logs");
});
Now this is the php that's running from the .load() call, and where I'm trying to access the $_POST variables:
get-show-logs.PHP:
<div id="get_logs">
<?php
if(isset($_POST["json"])){
$json = stripslashes($_POST["json"]);
$output = json_decode($json);
echo "im here";
var_dump($output);
// Now you can access your php object like so
// $output[0]->variable-name
}
var_dump(getRealPOST());
function getRealPOST() {
$pairs = explode("&", file_get_contents("php://input"));
$vars = array();
foreach ($pairs as $pair) {
$nv = explode("=", $pair);
$name = urldecode($nv[0]);
$value = urldecode($nv[1]);
$vars[$name] = $value;
}
return $vars;
}
?>
</div>
You can see that I'm trying just accessing the $_POST variable, and the isset check isn't passing, (the page isn't echoing "im here"), and then I'm also trying parsing through the input myself, and that is also empty.
the output on the page looks like this:
array(1){[""]=>string(0)""}
BUT, once again, the Firebug Net panel shows the following under the Response tab:
<div id="get_logs">
im hereobject(stdClass)#1 (1) {
["demo"]=>
string(33) "this is just a simple json object"
}
array(1) {
["json"]=>
string(44) "{"demo":"this is just a simple json object"}"
}
</div>
I'm not sure what could be causing the issue, the Firebug can see it, but the php file sees an empty array.
Now I'm very new at using ajax and $_POST and such, so if you read anything that you're not 100% sure about, don't assume that I know anything about it! Speak up! haha.
Also, I'm doing this with MAMP on Localhost, so I'm not sure if that leads to any issues.
Thanks for the help in advance!
You aren't using the response in your AJAX call currently. See this example which will output the returned response to the console.
$.ajax({
type: "POST",
url: template_dir + "/get-show-logs.php",
data: post_array,
success: function(response){
console.log(response);
},
error: function(xhr, ajaxOptions, thrownError){
alert(xhr.status);
alert(thrownError);
}
});
Success
Type: Function( Anything data, String textStatus, jqXHR jqXHR )
A function to be called if the request succeeds. The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter or the dataFilter callback function, if specified; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object.
-http://api.jquery.com/jquery.ajax/
Also this might be a good page to read more about jQuery and AJAX, https://learn.jquery.com/ajax/jquery-ajax-methods/.
I'm building a webpage where the user can 'sign' some agreements and view signed and new (unsigned) agreements. For this the webpage uses the 2 functions in the code below to get relevant information from the database and then build the webpage. Unfortenately, when -and only when- the php file (process.php) returns a variable nrofagreements=0, the console shows an error for the get function;for any other values nrofagreements>0 no error occurs - see the console log below. I also checked (with Netbeans debugger) that process.php works properly - see json output below for nrofagreements=0- but I still suspect that the error must be in this php file(?) Any idea what goes wrong and how to fix it?
A1. jquery code:
$(document).ready(function(){
function NewAgreements(){
var jqxhr = $.get( "process.php", //get all
{ command: "getnewagreements", val1: "", val2: "" },
function(msg) {
},
"json"
).done(function(msg) {
console.log( "NewAgreement. $.get result: second success" );
//some code here to build the form based on msg from $.get()
form = buildNewAgreementsform(msg); //build form with supplier agreements and related products
$("#wrapper").append(form);
})//.done(function()
.fail(function() {
console.log( "NewAgreement. $.get result: error" );
})//.fail(function()
.always(function() {
console.log( "NewAgreement. $.get result: finished" );
});//$.get(
}//function getX()
//used by: tabs-agreements
NewAgreements();
function SignedAgreements(){
var jqxhr = $.get( "process.php", //get all
{ command: "getsignedagreements", val1: "", val2: "" },
function(msg) {
//var ecorp_eprodselectid;
},
"json"
).done(function(msg) {
console.log( "SignedAgreement. $.get result: second success" );
//some code to build the form based on the msg info from $.get()
form = buildSignedAgreementsform(msg); //build form with supplier agreements and related products
$("#wrapper-signedagreements").append(form);
})//.done(function()
.fail(function() {
console.log( "SignedAgreement. $.get result: error" );
})//.fail(function()
.always(function() {
console.log( "SignedAgreement. $.get result: finished" );
});//$.get( ",
}
SignedAgreements();
}); //$(document).ready
A2 simplified php code:
session_start();
$response_array = array();
$cmd = $_GET['command'];
switch($cmd){ //command handler
case 'getsignedagreements':
//some code here
$response_array['nrofagreements'] = $k;
if($response_array['nrofagreements'] == 0){
$response_array['status_general'] = 'success';
break;
}
//some code here
break;
case 'getsignedagreements':
//some code here
break;
default: //invalid command from webpage
$response_array['status_general'] = 'error';
break;//default
}//switch
$str = json_encode($response_array);
echo json_encode($response_array);
B. log console:
NewAgreement. $.get result: error
NewAgreement. $.get result: finished
SignedAgreement. $.get result: second success
SignedAgreement. $.get result: finished
C log json output for function NewAgreements:
"{"nrofagreements":0,"status_general":"success"}"
I don't have a specific fix for you, but I've got something which will help point you in the right direction...
System Design
One of the philosophies we hold dear is the idea that everything needs to do its own job in the most efficient way. The problem for most developers is they get confused with what each part of their application will do, and consequently try & do 5 jobs with one component
The reason I'm explaining this is because part of your question asked whether you should validate with JS or PHP. The answer is that you have to know which part of the system will do -- it looks like you're using PHP to validate whether the input is valid with the session, so I would suggest that you only handle the logic for that in the PHP file
Ajax
Personally, I would handle the response in your $.get command, but I would change to Ajax as my own preference:
$.ajax({
url: "process.php",
data: { command: "getnewagreements", val1: "", val2: "" },
success: function (msg) {
//handle validation in here
},
error: function(msg) {
//only fires when the URL can't be found etc
}
});
I've tested your code, found one illogical item in process.php (one single case is handled):
//...
case 'getsignedagreements':
//...
//...
case 'getsignedagreements':
//...
==> should be corrected to something like (handling two cases):
//...
case 'getnewagreements':
//...
//...
case 'getsignedagreements':
//...
Here is the example delete options I'm using using in a jqGrid. It works just fine and my serverside scripts are working perfectly. The records get deleted, but there is something that goes wrong after the response from the server is received.
// Del Options
{
mtype: "POST",
modal: true,
url: "/internal/backupmanagement/backupmanager/deleteMySQLDB",
reloadAfterSubmit: false,
onclickSubmit: function () {
var post = $("#grid_" + o.id).jqGrid("getGridParam", "postData");
var server = post.serverID;
$.openDialog("load", "Deleting old database entry. Please wait...");
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
var row = $("#grid_" + o.id).jqGrid("getRowData", selrow);
console.log("about to return", row, server);
return {
id: row.recid,
database: row.database,
server: server
};
},
afterSubmit: function (response, postdata) {
response = eval("(" + response.responseText + ")");
console.log(response);
return [true, "success"];
},
afterComplete: function (response, postdata, formid) {
response = eval("(" + response.responseText + ")");
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
$("#grid_" + o.id).jqGrid("delRowData", selrow);
if (response.error == 0) {
$.openDialog("info", "Successfully deleted " + postdata.database + ".");
} else {
$.openDialog("info", "And error occured - " + response.msg + ".");
}
}
}
I get the following error before the afterComplete event is fired in the grid :
Uncaught TypeError: Object [object Array] has no method 'split'
So it seems something is being returned as an object when it was expecting a string. I'm not sure if my response from the server is formatted correctly and I wasn't able to find any expected response in the documentation either.
* UPDATE *
Server-side code as requested. I've just included the controller function that interacts with the jqGrid, the rest is working and happening further on in the application.
function deleteMySQLDB()
{
if (IS_AJAX) {
if (($this->Application->deleteMySQLDBData(
$_POST["id"],
$_POST["database"],
$_POST["server"]
)) === false) {
echo json_encode(
array(
"error" => 1,
"msg" => "Failed Deleting record from database: "
.$this->Application->error
)
);
return false;
}
echo json_encode(
array(
"error" => 0,
"msg" => "success"
)
);
return true;
} else {
header("Location: /");
}
}
I hope this helps to see what I'm currently returning to the grid.
* UPDATE *
What I have done is changed the source in the jqGrid plugin to include a toString() on the value before preforming the split.
On line 331 of jquery.jqGrid.min.4.3.1 :
var A=[];A=H.split(",");
Changed to :
var A=[];A=H.toString().split(",");
It seemed like a harmless change in the grand scheme of things and avoids arrays to be attempted to get split. Thanks a lot for the help guys. You certainly pointed me in the right place to start looking, Oleg!
Let's suppose that the origin of the described error is the code of your afterComplete callback. I think that you are using it in a wrong way. I don't understand some parts of the code, the part (testing of response.error) should be moved in afterSubmit.
The main problem will be clear if you examine the lines of code where afterComplete callback will be called. It will be executed inside of setTimeout with 0.5 sec delay. At the time new data in the grid can be loaded (or could be loading). So it would be wrong to use methods like delRowData and the value of selrow could be changed now.
I would strictly recommend you additionally don't use eval function. Instead of the line
response = eval("(" + response.responseText + ")");
it will be correct to use
response = $.parseJSON(response.responseText);
The code of onclickSubmit callback could be improved if you would use the fact that this inside of the callback (like the most other callbacks o jqGrid) are initialized to DOM element of the grid. So to get selrow option of the grid you can use
var selrow = $(this).jqGrid("getGridParam", "selrow");
instead of
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
Another fact is onclickSubmit will be called by jqGrid with two parameters: options and postdata. The parameter postdata is rowid if you use don't use multiselect: true. In case of usage of multiselect: true the value of postdata parameter of the callback can be comma separated list of rowids of the rows which will be deleted. So the usage of postdata is better as the usage of selrow.
I"m making a good guess since you didn't include your server side code.
On the server you can return something like:
return Json(new { success = false, showMessage = true, message = "Error - You can't have a negative value", title = "Error" });
Then on your client you can have something to display a message (in this example if there was an error)
afterComplete: function (response) {
var DialogVars = $.parseJSON(response.responseText); //parse the string that was returned in responseText into an object
if (!DialogVars.success || DialogVars.showMessage) {
showDialog($('#Dialog'), DialogVars.message, DialogVars.title);
}
} //afterComplete
I am attempting to create a simple comment reply to posts on a forum using the AJAX function in jQuery. The code is as follows:
$.ajax({type:"POST", url:"./pages/submit.php", data:"comment="+ textarea +"& thread="+ currentId, cache:false, timeout:10000,
success: function(msg) {
// Request has been successfully submitted
alert("Success " + msg);
},
error: function(msg) {
// An error occurred, do something about it
alert("Failed " + msg);
},
complete: function() {
// We're all done so do any cleaning up - turn off spinner animation etc.
// alert("Complete");
}
});
Inside the submit.php file I have this simple if->then:
if(System::$LoggedIn == true)
{
echo "Yes";
} else {
echo "No";
}
This call works on all other pages I use on the site, but I cannot access any of my variables via the AJAX function. I've tested everything more than once and I can echo back whatever, but anytime I try to access my other PHP variables or functions I just get this error:
Failed [object XMLHttpRequest]
Why am I unable to access my other functions/variables? I must submit the data sent into a database inside submit.php using my already made $mySQL variable, for example. Again these functions/variables can be accessed anywhere else except when I call it using this AJAX function. After hours of Googling I'm just spent. Can anyone shed some light on this for me? Many thanks.
The PHP script that you have only returns a single variable. Write another script that that returns JSON or if you are feeling brave XML. below is a quick example using JSON.
In your javascript
$.ajax({
type: 'GET'
,url: '../pages/my_vars.php'
,dataType: 'json'
,success: function(data){
// or console.log(data) if you have FireBug
alert(data.foo);
}
});
Then in the php script.
// make an array or stdClass
$array = array(
'foo' => 'I am a php variable'
,'bar' => '... So am I'
);
// Encodes the array into JSON
echo json_encode($array);
First thing, you have a space in the Data Parameter String for the URL - will cause problems.
Secondly, your success and error functions are referencing a variable msg. It seems you are expecting that variable to be a string. So, the question then becomes - What is the format of the output your PHP script at submit.php is producing?
A quick read of the jQuery API suggests that, if the format of the response is just text, the content should be accessible using the .responseText property of the response. This is also inline with the response you say you are getting which states "Failed [object XMLHttpRequest]" (as you are trying to turn an XHR into a String when using it in an alert.
Try this:
$.ajax( {
type: "POST" ,
url: "./pages/submit.php" ,
data: "comment="+ textarea +"&thread="+ currentId ,
cache: false ,
timeout: 10000 ,
success: function( msg ) {
// Request has been successfully submitted
alert( "Success " + msg.responseText );
} ,
error: function( msg ) {
// An error occurred, do something about it
alert( "Failed " + msg.responseText );
} ,
complete: function() {
// We're all done so do any cleaning up - turn off spinner animation etc.
// alert( "Complete" );
}
} );