I have a page with some checkboxes and a submit button. I use AJAX to post the checkbox values to a PHP script, calc.php, run some calculations with the data and assign the result to a PHP session variable. I have another PHP script, json.php, that takes that session data and encodes it as JSON for the jquery to display in the div. My problem is I allow the user to set the amount of data sets they are going to submit, subnumber, and my display loop gets out of sync when the user changes the number of sets.
For example, if they start with 3 data sets, they submit them one by one by pressing #button. After the last set, if (count == max) runs and. Now they can do another calculation and change the number of data sets if they wish. If they change it to say 2, output goes to four instead of reseting to 1 and emptying #log.
$("#button").click(function() {
$.ajax({
type: "POST",
url: "calc.php",
data: $("form#checkboxes").serialize(),
success: function(data) {
if(document.getElementById('calc').checked) {
var max = checkboxes.subnumber.value;
var stop = Number(max) + 1;
count++;
output++;
$.getJSON('json.php', function(data) {
$.each(data, function(key, val) {
$('#log').append(output);
$('#log').append(val.result);
$('#log').append("</br>");
})
})
if (count == max){
count = 0;
$("#results").load('results.php')
}
if(output == stop) {
$("#log").empty();
output = 1;
}
}
}
})
}
I know it's something simple, but I have been trying to fix it for two hours now and can't figure out the problem. Everything else works perfectly, it's just the output counter that isn't done correctly.
You're running asynchronous calls into your JSON. If users are doing things so quickly that the calls are coming back out of order, the issue lies in there.
You've got two options:
Run all of your JSON synchronously (use async:false in your JSON calls)
Utilize a counter and only process events that are coming back on the current index.
Psuedo Code for #2:
var pCounter = 0;
function doSomeAjax()
{
pCounter++;
$.ajax('url',{
data:{count:pCounter}
success:function(data)
{
// your json should return the current counter index
if (data.counter != pCounter) return;
// execute normally.
}
});
}
Related
I am developing a desktop app which will store data offline but whenever the desktop gets a connection a php script should detect it (cron job) and upload it to the online server like this:
while(true){
if(connected == true){
// run code;
else{
// wait to get connection
}
}
Hi Zaki Muhammad Mulla,
I did some testing myself, and I came up with the following piece of code
Running the code snippets here won't work because this is a sandbox and there is no access to the localstorage here.
Make sure to include Jquery in your code
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous">
</script>
Then the actual function that will do the trick:
function processData(online){
if(online == true){
//My connection is online so I can execute code here
//If data is stored locally, read it and post it with an $.ajax POST
//I can loop through all the data and insert it per found row of data
for(var i=0, len=localStorage.length; i<len; i++) {
var key = localStorage.key(i);
var value = localStorage[key];
$.ajax({
type: 'POST',
url: 'PATH/TO/SCRIPT.php',
data: { column: key, value: value },
success: function(response) {
//The insert was succesful
content.html(response);
}
});
}
}else{
//Create your own loop here and fill data accordingly
for(i = 0; i < 12; i++){
localStorage.setItem("lastname" + i, "Smith");
localStorage.setItem("firstname" + i, "John");
localStorage.setItem("age" + i, "22");
localStorage.setItem("job" + i, "Developer");
}
}
}
And at last the window.setInterval() to run a function every x seconds (Keep in mind 1 second = 1000 in the settimeout)
<script>
window.setInterval(function(){
var online = navigator.onLine;
processData(online);
}, 1000);
</script>
Hope this may help you on your quest!
The sources I used:
https://medium.com/#Carmichaelize/checking-for-an-online-connection-with-javascript-5de1fdeac336
Ajax passing data to php script
https://www.w3schools.com/html/html5_webstorage.asp
https://www.taniarascia.com/how-to-use-local-storage-with-javascript/
Get HTML5 localStorage keys
HTML5 localStorage getting key from value
What's the easiest way to call a function every 5 seconds in jQuery?
This is how I pass the array into the function
$rate=$data["rate"];//this is an array like rate[10,20,30,60,70]
$car->rate = $rate;
$car->rentalRate();
In the function , it accepts the array and insert into the table
public function rentalRate()
{
$rate = implode("','",$this->rate);
$sql = "INSERT INTO rental(day_1,day_3,day_7,day_15,day_30)VALUES('$rate')";
$stmt =connection::$pdo->prepare($sql);
$stmt->execute();
unset($rate);
}
Problem is,second time onwards it repeats the records. I mean for the first time when I insert only one row is inserted. The second time I insert, the same new record inserted twice. Third time I insert, thrice inserted..same goes for the number of times I insert. If I refresh than I don't have this issue.
WHat could be tracking the number of time I insert the data, could it be the array? or ajax?
This is how I submit the form via ajax
$("#submit").on("click",function()
{
$("#add_car_form").submit(function(){
var data = {
"action": "test"
};
data = $(this).serialize() + "&" + $.param(data);
$.ajax({
type: "POST",
dataType: "json",
url: "add_car_submit.php", //Relative or absolute path to response.php file
data: data,
success: function(data) {
$(".the-return").html("<br />JSON: " + data["json"] );
}
});
return false;
});
});
hard to say without seeing your full code but here is waht you can do:
Fist, use the dev tools on your browser and see how many requests you are submitting on every click. If they grow with every click it's your JS fault. If not then try to var_dump your POST data at the point of entry in your php scritpt. If the data is not repeated, there is a problem with your php part. (My bet would be with JS, as on AJAX request you create a new instance of php process so it can not track your submissions).
I have search results generated by a 3rd party script that I would like to add data to. I have parsed the results to get an array of id's, and queried the database for additional fields. The ajax success method receives the formatted array back, but now I'm stuck on how to get those results into the right place in the DOM.
The HTML:
<div class="ihf-results-property-info">
<div class="ihf-results-price">LIST: $2,150,000</div>
<div class="ihf-results-links"> 24 Photos
</div>
<div class="ihf-results-extra-info">
<div class="ihf-results-listingnum hidden-xs">Listing # 727938</div>
</div>
Repeat...
The last div I included in the example has the unique ID I'm using for the query. I'd like to use that to associate the ajax return with proper placement in the DOM. Here is my javascript:
jQuery(document).ready(function($) {
// grab the listings numbers so we can query the db for extra data
var listings = $('.ihf-results-listingnum').map(function() {
// grab just the digits
var listingNum = $(this).text().replace(/[^0-9]/g, '');
// add the listing number to the parent so we can target it later
$( this ).parents('.ihf-results-extra-info').parent().addClass('marketing-details-' + listingNum);
return listingNum;
// use .get to create an array of the listing numbers
}).get();
$.ajax({
type: "GET",
url: "custom/07-idx-queries.php",
data: 'mlsNums=' + listings, // looks like ?mlsNums=735383,727468,699876...
success: function(result) {
// this logic came from here: http://stackoverflow.com/questions/15311320/how-to-work-with-jquery-ajax-and-php-array-return
resultJson = $.parseJSON(result);
if (typeof resultJson == 'object') {
jsObject = eval(resultJson);
jsArray = [];
for(elem in jsObject){
jsArray.push(jsObject[elem]);
}
console.log(jsArray);
// this works as expected, except keys are 0 based
// This is where it all falls apart. I want to extract each object and stick it in the DOM in the correct place
jQuery.each(jsArray, function(key, value) {
$( this ).appendTo('.marketing-details-' + key);
});
}
else {
console.log("error occurred");
}
},
error: function(xhr, status, error) {
console.log(xhr.responseText);
}
})
});
And the php I'm using produces the desired results from the db, with the exception that it is a numerical array. I think an associative array would work better when trying to put the results into the DOM, tha way I could use the ID's as the key and match them to the classes I added. Here is the relevant code from custom/07-idx-queries.php:
$mls_nums = explode(",",$_GET['mlsNums']);
// removed all of the conditionals to keep the question clean
$html = array();
foreach ($mls_nums as $mls_num) {
// just retreiving a single object from each row for now
$remarks = $mysqli->query("SELECT mr FROM listings WHERE ln = '$mls_num'")->fetch_object()->mr;
// format the data
$my_html = "<p class='marketing-remarks mlsnum-".$mls_num."'>$remarks</p>";
// build an array of the results - necessary?
array_push($html,$my_html);
}
// send the data back in a JSON string
echo json_encode($html);
So my goal is to query the db for up to 10 rows, and insert the results into an equal number of new divs that are children to a div with the same id number in its class. I greatly appreciate any help.
In your PHP do this:
$html[$mls_num] = $my_html;
// this isn't needed
// array_push($html,$my_html);
Now your returned data has a way to tie into the target div.
Not clear if you have control over the HTML in the first part of your example, but this would be one approach.
<div class="ihf-results-listingnum hidden-xs">Listing # 727938</div>
<div class="remarks" id="remarks_<?= $listingid; ?>"></div>
Then in the JavaScript $("#remarks_" + key).html(value);
Otherwise, you need to use jQuery to locate the div with the listing id using the :contains selector:
$("div:contains('# " + key + "')").appendTo(value);
'# " + key + "' would equate to # 1234 or whatever it is. This won't work if the same listing is on the page twice though!
Okay, here is the working success method. Thanks to LG_PDX for the cleaned up php. I eliminated the unnecessary processing as .each() appears to iterate just fine over the JSON response:
success: function(result) {
resultJson = $.parseJSON(result);
if (typeof resultJson == 'object') {
$.each(resultJson, function(key, value) {
$('.marketing-details-' + key).append( value );
});
}
},
error: function(xhr, status, error) {
console.log(xhr.responseText);
}
Background Info
I'm fiddling around with some PHP and AJAX at the moment, to try and get the code working for an auto refreshing div (every 10 seconds), that contains comments.
Here is javascript code I am using to refresh the div..
<script type="text/javascript">// <![CDATA[
$(document).ready(function() {
$.ajaxSetup({ cache: false });
setInterval(function() {
$('#content_main').load('/feed_main.php');
}, 5000);
});
// ]]></script>
The code that will populate the div called "content_main", which is in feed_main.php, essentially accesses the database and echo's out the latest comments ...
Question
Is it possible, to only load the div "content_main" if the data inside of it, hasn't changed since the last time it was loaded?
My logic
Because I'm relatively new to javascript and AJAX I don't quite know how to do this, but my logic is:
For the first time it is run..
load data from feed_main.php file
Create a unique value (perhaps a hash value? ) to identify say 3 unique comments
Every other time it is run...
load the data from feed_main.php file
create a NEW unique value
check this value with the previous one
if they're the same, don't refresh the div, just leave things as they are, but if they're different then refresh..
The reason why I want to do this is because the comments usually have pictures attached, and it is quite annoying to see the image reload every time.
Any help with this would be greatly appreciated.
I've faced similar problem not too long ago, i assume that you using mysql or something for your comments storage serverside ?
I solved my problem by first adding timestamp integer column to my mysql table, then when i added a new row, i'd just simply use time() to save the current time.
mysql row insert example:
$query = "INSERT INTO comments (name, text, timestamp) VALUES ('". $name ."', '". $text ."',". time() .");";
step two would be to json_encode the data you sending from serverside:
$output = array();
if ($html && $html !== '') { // do we have any script output ?
$output['payload'] = $html; // your current script output would go in this variable
}
$output['time'] = time(); // so we know when did we last check for payload update
$json = json_encode($output, ((int)JSON_NUMERIC_CHECK)); // jsonify the array
echo $json; // send it to the client
So, now instead of pure html, your serverside script returns something like this:
{
"payload":"<div class=\"name\">Derpin<\/div><div class=\"msg\">Foo Bar!<\/div>",
"time":1354167493
}
You can grab the data in javascript simply enough:
<script type="text/javascript"> // <![CDATA[
var lastcheck;
var content_main = $('#content_main');
pollTimer = setInterval(function() {
updateJson();
}, 10000);
function updateJson() {
var request = '/feed_main.php?timestamp='+ (lastcheck ? lastcheck : 0);
$.ajax({
url: request,
dataType: 'json',
async: false,
cache: false,
success: function(result) {
if (result.payload) { // new data
lastcheck = result.time; // update stored timestamp
content_main.html(result.payload + content_main.html()); // update html element
} else { // no new data, update only timestamp
lastcheck = result.time;
}
}
});
}
// ]]> </script>
that pretty much takes care of communication between server and client, now you just query your database something like this:
$timestamp = 0;
$where = '';
if (isset($_GET['timestamp'])) {
$timestamp = your_arg_sanitizer($_GET['timestamp']);
}
if ($timestamp) {
$where = ' WHERE timestamp >= '.$timestamp;
}
$query = 'SELECT * FROM comments'. $where .' ORDER BY timestamp DESC;';
The timestamps get passed back and forth, client always sending the timestamp returned by the server in previous query.
Your server only sends comments that were submitted since you checked last time, and you can prepend them to the end of the html like i did. (warning: i have not added any kind of sanity control to that, your comments could get extremely long)
Since you poll for new data every 10 seconds you might want to consider sending pure data across the ajax call to save substantial chunk bandwidth (json string with just timestamp in it, is only around 20 bytes).
You can then use javascript to generate the html, it also has the advantage of offloading lot of the work from your server to the client :). You will also get much finer control over how many comments you want to display at once.
I've made some fairly large assumptions, you will have to modify the code to suit your needs. If you use my code, and your cat|computer|house happens to explode, you get to keep all the pieces :)
How about this:
<script type="text/javascript">
// <![CDATA[
$(function () {
function reload (elem, interval) {
var $elem = $(elem);
// grab the original html
var $original = $elem.html();
$.ajax({
cache : false,
url : '/feed_main.php',
type : 'get',
success : function (data) {
// compare the result to the original
if ($original == data) {
// just start the timer if the data is the same
setTimeout(function () {
reload(elem, interval)
}, interval);
return;
}
// or update the html with new data
$elem.html(data);
// and start the timer
setTimeout(function () {
reload(elem, interval)
}, interval);
}
});
}
// call it the first time
reload('#content_main', 10000);
});
// ]]>
</script>
This is just an idea to get you going it doesn't deal with errors or timeouts.
Best And Easy Code
setInterval(function()
{
$.ajax({
type:"post",
url:"uourpage.php",
datatype:"html",
success:function(data)
{
$("#div").html(data);
}
});
}, 5000);//time in milliseconds
I have a barcode scanner which reads the string of the barcode and displays in the active text box. also there is no consistent end character to the barcode, or standard length (I have 5 diffent length sizes. 16,17,18,19,20). I need to extract values from scanned data. so extracting values also depend on the barcode length.
So how would I go about firing a method when the WHOLE string has been read in?
Im using php and ajax to do this.
$(document).ready(function()
{
$("#bcode").focus();
//prevents autocomplete in some browsers
$("#bcode").attr('autocomplete', 'off').keyup(function(event)
{
var name = $("#bcode").val();
$("#status").empty();
if(name.length > 17 ) `// need to check all possible length values like this`
{
selectAll();
$("#status").html('<img align="absmiddle" src="images/loading.gif" /> Checking availability...').show();
$.ajax({
type: "POST",
url: "namecheck.php",
data : "bcode=" + name,
success: function(msg)
{
$("#status").html(msg).show();
}
});
}
else
{
$("#status").html('').addClass('err').show();
}
});
});
I did some work with a card swiper, there are similar challenges there. The data comes in a rapid burst, but there isn't a consistent "end-of-data" string being sent. The solution is to use setTimeout and wait - when the input stops, then you fire your processing code.
Depending on your hardware, the amount of waiting you'll want to do varies. Experiment with this code, to adjust the wait time, simply adjust the duration argument of setTimeout. I've started it on 500ms - that works pretty well for the card swipers. Forgive me if there are any minor wobbles in my code here - I am not a jQuery guy :)
$(document).ready(function() {
$("#bcode")
.focus()
.attr('autocomplete', 'off')
.keyup(function(event){
// if the timer is set, clear it
if (barcode_watch_timer !== false)
clearTimeout(barcode_watch_timer);
// set the timer to wait 500ms for more input
barcode_watch_timer = setTimeout(function () {
process_barcode_input();
}, 500);
// optionally show a status message
//$("#status").html('waiting for more input...').show();
// return false so the form doesn't submit if the char is equal to "enter"
return false;
});
});
var barcode_watch_timer = false;
function process_barcode_input() {
// if the timer is set, clear it
if (barcode_watch_timer !== false)
clearTimeout(barcode_watch_timer);
// grab the value, lock and empty the field
var name = $("#bcode").val();
$("#bcode").attr('disabled', true);
// empty the status message
$("#status").empty();
// add a loading message
$("#status").html('<img align="absmiddle" src="images/loading.gif" /> Checking availability...').show();
// send the ajax request
$.ajax({
type: "POST",
url: "namecheck.php",
data : "bcode=" + name,
success: function(msg) {
// unlock the field, show a success status
$("#bcode").attr('disabled', false);
$("#status").html(msg).show();
}
});
}
Does it need to be a text area?
The last barcode reader I used always ended with a newline. If you are inputing into a <input type="text"/> the return char will likely try to submit the form, and you can use an onSubmit to capture the event and process your input.
Try observe the field with code by interval
Example
setInterval(function() {
var value = $("#code").val(),
prev_value = $("#code").attr("prev_value");
if (prev_value == value) {// compare with prevent value for detecting canges
console.log("value is not changed");
return;
}
//if (value.length < 17) {
//exeption
// or reset value $("#code").val(prev_value);
//return;
//}
if (value[value.length-1] == "\n") {// check last symbol
console.log(value);// Do something with you code eg send by AJAX
}
$("#code").attr("prev_value", value); // save current value for compare later
}, 1000 );