I have the following issue:
Let's say that I have a function that process an array to do something with it depending on received parameters. So something like:
var arr = [];
function processArr(p1, p2, ....){};
p1, p2 etc are received from the server so we get to:
processArr(<?php echo $p1; ?>, <?php echo $p2; ?>, ...)
processArr(<?php echo $p1; ?>, <?php echo $p2; ?>, ...)
processArr(<?php echo $p1; ?>, <?php echo $p2; ?>, ...)
processArr(<?php echo $p1; ?>, <?php echo $p2; ?>, ...)
processArr(<?php echo $p1; ?>, <?php echo $p2; ?>, ...)
It is actually a php for but doesn't really matter.
Problem: js process the calls simultaneously (not exactly simultaneously but close enough) instead of one after the other. So if in first call I add an element to the array (then some other processing) and in second call I try to delete the element, at delete the element doesn't exist because it wasn't added yet.
How do I make second call to wait for the first to finish?
Added function:
function processSaved(act, params)
{
if (act == 1)
{
var newUser = params;
if (user.id == newUser.id)
user = clone(newUser);
activeElementIndex = i;
// Go to the next level from the active element level
var newLevel = newUser.level;
// Set current level
currentLevel = Math.max(currentLevel, newLevel);
// Create new object and push it to elements array
var obj = newUser;
elements.push(obj);
activeElementIndex = newUser.parent;
// Add element to order list
if (orderElements.length + 1 > newLevel)
{
var added = 0;
for (var i = 0; i < orderElements[newLevel - 1].el.length; i++)
{
if (elements[activeElementIndex].column < elements[elements[orderElements[newLevel - 1].el[i]].parent].column)
{
orderElements[newLevel - 1].el.splice(i, 0, elements.length - 1);
added = 1;
break;
}
}
if (added == 0)
orderElements[newLevel - 1].el.push(elements.length - 1);
}
else
{
var tmp = new Array();
tmp.push(elements.length - 1);
var obj = {"el": tmp};
orderElements[newLevel - 1] = obj;
}
flagCreate = 1;
actions.push(newUser);
// Call the rearange function
rearangeElementsWithoutRedraw();
}
else if (act == 0)
{
activeElementIndex = params.index;
deleteNode();
}
return true;
}
First call is made with act = 1. Second is made with act = 0. If I add a timeout to the second call with let's say 0.5 seconds everything works fine. If not I get error at removal because element does not exist. This suggests that the second call is made before first finished.
JS does not call functions in parallel. Your processArr functions are executed sequentially.
This obviously assumes that you do not simply start e.g. an AJAX request in the function - if you do the next function will obviously not wait for the request to finish (until it's synchronous).
Found the problem. There was an asynchronous call made by a library I was using (raphaeljs). Srry for loss of time :).
Related
I'm facing some output trouble at the second part of my codes.
function getSiteContent($url)
{
$html = cache()->rememberForever($url, function () use ($url) {
return file_get_contents($url);
});
$parser = new \DOMDocument();
#$parser->loadHTML($html);
return $parser;
}
libxml_use_internal_errors(true);
$url = 'https://sumai.tokyu-land.co.jp/osaka';
$parser = getSiteContent($url);
$allDivs =[];
$allDivs = $parser->getElementsByTagName('div');
foreach ($allDivs as $div) {
if ($div->getAttribute('class') == 'p-articlelist-content-right') {
$allLinks = $div->getElementsByTagName('a');
foreach ($allLinks as $a) {
$getlinks[] = $a->getAttribute('href');
}
}
}
var_dump($getlinks);
At this var_dump I can see links that I scraped. No problem 'till here. And one more time. I want to go into those links. That's why I wrote the codes right below.
getSiteContent($getlinks);
$link = [];
$siteler = [];
foreach ($siteler as $site) {
if($site == 'https://sumai.tokyu-land.co.jp'){
$site = $getlinks->getElementsByTagName('div');
foreach ($site as $links) {
if($links->getAttribute('class') == 'pc_hnavi'){
$linker = $links->getElementsByTagName('a');
foreach ($linker as $a) {
$link = $a->getAttribute('href');
}
}
}
}
}
var_dump($link);
When I var_dump it. It says Array 0
I didn't understand why it doesn't go in those links with foreach
My codes are wrong? What am I missing here? Any idea for this?
Thank you helping me out.
As I said in the comments $siteler is empty when you try to loop through it, but there are a couple more problems:
First your code will only trigger once at most, when the link is exactly 'https://sumai.tokyu-land.co.jp' and I'm not sure that's what you want.
You are calling DOM functions on an array.
Only seem to care about links inside 'div' tags.
You redefine the $link variable on each loop, so the final result will be just one link.
This is the fixed code:
$link = [];
foreach ($getlinks as $site) {
// Any link in the domain, not just the homepage
if(strpos($site, 'https://sumai.tokyu-land.co.jp') === 0) {
$dom = getSiteContent($site);
$divs = $dom->getElementsByTagName('div');
foreach ($divs as $div) {
// Can have more than one class
$attrs = explode(' ', $div->getAttribute('class'));
if(in_array('pc_hnavi', $attrs)) {
$linker = $div->getElementsByTagName('a');
foreach ($linker as $a) {
// Add to the array
$link[] = $a->getAttribute('href');
}
}
}
}
}
However this doesn't check if the link already exists in the array and has the potential to process the same links over and over. I'd strongly suggest to use an existing crawler.
From the comments, turns out that pc_hnavi is an id and not a class and you are interested in the first link only. You can access that element directly without iterating the elements:
foreach ($getlinks as $site) {
// Any link in the domain, not just the homepage
if(strpos($site, 'https://sumai.tokyu-land.co.jp') === 0) {
$dom = getSiteContent($site);
$div = $dom->getElementById('pc_hnavi');
if ($div != null) {
$links = $div->getElementsByTagName('a');
if ($links->length > 0) {
$a = $links->item(0);
$link[] = $a->getAttribute('href');
}
}
}
}
It looks like your problem is here:
...
$siteler = []; // $siteler is set to an empty array ...
foreach ($siteler as $site) { // then you loop through the empty array which does nothing ...
...
}
...
Fixing that should get you started.
Now there are plenty of people with the same issue and their resolutions have not worked.
Problem
I have a list of Times coming back from a REST call. They are created exactly as they should, except I want them to be stored into a JavaScript Array.
PHP
function getOpenAppts()
{
global $wpdb;
$final_array = "";
$td = date('m/d/Y');
$datetime = new DateTime('tomorrow');
$tm = $datetime->format('Y-m-d');
$startDate = $td;
$endDate = $tm;
$apptTypeID = "23";
$get_loc = $wpdb->get_results('SELECT provid,id FROM location');
foreach($get_loc as $val){
// call to Athena to get open appointments
$res = getOpenAppointments($val->id, $val->provid, $startDate, $endDate, $apptTypeID);
//print_r($res);
// if we got some appointments back strip any that started before now
if (array_key_exists('totalcount', $res) && $res['appointments'] > 0)
{
$tzStr = "America/Los_Angeles";
$tzObject = new DateTimeZone($tzStr);
$nowDT = new DateTime();
$nowDT->setTimezone($tzObject);
//print_r($nowDT);
//print_r("\n");
$appts = array();
for ($i = 0; $i < count($res['appointments']); $i++)
{
$apptDT = new DateTime($res['appointments'][$i]['date']." ".$res['appointments'][$i]['starttime'], $tzObject);
//print_r($apptDT);
//print_r("\n");
if ($nowDT < $apptDT)
$appts[] = $res['appointments'][$i];
}
}
if (count($appts) > 0)
foreach($appts as $data) {
$final_array[] = $data;
}
else
$res; // something went wrong. return error message
}
echo json_encode($final_array);
}
Header.php
<script>
var times = <?php getOpenAppts(); ?>;
console.log(times); //Will display properly
</script>
That is exactly how it should come back!
But.. When I run a console on the variable times (which is in the header making it a global variable. I get this.
It should give me the exact same list that the console.log gave me.
What I Have tried
I ran:
PARSE.json(times);
No effect...
I did in PHP:
json_encode(json_decode($appts),true);
No effect...
What part of this process is incorrect?
You are using time as a global variable.
Since the console.log right after the declaration prints everything fine, you are probably overriding its value somewhere after.
Avoid the most you can global variables, they're evil :)
Ok so I'm pretty much completely new to using ajax and I'm also still in the process of understanding effective implementation of php. Been a bit stuck recently because I feel like I'm forgetting or overlooking a really easy solution.
Right now the following code gets a trove api query with the help of php and appends 100 of these queries for each item (I know it's inefficient but right now I have a reason for this method). I use 'getperson' to grab the name from the object's own data and then for each I assign the relevant value to all items.
I want to do the same for a img url, however I don't have a good enough understanding of ajax syntax or possibilities to properly pass the correct index (which matches the getname index) into the ajax function.
I feel like there was a much more efficient way to do this, but would prefer if anyone could help explain the steps I can take to iterate on my current model.
var compilelist = [];
var promises = [];
for (i=0; i < <?php echo $rowcount ?>; i++) {
var getname = <?php echo json_encode($followarray) ?>[i];
var getimg = <?php echo json_encode($imgarray) ?>[i];
var getitem = Geturl(getname, 100);
var promise = $.getJSON(getitem);
$.when(promise).done (function(data) {
var getperson = data.response.query;
$.each(data.response.zone[0].records.article, function(index, value) {
value.name = getperson;
// This is what I want to do but I can't grab from the loop cause 'each' is inside the ajax query
value.img = getimg;
compilelist.push(this);
});
});
promises.push(promise);
}
Well this question was dumb anyway but I quickly found a messy solution if anyone ever has a similar problem, I just stored img var in array parallel to name array so that I could select index from the name and use it to grab img from php:
var compilelist = [];
var promises = [];
for (i=0; i < <?php echo $rowcount ?>; i++) {
var getname = <?php echo json_encode($followarray) ?>[i];
var getitem = Geturl(getname, 100);
var promise = $.getJSON(getitem);
$.when(promise).done (function(data) {
var getperson = data.response.query;
var getindex = <?php echo json_encode($followarray) ?>.indexOf(getperson);
$.each(data.response.zone[0].records.article, function(index, value) {
value.name = getperson;
value.imgurl = <?php echo json_encode($imgarray) ?>[getindex];
compilelist.push(this);
});
});
promises.push(promise);
}
I'm adding new data to database table with jQuery. Then i'm getting all content from that table. Problem is i'm getting wrong array size every odd time.If i refresh the page it's getting right array size but when i'm clicking button with jQuery function it's all messed up.
I figure out that
$n = mysqli_num_rows($result);
already return wrong num of rows
Here is the script:
$(document).ready(function(){
$.getallentries = function(){
$.getJSON("entries.php",{action : "getall"},function(data) {
var content_array = $.map(data, function(e) { return e;});
console.log(content_array.length); // to check array size
});
$.addstatic = function(){
$.post("entries.php",{action : "addstatic"});
};
};
$("#adds").on("click",function(){
$.addstatic();
$.getallentries();
});
$.getallentries();
And here is entries.php:
function getall(){
$link = db_connect();
$query= "SELECT * FROM jq";
$result = mysqli_query($link,$query, MYSQLI_STORE_RESULT);// Smart people said MYSQLI_STORE_RESULT should help but it didn't
$n = mysqli_num_rows($result);
for($i = 0 ;$i<$n;$i++)
{
$row=mysqli_fetch_assoc($result);
$b[]=$row;
}
echo json_encode(array($b));
}
function addstatic(){
$link = db_connect();
$statin_Entry = "Static Entry";
$query = "INSERT INTO jq (Entry) VALUES ('$statin_Entry')";
$result = mysqli_query($link,$query);
}
if(isset($_GET['action']) && !empty($_GET['action'])) {
$action = $_GET['action'];
switch($action) {
case 'getall' : getall(); break;
}
}
else {
if(isset($_POST['action']) && !empty($_POST['action'])) {
$action = $_POST['action'];
switch($action) {
case 'addstatic' : addstatic();break;
case 'removelast' : removelast();break;
// ...etc...
}
}
}
This is log of array length
So the problem again, same array size 143,146,151 and where is 156??
You should call $.getallentries in the callback function of the $.addstatic AJAX call, so that it runs after $.addstatic has finished updating the database.
$.addstatic = function(){
$.post("entries.php",{action : "addstatic"}, $.getallentries);
};
There's no need to use mysqli_num_rows before fetching the rows. You should use a loop like this:
while ($row = mysqli_fetch_assoc($result)) {
$b[] = $row;
}
Also, you're wrapping your array in another array. Just do:
echo json_encode($b);
The way you've written it, console.log(content_array.length) should always log 1, I don't understand how you're getting higher numbers. Are you sure you posted the actual code?
There's no point in use $.map, all it's doing is making a copy of the data array. Just use data itself.
And in your PHP, you don't need to test both isset() and !empty(), because empty() checks if the variable is set first.
You don't need to use MYSQLI_STORE_RESULT, it's the default for that option.
can anyone help me...my script function automatically updates what's inside the output of my textboxes from the database if I change the values in the table in the database without refreshing the page or clicking the button again to execute the script.
After a seconds later my page is lagy. I can't move my mouse freely. Is there any way how to automatically update data in my textboxes using javascript if I change the values in my table in my database?
current script:
$(document).ready(function(){
var timer ;
$('#send_search_form').click(function(event){
event.preventDefault();
$(".search_form_input").val('');
$(".empty_batchcode").html("Doesn't exist!");
clearInterval(timer);
updateTextboxes();
});
function updateTextboxes(){
$.ajax({
url:"search.php",
type:"GET",
data: { term : $('#query').val() },
dataType:"JSON",
success: function(result) {
var ii = 1;
for (var i = 0; i < result.length; i++) {
$('#funiq_id').html(result[i].value).show();
$('#t_region').val(result[i].region).show();
$('#t_town').val(result[i].town).show();
$('#t_uniq_id').val(result[i].uniq_id).show();
$('#t_position').val(result[i].position).show();
$('#t_salary_grade').val(result[i].salary_grade).show();
$('#t_salary').val(result[i].salary).show();
$('#id'+ii+'').val(result[i].atid).show();
$('#aic'+ii+'').val(result[i].atic).show();
$('#name'+ii+'').val(result[i].atname).show();
$('#other_qual'+ii+'').val(result[i].other_sum).show();
$('#interview'+ii+'').val(result[i].interview_sum).show();
ii++;
}
if(timer == 1){ // if timer has been cleared
timer = setInterval(updateTextboxes,1000); // <-- change 1000 to the value you want
}
}
});
timer = setInterval(updateTextboxes,1000);
}
});
search.php code:
<?php
if (isset($_GET['term'])) {
$q = $_GET['term'];
mysql_connect("localhost", "root", "");
mysql_select_db("klayton");
$query = mysql_query
("
SELECT DISTINCT
ROUND((SELECT SUM(t2.inttotal)
FROM app_interview2 AS t2
WHERE t2.atic = t.atic)/7,1)
AS interview_sum,
ROUND((SELECT SUM(o2.ototal)
FROM other_app2 AS o2
WHERE o2.oaic = t.atic)/7,1)
AS other_sum,
atid,
atic,
atname,
region,
town,
uniq_id,
position,
salary_grade,
salary
FROM app_interview2 AS t
WHERE uniq_id = '$q'
GROUP BY t.atname HAVING COUNT(DISTINCT t.atic) ");
$data = array();
while ($row = mysql_fetch_array($query)) {
$data[] = array(
'value' => $row['uniq_id'],
'atid' => $row['atid'],
'atic' => $row['atic'],
'region' => $row['region'],
'town' => $row['town'],
'uniq_id' => $row['uniq_id'],
'position' => $row['position'],
'salary_grade' => $row['salary_grade'],
'salary' => $row['salary'],
'atname' => $row['atname'],
'other_sum' => $row['other_sum'],
'interview_sum' => $row['interview_sum']
);
}
header('Content-type: application/json');
echo json_encode($data);
}
?>
You are setting more and more setIntervals inside setIntervals and never clearing them. Remember, each setInterval call results in function running multiple times, once every N milliseconds. As the time passes, the amount of running code increases exponentially, which causes lag.
Consider using setTimeout instead. Also, setTimeout or setInterval? might be a good read.
The documentation on the above methods:
https://developer.mozilla.org/en/docs/Web/API/window.setTimeout
https://developer.mozilla.org/en/docs/Web/API/window.setInterval
Two things I have noticed. The first is the setInterval(). Every loop-illiteration it starts another timer. 1sec = 1 interval, 2sec=2, 3sec=4(!), 4sec=8(!!). So after a few seconds, your browser's going crazy. Use setTimeout() instead :)
Number two is saving the DOMreference. Every illiteration you select the id's and set a new value. Every second jQuery finds the elements. It's better to save them first, and then use the saved reference. I've done both:
var $funiq_id = $('#funiq_id'),
$t_region = $('#t_region'),
$t_town = $('#t_town'),
$t_uniq_id = $('#t_uniq_id'),
$t_position = $('#t_position'),
$t_salary_grade = $('#t_salary_grade'),
$t_salary = $('#t_salary');
function updateTextboxes(){
$.ajax({
url:"search.php",
type:"GET",
data: { term : $('#query').val() },
dataType:"JSON",
success: function(result) {
if(result.changedOccured){ // make php send if there are changes (true/false)
var ii = 1;
var resultLength = result.length;// Out of the loop will improve a tiny bit
for (var i = 0; i < resultLength; i++) {
$funiq_id.html(result[i].value).show(); // reference
$t_region.val(result[i].region).show(); // reference
$t_town.val(result[i].town).show(); // reference
$t_uniq_id.val(result[i].uniq_id).show(); // reference
$t_position.val(result[i].position).show(); // reference
$t_salary_grade.val(result[i].salary_grade).show(); // reference
$t_salary.val(result[i].salary).show(); // reference
$('#id'+ii+'').val(result[i].atid).show();
$('#aic'+ii+'').val(result[i].atic).show();
$('#name'+ii+'').val(result[i].atname).show();
$('#other_qual'+ii+'').val(result[i].other_sum).show();
$('#interview'+ii+'').val(result[i].interview_sum).show();
ii++;
}
}
}
}
if(timer == 1){ // if timer has been cleared
timer = setTimeOut(updateTextboxes,1000); // <-- change 1000 to the value you want
}
}
Small note: Saving the DOM references into variables need to happen at the bottom of the page, or on a $(document).ready(). The elements have to exists before you can select them
For better performance, make php send wether or not something has changed. If something has, do the code you have now. If no changes, DONT UPDATE THE ELEMENTS. It's a waste of power to change something from 'abc' to 'abc'.