I´m having several problems with a progress bar in one of my developments.
I have a JavaScript function which launch serveral Ajax calls which call a PHP process, all at the same time. Those Ajax calls represent a percentage of a bigger proccess, so, for example, if I launch 100 ajax calls each one represent a 1% of the process.
The problem is that I can't force re-draw the HTTP DOM via JavaScript when an Ajax call ends.
So, the imports are these:
<link rel="stylesheet" href="(...)/javascript/themes/base/ui.core.css">
<link rel="stylesheet" href="(...)/javascript/themes/base/ui.theme.css">
<script src="(...)/js/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
And the important code is the next one:
Creation of progressbar (before launch Ajax calls):
$("#progressbar").progressbar({max:100, value:0});
$("#progressbar").progressbar("enable");
Every Ajax call will modify a variable when they finish. When I launch all Ajax calls I create an Observer function with JavaScript setTimeout, which looks at that variable and get the percentage:
setTimeout (function(){
(...)
var percentage = Math.round(((proccessedLines)/totalLines)*100);
$("#progressbar").progressbar("value", percentage);
(...)
}, 500);
And, finally, that $("#progressbar") is just a div HTML tag with that name.
So, the problem is that timeout. It supposed to update that progressbar value and update the DOM, it should to be redrawn but It doesn´t work as It should.
Any ideas?
I have to point one more thing: this process was working perfectly 'till 2 days ago; could be some new changes in the browsers?
The setTimeout function is just executed one time after 500ms. Maybe use the setInterval function to execute your function every 500ms or consider this snippet: https://jsfiddle.net/nicolastorre/o35teyq3/32/
// Parameters
var queryList = new Array('code', 'js', 'php');
var lenQueryList = queryList.length;
var percentage = 0;
var proceed = 0;
var totalPercentage = 100;
// Init progress bar
$("#progressbar").progressbar({max:totalPercentage, value:percentage});
$("#progressbar").progressbar("enable");
for(var i = 0; i < lenQueryList; i++) {
/*### setTimeout to make a pause (just for the demo) ###*/
setTimeout(function() {
console.log('just a pause to see slowly!');
console.log(queryList[i]);
// Wikipedia api search
$.ajax({
url: 'https://en.wikipedia.org/w/api.php?callback=?',
data: {
srsearch: queryList[i],
action: "query",
list: "search",
format: "json"
},
error: function() {
console.log('An error occured');
},
dataType: 'json',
success: function(data) {
// Get results
console.log(data);
// Update progress bar
proceed++;
percentage = Math.round((proceed/lenQueryList)*totalPercentage);
$("#progressbar").progressbar("value", percentage);
},
type: 'POST'
});
}, 500 * i); // setTimeout to make a pause (just for the demo)
/*########################################*/
}
Related
I have a flask-environment running server-sided, which calculates the distance between it's current position (GPS-Module attached to the server) and given coordinates. I want a text to update when a certain event occurs. It should keep updating until a different event occurs.
This is my function to update the distance:
function getDistToCurPos(lat, lon) {
$.getJSON('/getDistFromCurPosToPoint', {
pLat: lat,
pLon: lon,
},
function(data){
dist = data;
let distStr = String(dist);
let outStr = '<div class="distanceOutput"> Distance: '.concat(distStr).concat("</div>");
$( "div.distanceOutput" ).replaceWith( outStr );
});
};
When the start-event occurs, I call the function as follows (with example-values 38 and 9):
distRefreshID = setInterval(function() { getDistToCurPos(38,9); }, distUpdateTime);
distUpdateTime is set to 500. The server response takes 15 ms in average.
Initial state of the text:
<div class="distanceOutput">Inactive !</div>
To terminate updating the text, I call the following, when a different event occurs:
if ( distRefreshID !== 0) {
clearInterval(distRefreshID);
$( "div.distanceOutput" ).replaceWith('<div class="distanceOutput">Inactive again!</div>');
distRefreshID = 0;
}
The code works in general. But when the stop-event occurs, I see "Inactive again!" only for a short moment. After that, the text keeps getting updated with the current values for a few seconds.
Any tips, where my bug is ?
setInterval does not initially call the function, it calls it after x milliseconds have passed so if you want to instantly update the content call the function right before setting the interval
getDistToCurPos(38,9);
distRefreshID = setInterval(function() { getDistToCurPos(38,9); }, distUpdateTime);
Well I am unable to lazy load images for some reason. Here is the waterfall view of the tested site
Apparently I am using two lazy load scripts with lazy load script 1 which works but kills the lightbox plugin and also requires lots of tweaking using data-src and src and class="lazy-load" attributes. which I am using for non post related images.
But the main problem lies in the second script which requires Jquery but doesn't require any tweaking with the images. The script is called stalactite (via Github) which I am using like this
<script charset='utf-8' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' type='text/javascript' />
<script href='http://googledrive.com/host/0B2xMFcMT-eLiV1owdlBMeklGc2M' type='text/javascript' />
<script type='text/javascript'>
$( 'body').stalactite({
loader: '<img/>' // The contents of the loader. Defaults to a dataURL animated gif.
});
</script>
You can find the link of the stalactite script in the above code and here is the documentation.
I don't know why it doesn't work ! Or am I executing it wrongly.
A solution to the problem will be very helpful. Many thanks in advance.
If you are tired of trying to use lazy load libraries and haven't managed to make all of it work, I can suggest you to create lazy load script on your own, or you can take a look at this code below.
By only using jQuery and without needing any other library, you can use this script to achieve the lazy load (I modified the codes from the original one that I used at work):
var doLazyLoad = true;
var lazyLoadCounter = 0;
var lazyLoadMax = 2; // Maximum number of lazy load done
// Button to indicate lazy load is loading,
// or when lazy load has reached its maximum number,
// this button load data manually.
// You can replace this with something like gif loading animation.
var $btnLoadMore = $("#btn-lazy-load-more");
// I use AJAX function to get the data on lazy load
var ajaxFn = function (enableScrollAnim = true) {
var loadingStr = 'Loading...',
idleStr = 'Load more',
ajaxUrl = 'http://www.example.com/posts',
ajaxHeaders = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
ajaxData = {
start: $('.posts-wrapper .post').length
};
$btnLoadMore.text(loadingStr); // You can disable the button to prevent manual loading
return $.ajax({
url: ajaxUrl,
type: 'GET',
dataType: 'json',
data: ajaxData,
headers: ajaxHeaders,
// On success AJAX, append newly loaded data to lazy load container.
// Here in my example, the GET request returns data.view i.e. the content, and data.total i.e. total number of posts
success: function (data) {
var $newLoadedPosts = $(data.view),
nlsMarginBottom;
$('.posts-wrapper').append($newLoadedPosts);
$newLoadedPosts.css('display', 'none').fadeIn();
// Animate auto scroll to newly loaded content
if (enableScrollAnim) {
$('html, body').animate({
scrollTop: $newLoadedPosts.first().offset().top
});
}
if ($('.posts-wrapper .post').length < data.total) {
$btnLoadMore.text(idleStr); // If you disable the button, enable the button again here
} else {
// Remove the button when there's no more content to load.
// Determined by data.total
$btnLoadMore.remove();
}
},
error: function () {
$btnLoadMore.text(idleStr); // If you disable the button, enable the button again here
}
});
};
// Do the lazy load here
if ($btnLoadMore.length) {
$(window).scroll(function () {
var scrollOffset = (($btnLoadMore.offset().top - $(window).height()) + $btnLoadMore.height()) + 100;
var hasReachedOffset = $(window).scrollTop() >= scrollOffset;
var isLmsBtnExist = $btnLoadMore.length;
if (hasReachedOffset && lazyLoadCounter < lazyLoadMax && doLazyLoad && isLmsBtnExist) {
doLazyLoad = false;
ajaxFn(false).always(function () {
doLazyLoad = true;
lazyLoadCounter++;
});
}
});
}
$btnLoadMore.click(ajaxFn);
And here is the GIF demo image of my working code.
If you need any further explanation, just comment this answer and I will try to help you.
I'm trying to write a function that increments a variable, which will later be stored as post meta for the WordPress post, by clicking the posts title. In other words, I want to a create function that keep track of how many times a post title of a certain post is being clicked.
I'm new to using jQuery so I'm trying to figure out how to get the 2 function in PHP and jQuery to interact. I need to process the data in PHP later, which is why I need to do this.
This is what I have so far (PHP):
function clickScoreMethod($postid){
//$clickScore = 0;
$clickScore = get_post_meta($postid, 'redditclickscore', true);
$clickScore = $clickScore + 0.25;
update_post_meta($postid, 'redditclickscore',$clickScore);
}
$clickScore is the variable I want to increase by 0.25 every time the post title is clicked. I'm using meta to store it easily per post. If it is simpler, I can also increase the score by just incrementing the variable and then dividing it by 4 when I process it in the PHP later.
The jQuery:
$("li.post-item article").each(function(){
$( ".the-post-container .entry-title" ).click(function() {
var clickScore = 0.25;
});
});
.entry-title is the post title and .post-item-article is basically the blog roll.
I have no idea how to get these two to work together so that I increase the number.
Use ajax to do this.
Your jQuery would look something like this:
$("li.post-item article").each(function () {
$(".the-post-container .entry-title").click(function () {
var clickScore = 0.25;
$.ajax({
url: "/path/to/php/file",
type: "POST",
data: { clickScore: clickScore },
success: function () {
console.log("Success!");
}
});
});
});
and you would access the variable and do stuff with it with this (in PHP):
$clickScore = $_POST["clickScore"]
Hope this helps you.
This question already has answers here:
How to wait for one jquery animation to finish before the next one begins?
(6 answers)
Closed 1 year ago.
I am having trouble changing the contents of a div. What I want to achieve is wait for the animation to end and then change the content to launch the animation to reveal the new info. This code works from time to time, meaning sometimes it hangs (isWorking never becomes false, because animation freezes or animation never has the time to finish from the constant looping inside the while.) Is there a way to wait for the animation to end and then change the content? (The way you see it below allows me to browse for the new content while the animation is ongoing which saves time for the end user.) Is there a way to catch when the animation ends?
function DesignResults(InnerHTML) {
while(isWorking){
}
$("#holder").html(InnerHTML);
ShowSearch(true);
}
var isWorking = false;
function ShowSearch(show) {
isWorking = true;
var outer = $("#outer");
var inner = $("#inner");
var height = 0;
if (show == true)
height = inner.outerHeight();
var loaderHeight
if (height > 0) {
loaderHeight = 0;
} else {
loaderHeight = 31;
}
outer.animate({
'height': height + "px"
}, 1600, function () {
$("#loading").animate({ 'height': loaderHeight + "px" }, 900, function () { });
isWorking = false;
});
}
I understand that $(elem).is(':animated') will give me if the animation is still in progress, but that still freezes everything due to the constant looping of the while. Can anyone point me to the right direction?
EDIT:
I guess I am misunderstood. Here is the plan I want to achieve:
Start hiding animation.
While the animation is hiding I am launching another function to get the content
If I get the content faster I wish to wait for the animation to end then change the content and show the layer again.
There isn't a issue here if the data takes more than a second to return
I agree that i can do it after the animation completes as you suggested, but I have put the animation to almost 1 second execute time and that time can be used for the data to be pulled from the database. I am looking for the most effective code.
The last parameter in this function:
$("#loading").animate({ 'height': loaderHeight + "px" }, 900, function () { });
Is the 'complete' function. This function is called when the animation is complete.
So, you can do something in this function when it's complete, like so:
$("#loading").animate({ 'height': loaderHeight + "px" }, 900, function () {
alert('animations complete!');
});
----Edit----
Based on your edits, you probably want to do something like this.
Have a variable that will let you know when both are finished:
var signal = 0;
Have a function to change your content with this in it:
function changeContent() {
signal++;
if (signal === 2) {
// change the content code here
signal = 0;
}
}
When the animation is finished, call:
changeContent();
When you've grabbed the data, call:
changeContent();
When changeContent() is called the first time by either function, it will increment signal to 1 and exit the function. Then on the second time, it will increment signal to 2. Since signal === 2, you know that both the animation and grabbing the data is complete, so you can now change your content.
The good part about using an integer to do this, is if you want to have 3, 4, 5+ functions finish working before changing your content. In this case you just have to change the condition by increasing the number in if (signal === 2).
Just add the additional task here
$("#loading").animate({ 'height': loaderHeight + "px" }, 900, function () { /* Change Content */ });
Than it would be execute after the animation
I am working on the adobe air with javascript and html. I want to run multiple functions in a function with show the percentange run on the each function but the percentage also show the last calculation please help me.
Edit: added code snippet from comment, but I may have butchered the layout.
function show_percentage() {
down_admin()
down_staff()
down_client() }
function down_admin() {
down all information of admin from the server; flag=1; }
function down_staff() {
down all information of the staff falg=2; }
we want to calculation show the every after loaded functions. as percentage=25% to 100%
If you downloading several types of info and want to show summary progress, first you need to know bytes total of each download. When you get ProgressEvent from each operation, you may call function show():
function show() {
var progress = (adminBytesLoaded + staffBytesLoaded + clientBytesLoaded) * 100 /
(adminBytesTotal + staffBytesTotal + clientBytesTotal);
//show progress somehow
}
Update: some clarifications
Load resource you need with Loader. Add event listener to ProgressEvent on Loader.contentLoaderInfo. There will be three listeners for three load operations - load admin data, client data and staff data. When you get progress event from each operation (track it with three vars), you will know download size total:
var adminTotal:int;
var clientTotal:int;
var staffTotal:int;
var adminLoaded:int;
var clientLoaded:int;
var staffLoaded:int;
function onAdminLoadProgress(event:ProgressEvent):void
{
adminLoaded = event.bytesLoaded;
adminTotal = event.bytesTotal;
//if other operations already going, show progress
if (clientTotal && staffTotal)
{
showProgress();
}
}
function onClientLoadProgress(event:ProgressEvent):void
{
clientLoaded = event.bytesLoaded;
clientTotal = event.bytesTotal;
if (adminTotal && staffTotal)
{
showProgress();
}
}
//write onStaffLoaded yourself as an exercise :)))
I'm assuming you will make single request for each of those three downloads.