I got a progress bar that runs after clicking submit.
The app will then process the background task and update the progress bar.
The question is how can I show the download button after the progress bar hits 100% instead of showing the button when the progress bar starts updating?
$('form').on('submit', function(event) {
event.preventDefault();
var formData = new FormData(this);
// add task status elements
div = $('<div class="progress"><div></div><div>0%</div><div>...</div></div>');
$('#progress').append(div);
// progress bar
var nanobar = new Nanobar({
bg: '#03adff',
target: div[0].childNodes[0]
});
$.ajax({
type: 'POST',
url: '/longtask',
data: formData,
processData: false,
contentType: false,
success: function(data, status, request) {
status_url = request.getResponseHeader('Location');
update_progress(status_url, nanobar, div[0]);
},
complete: function() {
$("#dl").css("display", "block");
},
error: function() {
alert('Unexpected error');
}
});
})
function update_progress(status_url, nanobar, status_div) {
// send GET request to status URL
$.getJSON(status_url, function(data) {
percent = parseInt(data['current'] * 100 / data['total']);
nanobar.go(percent);
$(status_div.childNodes[1]).text(percent + '%');
$(status_div.childNodes[2]).text(data['status']);
if (data['state'] != 'PENDING' && data['state'] != 'PROGRESS') {
if ('result' in data) {
// show result
$(status_div.childNodes[3]).text('Result: ' + data['result']);
} else {
// something unexpected happened
$(status_div.childNodes[3]).text('Result: ' + data['state']);
}
} else {
setTimeout(function() {
update_progress(status_url, nanobar, status_div);
}, 1000);
}
});
}
Assuming #dl is you download button.
You could just move the $("#dl").css("display", "block"); into your update_progress function:
$('form').on('submit', function(event) {
event.preventDefault();
var formData = new FormData(this);
// add task status elements
div = $('<div class="progress"><div></div><div>0%</div><div>...</div></div>');
$('#progress').append(div);
// progress bar
var nanobar = new Nanobar({
bg: '#03adff',
target: div[0].childNodes[0]
});
$.ajax({
type: 'POST',
url: '/longtask',
data: formData,
processData: false,
contentType: false,
success: function(data, status, request) {
status_url = request.getResponseHeader('Location');
update_progress(status_url, nanobar, div[0]);
},
error: function() {
alert('Unexpected error');
}
});
})
function update_progress(status_url, nanobar, status_div) {
// send GET request to status URL
$.getJSON(status_url, function(data) {
percent = parseInt(data['current'] * 100 / data['total']);
nanobar.go(percent);
$(status_div.childNodes[1]).text(percent + '%');
$(status_div.childNodes[2]).text(data['status']);
if (data['state'] != 'PENDING' && data['state'] != 'PROGRESS') {
if ('result' in data) {
// Show download button once done
$("#dl").css("display", "block");
// show result
$(status_div.childNodes[3]).text('Result: ' + data['result']);
} else {
// something unexpected happened
$(status_div.childNodes[3]).text('Result: ' + data['state']);
}
} else {
setTimeout(function() {
update_progress(status_url, nanobar, status_div);
}, 1000);
}
});
}
Related
i created js code that when user change some file input its send POST request to server and upload the file.
but the JS side very slow if i try to upload 4MB image, the PHP file start after 1 min
i tried to add some log to the php file and i saw that its another to the start of the file after 1 min.
this is the JS code:
$("input[name='upload-avatar-input']").on('change', function () {
const me = this;
setLoading(true);
if (this.files.length > 0) {
if (!window.FormData) {
alert("Error!");
return false;
}
const url = $(this).closest("form").attr("action");
$.ajax({
url: url,
method: 'POST',
dataType: 'json',
data: new FormData(this.form),
contentType: false,
processData: false,
beforeSend: function () {
if ($(".myformPop").length <= 0)
$("body").append('<div class="myformPop"><i class="close">close</i><div class="heading"></div><div class="output"></div></div>');
},
success: function (data) {
if (data.success === 1) {
const t = new Date().getTime();
const img = $(me).closest("form").find("#avatarCircle .inner");
img.css("background-image", "url('" + data.url + "?t=" + t + "')");
$('.delete-avatar-button').attr("disabled", false);
} else {
const pop = $(".myformPop");
pop.find("div.heading").html(data.heading);
pop.find("div.output").html('<ul>' + data.message + '</ul>');
$.getScript("assets/js/jquery.bpopup-0.7.0.min.js", function (bpop_data, textStatus, jqxhr) {
pop.bPopup({
bmodalClose: false,
onClose: function () { }
});
});
}
setLoading(false);
},
complete: function () { },
error: function () {
setLoading(false);
}
});
} else {
setLoading(false);
}
});
and the url variable is some php file that upload the file, but the file started after 1 min, so the problem in the js code.
what can i do with large files like 4MB - 8MB (its normal size of mobile hd images)
tnx
I'm using this jsFuddle http://jsfiddle.net/GvdSy/ for implementing progress bar. But the problem is that bar starts loading only after I get response from API not when I create a request for API.
How can I start loading the progress bar as soon as I Start initiating the API call(click on button) and make it to 100% only after I get a response from API i.e. Progress bar should be consistent with the whole duration.
This is the code I used:
$.ajax({
cache: false,
type: "Post",
data: "",
async: true,
url: "/Apps/AddConnector?connectorId=" + connectorId + "&consumer=" + consumer,
xhr: function () {
var xhr = $.ajaxSettings.xhr();
xhr.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
progressBar.css({
width: percentComplete * 100 + '%'
});
}
}, false);
return xhr;
},
success: function (Response) {
if (Response.Status == "Success") {
try { mixpanel.track('Application', { 'App Id': connectorId }, { 'Action': 'added' }); } catch (ex) { }
try { ga('send', 'event', 'Applications', connectorId, 'apps_added'); } catch (ex) { }
progressLabel.text("Installed");
}
else {
progressLabel.text(Response.Message);
setTimeout(function(){flipInstance.slideToggle("slow");},2000);
}
},
error: function (xhr, e) {
if (!HandleAjaxError(xhr, e, "")) {
progressLabel.text(e);
}
},
});
$.ajax({
cache: false,
type: "Post",
data: "",
async: true,
url: "/Apps/AddConnector?connectorId=" + connectorId + "&consumer=" + consumer,
xhr: function () {
var xhr = $.ajaxSettings.xhr();
xhr.addEventListener("progress", function (evt) {
if (evt.lengthComputable && evt.loaded) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
progressBar.css({
width: percentComplete * 100 + '%'
});
// HERE IS WHERE YOU IMPLEMENT AN ELSE, BEFORE evt.lengthComputable is truthy
} else {
progressBar.css({
width: '2%'
});
}
}, false);
return xhr;
},
success: function (Response) {
if (Response.Status == "Success") {
try { mixpanel.track('Application', { 'App Id': connectorId }, { 'Action': 'added' }); } catch (ex) { }
try { ga('send', 'event', 'Applications', connectorId, 'apps_added'); } catch (ex) { }
progressLabel.text("Installed");
}
else {
progressLabel.text(Response.Message);
setTimeout(function(){flipInstance.slideToggle("slow");},2000);
}
},
error: function (xhr, e) {
if (!HandleAjaxError(xhr, e, "")) {
progressLabel.text(e);
}
},
});
I am using following code to fetch and cache data from a ASP.NET handler. The problem is that whenever I cache data using a button click its working fine, but I want this to happen at document.ready() event. When I executed this code on document.ready() event, its fetching data perfectly, but its not getting data from the cache when I reload the page.
var localCache = {
data: {},
remove: function (url) {
delete localCache.data[url];
},
exist: function (url) {
return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null;
},
get: function (url) {
console.log('Getting in cache for url' + url);
return localCache.data[url];
},
set: function (url, cachedData, callback) {
cacheTime = (new Date()).getTime();
localCache.remove(url);
localCache.data[url] = cachedData;
if ($.isFunction(callback)) callback(cachedData);
}
};
var now;
var cacheTime;
var tDiff;
function getValueAtIndex(index) {
var str = window.location.href;
return str.split("/")[index];
}
//$(document).ready(function () {
$('#Button1').click(function (e) {
var url = '/Handlers/ResponseFetcher.ashx';
var topicid = "<%=desid %>";
$.ajax({
url: url,
type: "POST",
data:
JSON.stringify({ tid: topicid })
,
dataType: "json",
cache: true,
beforeSend: function () {
now = (new Date()).getTime();
if (localCache.exist(url)) {
tDiff = now - cacheTime;
if (tDiff < 20000) {
loadData(localCache.get(url));
return false;
}
}
return true;
},
complete: function (jqXHR, textStatus) {
localCache.set(url, jqXHR, loadData);
}
});
});
function loadData(data) {
console.log("now: " + now + ", cacheTime: " + cacheTime + ", tDiff:" + (cacheTime - now));
$('#responseloader').hide();
var resdata = JSON.parse(data.responseText);
$(resdata).each(function (i) {
$('#responsecontainer').append("<div>" + this.Title + "</div>");
});
}
Here tDiff will be undefined on first run. Is this the problem? or caching doesn't work if the page is reloaded? Please help!
I have below code, it executes when I click on a button.
I need to display a progress bar/waiting image in the browser for 5 seconds, when user clicks on a button. How to set time out and how to display progress bar/waiting page image in the page when user clicks on a button
$("#btnSubmit").click(function(){
var formData = $("form").serialize();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
},
failure: function () {
alert("Ajax request failed!!!");
},error: function () {
alert("Ajax request failed to update data!!!");
}
});
});
i could able to fix my code with the link jsfiddle.net/joshdavenport/Qw6uv/4 , this works fine..
Use beforeSend and complete
$("#btnSubmit").click(function(){
var formData = $("form").serialize();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
},
failure: function () {
alert("Ajax request failed!!!");
},error: function () {
alert("Ajax request failed to update data!!!");
},
beforeSend: function(){
$('.progress').show();
},
complete: function(){
$('.progress').hide();
}
});
});
HTML
<div class="progress" style="display:none;"><img src="loading.gif" />Loading...</div>
$("#btnSubmit").click(function(){
var startTime = Date.now(),
// finish function is called at the end - when request is completed and at least 5s passed
// result will be null on error or whatever was received by success callback
finish = function (result) {
if (result === null) {
// probably error, handle it..
} else {
// handle result
}
$('#progress').hide();
},
checkDone = function (result) {
var r = Date.now() - startTime; // time taken by request
if (r < 5000) { // if less than 5s then set timeout for remaining time
setTimeout(function () {
finish(result);
}, 5000 - r);
} else { // if there was already 5s finish immediately
finish(result);
}
},
formData = $("form").serialize();
$('#progress').show();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
checkDone(result);
},
failure: function () {
alert("Ajax request failed!!!");
checkDone(null);
},
error: function () {
alert("Ajax request failed to update data!!!");
checkDone(null);
}
});
});
progress div example (just put in body):
<div id="progress" style="display:none;position:absolute;z-index:99999;top:0;left:0;width:100%;height:100%;opcity:0.7;background:url('/img/progress.gif') 50% 50% no-repeate #000"></div>
in my MVC layout page I have the following:
$("body").ajaxError(
function (e, request) {
if (request.status == 403 || request.status == 500) {
window.location = '#Url.Action("LogOn", "Account", new {area = "", msg = "forbidden", returnUrl = HttpContext.Current.Request.RawUrl})' + window.location.hash;
return;
}
window.location = '#Url.Action("Index", "Error")';
}
);
on another page I'm performing an ajax call like so:
...
$.when(refreshActionLinks(row, machineId, packageId)).done(function(a1) {
row.find("span").text(opStatus).removeClass("pending");
progressbar.progressbar("destroy");
$(row).flash(bg[1], 1000);
});
...
javascript function:
function refreshActionLinks($row, machineId, packageId) {
try {
var json = JSON.stringify({ packageId: packageId, machineId: machineId, tabType: $("#TabType").val() });
console.log("refreshActionLinks => " + json);
$row.find("td.options div.actionLinks").html("<img src='#Url.Content("~/Content/images/ajax-load2.gif")' />"); // pending
return $.ajax({
url: "#Url.Action("GetActionLinks", "Packages")",
data: json,
timeout: 50000,
contentType: 'application/json',
type: 'POST',
success: function (data) {
if ($row.length) {
$row.find("td.options div.actionLinks").html(data);
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
} catch(e) {
// hide icons
$row.find("a.action").remove();
}
}
The issue is that while refreshAction function is executing, clicking a menu link causes the ajax call to error out - which in this case is correct. BUT it does take me to /Index/Error page which is NOT correct. I would like "$("body").ajaxError" to handle all ajax errors on the site EXCEPT on the page I'm calling refreshActionLinks. Notice, I already have try/catch surrounding my ajax call. why doesn't that work?
thanks
figured it out:
ajax has a settings:
global: false
now my function looks like this:
function refreshActionLinks($row, machineId, packageId) {
try {
var json = JSON.stringify({ packageId: packageId, machineId: machineId, tabType: $("#TabType").val() });
console.log("refreshActionLinks => " + json);
$row.find("td.options div.actionLinks").html("<img src='#Url.Content("~/Content/images/ajax-load2.gif")' />"); // pending
return $.ajax({
url: "#Url.Action("GetActionLinks", "Packages")",
global: false, // disable error pages on failed ajax calls
data: json,
timeout: 50000,
contentType: 'application/json',
type: 'POST',
success: function (data) {
if ($row.length) {
$row.find("td.options div.actionLinks").html(data);
}
}
});
} catch(e) {
// hide icons
$row.find("a.action").remove();
}
}