delay between each foreach javascript/php - php

I have a function that gets individuals from the database and then, in jquery, runs through them, animating them. The problem...which I see is quite common is the fact that javascript runs through all the items in a split second and the delay would be applied to all.
I have search stackoverflow and have found some references to this, but none work with my code below. Any ideas would be greatly appreciated.
$individuals = $wpdb->get_results("SELECT * FROM wp_sisanda_individualsponsors");
?>
<script type="text/javascript">
function individual_sponsors() {
var individuals = <?php echo json_encode($individuals) ?>;
individuals.sort(function() { return 0.5 - Math.random() });
jQuery.each(individuals, function (i, elem) {
var topRand = Math.floor(Math.random()*301);
var leftRand = Math.floor(Math.random()*301);
var startLeftRand = Math.floor(Math.random()*301);
jQuery('.individuals').append('<div id="'+ elem.id + '" class="indiv" style="position: absolute; bottom: -70px; left:' + startLeftRand +'px;">' + elem.name + '</div>');
jQuery('#' + elem.id).animate({
top: -100,
left: Math.floor(Math.random()*301)
},20000 + Math.floor(Math.random()*50000));
});
}
</script>
As you can see, the items get a random horizontal starting position and ending position and a random speed, this works well, except there is still major bunching of items.
I have tried limiting the amount requested initially - randomly selecting a few and then calling the function repeatedly with a php wait in between, but this, I think, caused an ifinite loop...not sure...page wasn't loading.
I hope someone can point me in the right direction.
Ideally it would animate a few...wait...and then do some more...
Thanks in advance

A PHP wait won't help you as PHP executes on the server before anything gets sent to the client (where the JavaScript executes). If you want to animate a few, wait a bit, then animate some more, until you're done then you can use setTimeout:
var current = 0;
function animateSome() {
// Animate a few (starting at individuals[current]) and
// update current with the array index where you stopped.
// ...
// If there's anything left to do, start a timer to animate
// the next chunk of individuals.
if(current < individuals.length)
setTimeout(animateSome, 250);
}
animateSome();

Related

increase limit of query by given amount using php and ajax

Re-frased question do to new info
I'm trying to show a limited set of results on a search (i.e. LIMIT 10 in query) then have a button that will load the next 10 (now LIMIT 20 in same query).
The problem is that when I press the button, it not only refreshes the the specified div - but it re-runs the doSearch at the very top of the page - and thereby resetting the LIMIT to 10...
So if I
1. load the result-page
2. comment out the doSearch at top of page
and first then...
3. click the button
It works as perscribed... it now show 20 results... and if I click again it shows 30... etc.
And if I uncomment the doSearch at the very top of page and click the button... it now shows 10 results again...
the code in question in the ajax-code is
var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
showResult.load(location.href + " #showResults>*", "");
I can't see why my code would re-run the doSearch at the top of page... but hopeully some of you wise folks can see the error of my ways and set me on the right path...
My basic setup:
page with results:
<?php // get search results limit 10 ?>
.
.
.
<div id="showResultsAll">
.
.
.
<div id="showResults">
// Loop through and show results
<div id="moreResultsButton">
<input type="hidden" name="search" id="search" value="<?php // search terms ?>">
<button id="moreResults" value="<?php // number of results found ?>">
jquery.js
$(document).ready(function(){
"use strict";
$(document).on('click','button[id^="moreResults"]', function(){
var self = $(this);
var closestDiv = self.closest('#moreResultsButton');
var search = closestDiv.find('[id^="search"]').val();
var count = self.val();
var countNew = + count + 10;
$.ajax({
type: "POST",
url:'../scripts/moreresults.php',
data:"countNew="+countNew+"&search="+search,
success:function(){
var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
showResult.load(location.href + " #showResults>*", "");
}
});
});
});
moreresults.php
session_start ();
require ( "../scripts/functions.php" );
// Set variable
$search = $_POST['search'];
$limit = $_POST['countNew'];
doSearch ( $pdo , $search , $limit ); // same function that found the search results in the first place
Update
So found a solution loosely based on an answer given below by #delCano (although I'm still curious as to why my original code insisted on rerunning the doSearch at the top of the page)
Solution:
I split everything up by first dropping the limit in the doSearch and just let it find all results and then did the 'limiting' in the show-results part of the page, and then just added 10 to that in my jQuery
New code:
page with results
<?php // doSearch no limit ?>
.
.
.
<div id="showResultsAll">
.
.
.
<div id="showResults">
// Loop through and show results - limiting like this
// if isset $_POST['show'] (ie. button clicked)
// if $_POST['show'] less than $_SESSION['totalResults'] (ie. more results coming)
// $show = $_POST['show'] (ie. 20, 30, etc.)
// else
// $show = $_SESSION['totalResults'] (ie. 11, 12, ..., 21, 22, ..., 31, 32, ..., etc.)
// else (if button not clicked limit results to max. 10)
// if $_SESSION['totalResults'] more than 10
// $show = 10
// else
// $show = $_SESSION['totalResults'] (ie. 1, 2, 3, etc.)
// loop trough $show number of results
<div class="<?php if $show == $_SESSION['totalResults'] echo "disabled" // Only active if more results are available ?>" id="moreResultsButton">
<button id="moreResults" value="<?php echo $show; ?>">
jQuery.js
$(document).ready(function(){
"use strict";
$(document).on('click','button[id^="moreResults"]', function(){
var self = $(this);
var show = self.val();
var showNew = + show + 10;
$.ajax({
type: "POST",
url:'',
data:"show="+showNew,
success:function(){
self.closest('#showResultsAll').find('[id^="showResults"]').load(location.href + " #showResults>*", "");
}
});
});
});
OK, this is not the best answer, just a development from the comments above. I'll try and write a better answer tomorrow.
However, for the time being, my quick workaround would be:
Remove, as you mention, the doSearch from the top of the page, and set all the initial numbers to 0.
Replace your jQuery with this:
$(document).ready(function(){
"use strict";
$('button#moreResults').click(addResults);
function addResults(){
var self = $(this);
var closestDiv = self.closest('#moreResultsButton');
var search = closestDiv.find('[id^="search"]').val();
var count = self.val();
var countNew = + count + 10;
$.ajax({
type: "POST",
url:'../scripts/moreresults.php',
data:"countNew="+countNew+"&search="+search,
success:function(){
var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
showResult.load(location.href + " #showResults>*", "");
}
});
}
// load the first ten results
addResults();
});
Please note I did minimal changes to your Javascript. This is not necessarily the most optimal way to do it; I'll revise and edit it tomorrow.
Edit: major refactoring
doSearch is a PHP function that prints the search results to screen. I would change this into a function that returns an array of results. I don't have your code on this, and I don't know how it looks, but it should return something similar to:
array(
array( 'name' => 'One', 'surname' => 'Smith' ),
array( 'name' => 'Two', 'surname' => 'Smythe' ),
....
)
moreresults.php is the PHP that is called to load new results. Since all the rest of the logic will be done in Javascript, this is for now the ONLY PHP code we call. I would include doSearch() in this file now.
session_start ();
require ( "../scripts/functions.php" );
function doSearch( $pdo, $search, $limit) {
/* do logic here */
return $array_of_results;
}
// Set variable
$search = $_POST['search'];
$limit = $_POST['countNew'];
$results = doSearch ( $pdo , $search , $limit );
header('Content-Type: application/json'); // This will tell the client the type of content returned.
echo json_encode($results); // It is a good idea to make all data transmissions between your server-side code (PHP) and your front-end code (Javascript) in JSON. It's also a good idea to never output anything in your PHP code until the very end, where you have all the required data. It makes it easier to debug later on.
Now, the HTML. It doesn't need any PHP preprocessing now, since it will always start the same. We also don't need the tracking of the variables here, since all the logic would be in the Javascript part now.
.
.
.
<div id="showResultsAll">
.
.
.
<ul id="showResults">
</ul>
<button id="loadMore">Load more results</button>
</div>
.
.
.
The Javascript now bears the weight of most of the logic.
$(function() { // Shorthand for "$(document).ready(function()..."
var count = 0;
$("#loadMore").click(loadMoreResults);
function loadMoreResults() {
var url = "../scripts/moreresults.php";
var search = $("#search").val();
count += 10;
var data = {
'countNew': count,
'search': search
};
$.post(url, data, showResults, 'json' );
}
function showResults(data) {
$("#showResults").empty().append(`
<li>${data.name} ${data.surname}</li>
`);
}
});
Notes:
Since I didn't know what kind of data you're working with, I used a list of names and surnames as an example.
Likewise, I presented the results as a unordered list () and list items(); you might prefer a table, or something different.
The code is completely untested. I tried to be careful, but I may have made some typos or other mistakes.
If I were you, I would try to start by learning some jQuery basics before launching myself into Ajax. The FreeCodeCamp has a nice jQuery course.
Code architecture is extremely important, and not often well explained in online courses. As a summary:
Always plan ahead your code. Pick up a pen&paper, or your favourite text editor, and answer yourself the question: "What must the code do?". Then decompose the answer in smaller steps. Then separate each step into smaller steps, and so on.
Whenever you have a piece of code you might need twice, wrap it into a function. Think of functions as small "tasks"
Separate as much as possible the logic from the presentation. You should have part of your code working on the data itself, and part of it working on showing the data, and they should be almost independent from each other. You might want to look at the MVC pattern (Model-View-Controller); it may be in process of replacing, but it is a good starting point. This, by the way, is valid both on the backend (doSearch would be the logic, moreresults the presentation) and the frontend (html is the presentation, javascript the logic).
To finish, the code I gave you is not perfect, but I think is a better start. You'll assuredly find many ways to improve it

Bug fixing for my damage per second function

I've created a working damage per second loop although it has a few bugs that need to be worked out.
i'd like the 'target has been destroyed' message to be displayed instantly, not 1.2 seconds after the current hitpoints reach 0.
the major bug is that if you click the attack button multiple times, it will initiate the setInterval multiple times and the damage will be inflicted every 1.2 seconds for every time you clicked it, so it can execute multiple times.
The initial attack should happen instantly.
Any thoughts or ideas? I have tried the using a do while loop but i couldn't get that code to work at all. I've only had success with the setInterval function.
I have a working script on my website and i'll post the code here as well.
$(document).ready(function(){
var dmg = 60;
var curr_hp = 1200;
var tot_hp = 1200;
$('#attk_spd').html('1.2 seconds');
$('#dmg').html('60'); $('#curr_hp').html('1200');
$('#tot_hp').html('1200');
$("#btn").click(function(){
$('#attk').html('You are currently attacking your target.');
setInterval(
function () {
if (curr_hp > 0) {
curr_hp = curr_hp - dmg;
$('#curr_hp').html(curr_hp);
} else { $('#attk').html('Your target has been destroyed.');
}
},
1200);
})
});
And here's the current working version in action:
http://www.evenstar-online.com/Jquery_snippets/dpsloop.php
Use setTimeout instead of setInterval, so you can control precisely whether to attack again. Then you can just call the function once and the first attack happens immediately. This is a little weird to explain; follow the code below :)
Also:
Taking care to indent your code correctly makes it much easier to follow at a glance :)
Don't use $.html unless you're actually assigning HTML! Get in the habit of using $.text instead, or you'll end up trying to stick an angle bracket somewhere and have no idea why all the text disappeared.
I ended up with:
$(document).ready(function(){
var dmg = 60;
var curr_hp = 1200;
var tot_hp = 1200;
$('#attk_spd').text('1.2 seconds');
$('#dmg').text('60');
$('#curr_hp').text('1200');
$('#tot_hp').text('1200');
var attack_timer;
$("#btn").click(function() {
if (attack_timer) {
// We're already waiting for the next attack, so do nothing
return;
}
$('#attk').text('You are currently attacking your target.');
var attack_once = function() {
// Always attack immediately
curr_hp -= dmg;
$('#curr_hp').text(curr_hp);
// Only schedule another attack if the target is still alive
if (curr_hp > 0) {
attack_timer = setTimeout(attack_once, 1200);
}
else {
$('#attk').text('Your target has been destroyed.');
}
};
attack_once();
})
});

Javascript countdown timer that stops when window is not in focus

Ok , I'm having trouble to solve this , I'm a php / C# web developer , and have no experience or knowledge in Javascript, I have to do just this one thing that needs Javascript:
When a certain page loads, a counter starts. The client must stay on this page for 20 seconds. after, I want to execute php code.
So there are 2 issues concerning me, first: how do I stop the counter, if client leaves the page (meaning the page is not in focus).
2) How can I execute php in javascript? , or call a php function from Javascript.
The code I have so far is this:
<html>
<head>
</head>
<body>
<div id='timer'>
<script type="text/javascript">
COUNTER_START = 20
function tick () {
if (document.getElementById ('counter').firstChild.data > 0) {
document.getElementById ('counter').firstChild.data = document.getElementById ('counter').firstChild.data - 1
setTimeout ('tick()', 1000)
} else {
document.getElementById ('counter').firstChild.data = 'done'
}
}
if (document.getElementById) onload = function () {
var t = document.createTextNode (COUNTER_START)
var p = document.createElement ('P')
p.appendChild (t)
p.setAttribute ('id', 'counter')
var body = document.getElementsByTagName ('BODY')[0]
var firstChild = body.getElementsByTagName ('*')[0]
body.insertBefore (p, firstChild)
tick()
}
</script>
</div>
</body>
</html>
and I also want the timer to start ticking when the client gets back on page
Thank you very much for ur help in advance
You could do this using jQuery.
Recycling an old Stackoverflow post, try this:
var window_focus;
var counter = 1000;
// on focus, set window_focus = true.
$(window).focus(function() {
window_focus = true;
});
// when the window loses focus, set window_focus to false
$(window).focusout(function() {
window_focus = false;
});
// this is set to the ('click' function, but you could start the interval/timer in a jQuery.ready function: http://api.jquery.com/ready/
$(document).one('click',function() {
// Run this function every second. Decrement counter if window_focus is true.
setInterval(function() {
$('body').append('Count: ' + counter + '<br>');
if(window_focus) { counter = counter-1; }
}, 1000);
});
Demo and old post
DEMO | Old So post
Update
Probably because the demo runs in 4 iframes, the $(window).focus bit only works on the iframe actually running the code (the bottom-right window).
jQuery
jQuery.com (How jQuery works) | Example (back to basics halfway down the page) | If you use the 2nd link, also read this
In regards to your first question about detecting if the window is out of focus, see this answer: Is there a way to detect if a browser window is not currently active?
It is possible, but only very new browsers support this so it may not be useful based on current browser support.
To trigger PHP code from Javascript, you would have to make an AJAX call to a server-side PHP script to invoke PHP since JS is client-side and PHP is server-side.

Infinite Scrolling in Yii

I am looking for a solution to display many items (10's of thousands) in a list view in Yii. I would like to be able to display them in a continually scrollable list. Here is the catch, when the user scrolls past the end of the list I want the new data to replace the data he just scrolled passed. Kind of like google music if you have a really long play list.
I looked at Yiinfinite-scroller but it appends to the end of the list making a very long list which is killing my memory usage.
Thanks
Its actuality really easy to implement infinite scroll in just a few lines of js and with the help of jQuery. Measure the height of the content div and as the page scrolls subtract the scroll difference from the divs height then when it hit the min amount do the query for more content and reset the height counter and repeat:
<script type="text/javascript">
var contentHeight = 4000,;
var pageHeight = document.documentElement.clientHeight;
var scrollPosition;
var n = 1;
function scroll(){
if(navigator.appName == "Microsoft Internet Explorer")
scrollPosition = document.documentElement.scrollTop;
else
scrollPosition = window.pageYOffset;
if((contentHeight - pageHeight - scrollPosition) < 500){
$.ajax({ url: "./yourAPI/?next="+n, cache: false,
success: function(data){
//append result
$('#infscroll').append('<div>'+data.result+'</div>');
}, dataType: "json"});
n += 1;
contentHeight += 4000;
}
}
$(document).scroll(function(){
setInterval('scroll();', 250);
});
</script>
<div id="infscroll"></div>

Making Tab Persist when Reloading Page

I'm trying to modify Gaya Design's Tabbed Content (Available Here) to have the current tab persist when the page is reloaded, yet have it change when a new tab is clicked. I've already changed it a little to be able to change default tab by using a PHP GET variable. The current condition of the page I'm working on can be viewed here.
So here's my likely scenario. If you've clicked on the link above, you'll see I'm working on a simple PHP shopping cart. Now when a user clicks an add link, it has to reload the page, and when it does that it resets the tab. So, I'm thinking this should easily be solved with a cookie that updates whenever a new tab is clicked....I'm just not too sure how to go about this. Any thoughts, suggestions, or advice will be greatly appreciated.
Here's my current JS:
var TabbedContent = {
init: function() {
$(".category").click(function() {
var background = $(this).parent().find(".selected");
$(background).stop().animate({
left: $(this).position()['left']
}, {
duration: 350
});
TabbedContent.slideContent($(this));
});
},
slideContent: function(obj) {
var margin = $(obj).parent().parent().find(".sliderContainer").width();
margin = margin * ($(obj).prevAll().size() - 1);
margin = margin * -1;
$(obj).parent().parent().find(".displayContent").stop().animate({
marginLeft: margin + "px"
}, {
duration: 1
});
},
gotab: function( obj ) {
var background = $(obj).parent().find(".selected");
$(background).stop().animate({
left: $(obj).position()['left']
}, {
duration: 1
});
TabbedContent.slideContent( $(obj) );
}
}
$(document).ready(function() {
TabbedContent.init();
});
Here's how a tab is initialized when it is linked to:
<?php
// Load a specific tab if required
if(isset($_GET['tab'])) {
// Array storing possible tab IDs
$tabChoices = array('productsTab', 'specsTab', 'brochuresTab', 'bannersTab', 'kitsTab', 'displaysTab');
$tab = '';
if(in_array($_GET['tab'], $tabChoices)) $tab = $_GET['tab'];
// Default to productsTab if not in array list
else $tab = 'productsTab';
// JS to actually do the switch
echo '<script>$(document).ready(function() {TabbedContent.gotab($("#' . $tab . '"))});</script>';
}
?>
You're painting yourself into a corner by inline scripting a solution. You should always only have one $(document).ready... call in your entire product, in order to avoid order dependent explosions in code, and have a clear point of entry.
That said, you are almost there. Instead of calling a function, assign a value.
echo "<script>var selectedTab=$tab;</script>"
Then during your initialization function, make use of that value. My example is in global scope. There may be a race condition if you try to assign it to a namespace. In that case, try putting that script at the bottom of the page.
One more suggestion, have one and only one function handle all of your animations calls for that object.
Instead of using get/post params you could use hash; creating links like this in the tabs:
<a class="tab_item" href="#one_go" id="one">
And then put this in the javascript:
var gototab = document.location.hash.replace('_go',"")
if(gototab){
$(gototab).each(function(){
var pos = $(this).prevAll(".tab_item").length,
left = pos * $(this).outerWidth(),
margin = pos * $(this).parent().parent().find(".slide_content").width() * -1;
$(this).parent().find('.moving_bg').css('left',left)
$(this).parent().parent().find(".tabslider").css('margin-left',margin)
})
}

Categories