Basically I have created a simple project where users can drag and drop to upload a file to server. Just to inform the user how long would it take to complete the process I need to show their upload speed. I found this question estimate users' upload speed without direct permission But It quite didn't suited my project.
So here is my code how i'm upload the file:
function upload(file){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
}
}
xhr.upload.addEventListener('progress', function(e){
$('.upgbar').show();
$('.trkpb').css('width', (e.loaded/e.total*100)+"%");
var loaded = e.loaded;
var total = e.total;
var progressValue = Math.round( ( e.loaded / e.total ) * 100 );
var seconds_elapsed = ( new Date().getTime() - started_at.getTime() )/1000; var bytes_per_second = seconds_elapsed ? loaded / seconds_elapsed : 0 ;
var Kbytes_per_second = bytes_per_second / 1000 ;
var remaining_bytes = total - loaded;
var seconds = seconds_elapsed ? remaining_bytes / bytes_per_second : 'calculating' ;
$('.time_re').text("Time Remaining: "+seconds.charAt(0));
}, false);
xhr.open('post','../uploadtostack',true);
xhr.setRequestHeader('X-File-Name',file.name);
xhr.setRequestHeader('x-File-Size',file.size);
xhr.setRequestHeader('X-File-Type',file.type);
xhr.send(file);
}
through xhr.upload.addEventListener I can estimate the time remaining and the amount of data uploaded But don't know to munipulate this to show me the upload speed. and If you Might why am I getting an error at line $('.time_re').text("Time Remaining: "+seconds.charAt(0));
TypeError: seconds.charAt is not a function[Learn More]
I would really appreciate if someone could tell me how to implement a speechecker in javascript || jquery. Regards
You can try send a defined size file before and calculate the estimate time with this.
Example: demo file.txt > size 10k 1 second
another: filetoupload.txt > size 20k expected time 2 seconds
Related
I created a photo app. It runs in the browser, and what it does is this:
it runs every minute, goes to the server to get a random filename (from all the files on the server) with randomfilename.php, then load and places that in a hidden image named 'next' (image.php?filename=).
Then the next minute, it puts the image from the hidden 'next' image in the image called 'current', (the image called 'current' is what the user sees) and then it loads another image from the server in 'next'. And so on.
The reason I first preload the image in the 'next' image, is that it runs on a Raspberry Pi and it's not so quick in loading the image. When it takes 2 or 3 seconds, it doesn't look so smooth.
So now it has almost a minute to get the image and put it in 'next', and then instant it loads in 'current' (what the user sees) with this code: document.getElementById('current').src = document.getElementById('next').src;
This works....until the browser kept crashing, and when loading it from my pc and inspect memory, I saw the browser memory go up and up, and I understand why the limited memory Pi would crash.
So first I deleted all console.logs, didn't help.
Then I commented the code to load the image in next, and the code to copy the image from 'next' to 'current'. So the script was still getting the filename and the image from server, but didn't do anything with it. And at this time the memory didn't go up.
So I am wondering, what am I doing wrong with my setup? Does it hold all images in memory, doesn't it free memory from the previous image when I load a new one in 'next' and in 'current'?
Do I have to say (pseudocode) document.getElementById('current').clear() or remove it from DOM and then create a new one?
All help and tips on my code is welcome.
EDIT 1: the memory usage:
I've created 3 snapshots in FireFox, at t=0, t=.5 hours and t = 7 hours, it's 3.1 , 4.85 and 3.55 MB. So not a lot.
The same moments, the memory usage of FireFox in the task manager: 450 Mb, 943 MB and 4902 MB. So this is quite a lot.
Could it be that all images are stored/cached/remembered in the tabpage?
$( document ).ready(function() {
var currentFileName = '';
var nextFileName = '';
var latestRetrievedFile = 'pending...';
setInterval( refreshAfbeelding , 60000 );
function refreshAfbeelding(){
setTimeout(function(){
document.getElementById('current').src = document.getElementById('next').src;
setTimeout(function(){
$( "#current" ).fadeTo( 1500 , 1, function() {
d = new Date().toISOString();
$.get( "randomfilename.php?id=" + d, function( data ) {
data = $.trim(data);
parts = data.split("|");
document.getElementById('next').src = "image.php?filename=" + parts[1];
latestRetrievedFile = parts[0];
});
});
}, 0);
}, 1500);
$( "#current" ).fadeTo( 1500 , 0, function() {
});
};
});
Edit 2
Even with the simplest code, without fade en nifty timeouts, it still creates the same amount of memory, in the Windows process
var currentFileName = '';
var nextFileName = '';
var latestRetrievedFile = 'pending...';
var currentFileName = '/twee.jpg';
var nextFileName = '/een.jpg';
function refreshAfbeelding() {
document.getElementById('current').src = document.getElementById('next').src;
document.getElementById("imagename").innerHTML = latestRetrievedFile;
var d = new Date().toISOString();
$.get( "randomfilename.php?id=" + d, function( data ) {
var dataTrimmed = $.trim(data);
var parts = dataTrimmed.split("|");
document.getElementById('next').src = "image.php?filename=" + parts[1];
latestRetrievedFile = parts[0];
});
}
setInterval( refreshAfbeelding , 60000 );
When creating an animation I try to use javascript for additional effects, namely snow being piled up and falling off the edges of the foreground. I figured that the javascript could do the "calculations" on a <canvas> that had the image, then send the "snow" to a php script that would create the png images. This is all placed on my local "server" because that is the only one that can write files.
<html>
<head>
<title>Making Snow</title>
</head>
<body bgcolor="black">
<canvas id="canvas" width="1920px" height="1080px"></canvas>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
var canvas;
var ctx;
var frame=-530;
var simg = new Image()
var dimg = new Image()
onload = function()
{
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
simg.src = "prodB/C/DGB.0530.png"
}
simg.onload = function()
{
var ipo=3;
// Initialize all pixels on the screen/page
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(simg,0,0);
document.title = "Making Snow " + (frame+530) + " / 7000";
snowdraw();
}
dimg.onerror = function()
{
dimg.src = "../imagewriting/snow" + zeroFill(frame+530,4) + ".png";
}
dimg.onload = function()
{
frame++;
if(frame<530)
simg.src = "prodB/C/DGB.0530.png"
else if(frame>4400)
simg.src = "prodB/C/DGB.4400.png"
else
simg.src = "prodB/C/DGB." + zeroFill(frame,4) + ".png"
}
var snowdraw = function()
{
var temp;
var canvasData = "";
// console.log(screen);
// Animation
// Choose a random pixel at the top of the screen
if(frame<7000)
{
for(ny=canvas.height-2; ny>=0; ny--)
{ // Iterate through all the pixels starting from the bottom right corner.
for(nx=canvas.width-2; nx>=0; nx--)
{
canvasData=canvasData+"1";
}
}
$.ajax({
method: "POST",
url: "makesnow.php",
data:{ imgData: canvasData, frame: (frame+530) }
})
.done(function( msg ) {
dimg.src = "../imagewriting/snow" + zeroFill(frame+530,4) + ".png";
});
}
else
{
document.title = "COMPLETE";
}
}
// http://stackoverflow.com/questions/1267283/how-can-i-create-a-zerofilled-value-using-javascript
// by Peter Bailey http://stackoverflow.com/users/8815
function zeroFill( number, width )
{
width -= number.toString().length;
if ( width > 0 )
{
return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
}
return number + ""; // always return a string
}
</script>
</html>
However, on the 1640th frame (or more precisely frame=1110) ajax is suddenly undefined. The image snow1640.png is created, but the browser tells me ajax is not defined and won't advance passed Making Snow 1640 / 7000. Because of the small random nature for each "snow flake" I can't just pick it up from where I left off, as the snow would jump from one frame to the next. Though I did try that at one point and ajax still stopped after that frame.
I first ran it on the local machine running Firefox (http://127.0.0.1/...) then moved onto another machine on the network which is more powerful running Chrome and both died on that same frame. Thought it might be a memory or file limit so I moved the complete frames out of there. Still nothing.
EDIT: Code now snippit of just the problem.
Also, console.log for data and ajax.responseText seem to be generally empty, both during successful "renders" and when it starts iterating ajax is not defined (every other line empty, every other error).
EDIT: New development! Turns out that the error ReferenceError: ajax is not defined anyways gets called between frames (and the 404 when asking dimg if image was created).
EDIT: By typing in console.log($.ajax) after onload and commenting out simg.src I got function ajax().
Error persists, this time I expanded it to reveal the following:
success http://127.0.0.1/ag/makesnowBC.html 197:7
j http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js 2:27131
fireWith http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js 2:27949
x http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js 4:22242
b http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js 4:26298
EDIT: Changed the code to now use Synchronous ajax. This time there are no error messages what so ever, but it still stops at 1640.
I wrote the following function to process an AJAX request to fetch data:
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
xhr.onload = function() {
var txt1 = xhr.responsetxt1;
var heading = getheading(txt1);
if (heading == 'PASS') {
var file = "My_URL" + ".js";
downloadFile(file);
//My code to display a progress bar here?
} else {
//Logic to handle failure to load
}
};
Here is my downloadFile function to download the file. But, I don't understand how to:
Check if the download completed.
Display a progress bar to show the progress.
If you can add a description of how it works, that'd be great. Thanks.
function downloadFile(fileName) {
(function(d) {
var ref = d.getElementsByTagName('script')[0];
var js = d.createElement('script');
js.src = fileName;
ref.parentNode.insertBefore(js, ref);
// My code to display a progress bar here?
}(document));
}
AFAIK, script elements don't have progress events. Your best bet is to use an XHR to get the script's body, then count on the browser cache for a second fetch. The problem is that your script then needs to be parsed by the browser, and there doesn't seem to be events for that.
My solution is pure JS, so you can adapt it to whatever framework you're using. It assumes that actual download will be about 70% of the total time, and allocates 20 % to the browser parsing. I use a non-minified versionof the awesome three.js 3D library as a biggish source file.
because it is in another sandbox, progress callculation is inaccurate, but if you serve your own script that shouldn't be a problem.
keep in mind that this is a fairly stripped down implementation. I used a simple HR as a progress bar, for example.
//this is a rough size estimate for my example file
let TOTAL_ESTIMATE = 1016 * 1024;
// I use a hr as a
let bar = document.getElementById("progressbar");
let button = document.getElementById("dlbtn");
var js; // to hold the created dom element
var fileName; // to hold my cacheBusted script adress
/* this function will be called several times during (the first) download, with info about how much data is loaded */
function onProgress(e) {
var percentComplete = e.loaded / TOTAL_ESTIMATE;
if (e.lengthComputable) {
percentComplete = e.loaded / e.total;
}
p = Math.round(percentComplete * 100);
console.log("progress", p + "%,", e.loaded, "bytes loaded")
bar.style = "width: " + (5 + .6 * p) + "%"; // I just assume dl will be around 60-70% of total time
}
/* this function is called when info comes. at the end of the initial download, the readystate will be 4 so we then set the file's src attribute, triggering a re-download but taking advantage of the browser's cache. It's not ideal, and simply `eval` ing the data would probably yield better results. I just assumed you wanted a <script> tag on your page, and for it to be evaluated. */
function onReadyState(e) {
let r = e.target;
//this is lifted almost verbatim from http://vanilla-js.com/ ;)
if (r.readyState != 4 || r.status != 200)
return;
let l = r.responseText.length;
console.log("Success !", l, "bytes total (" + Math.round(l / 1024) + " KB )");
bar.style = "width: 70%";
//just add / to next line to toggle ending methods
/* you could speed up the proces by simply eval()ing the returned js. like so (please be aware of security concerns) :
eval.bind(window)(r.responseText);
onScriptLoaded();
/*/
js.src = fileName;
bar.style = "width: 80%";
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(js, ref);
//*/
};
//this is called when the script has been evaluated :
function onScriptLoaded() {
bar.style = "width: 100%; background-color: lightgreen;";
button.disabled = false;
console.log("script has been evaluated ?", THREE ? "yes" : "no"); // the demo file exposes window.THREE
}
function downloadFile(file) {
button.disabled = true;
(function(d) {
// this helps to test this script multiple times. don't keep it
fileName = file + "?bustCache=" + new Date().getTime();
console.log("inserting new script");
js = d.createElement('script');
js.type = "text/javascript";
js.defer = "defer";
js.async = "async";
var r = new XMLHttpRequest();
bar.style = "width: 5%"; //always react ASAP
r.addEventListener("progress", onProgress);
r.open("GET", fileName, true);
r.onreadystatechange = onReadyState;
js.onload = onScriptLoaded;
r.send();
// My code to display a progress bar here?
}(document));
}
#progressbar {
height: 6px;
border-radius: 3px;
width: 0%;
border-color: green;
background-color: green;
}
<button onclick="downloadFile('https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js', this)" id="dlbtn">Download</button>
<script id="dummy" type="text/javascript">
console.log("dummy script ready")
</script>
<hr id="progressbar" align="left" />
DISCLAIMER: I did not test this on Android. I tested ONLY in Chrome (desktop). You should see progress events writing to the browser console
var url = 'url/to/file/';
var request = new XMLHttpRequest();
request.responseType = "blob"; // Not sure if this is needed
request.open("POST", url);
var self = this;
request.onreadystatechange = function () {
if (request.readyState === 4) {
var file = $(self).data('file');
var anchor = document.createElement('a');
anchor.download = file;
anchor.href = window.URL.createObjectURL(request.response);
anchor.click();
}
};
request.addEventListener("progress", function (e) {
if(e.lengthComputable) {
var completedPercentage = e.loaded / e.total;
console.log("Completed: ", completedPercentage , "%");
}
}, false);
request.send();
Hope this helps.
Well, it depends much more on the programming language instead of client side. For example, PHP has http://php.net/manual/en/session.upload-progress.php
As for client side, Boris answer is a good example! Hope it helps.
I got a free source progress bar, and I wrote a script for it.
the script is here,
var nanobar = new Nanobar( options );
var loaded = 0;
var number_of_media = $("body img").length;
doProgress();
// function for the progress bar
function doProgress() {
$("img").load(function() {
loaded++;
var newWidthPercentage = (loaded / number_of_media) * 100;
nanobar.go(newWidthPercentage);
document.getElementById("showing").innerHTML = newWidthPercentage;
})
};
});
This. I think,
Loaded <-- (which gets + 1 every time an image finished loaded)
divided by
Number of total body images,,
and then multiplied by 100
So that this can make the percentage number of loading process.
Then I put that percentage number into the box of,
A Loading bar's destination point. (which is : nanobar.go( here ))
But the bar moves werid,
everytime I click the menu, it returns different.
so I made a box to display the percentage number ( in the red box you can see in the picture )
I don't understand how this kind of random numbers are coming out every time.
Please advice.
Consider....
6/7 = 0.8571428571;
0.8571428571 * 100 = 85.71428571;
So if you want to 'tidy' these long decimals, then you need to truncate the float. http://www.w3schools.com/jsref/jsref_tofixed.asp
var num = 0.8571428571 * 100;
var n = num.toFixed(2);
Then n == 85.71
I hope this helps.
I'm trying to detect when a video file has completed loading. i made it work successfully on firefox and safari but on chrome, buffered event behaves strange..
so,
in my local host chrome works fine but when i upload to server;
buffer percentage stops about %50 but buffers %100,
when page refreshed, percentage stay at %0 but it continues to buffering..
here is my javascript
function loaded()
{
var v = document.getElementById('myVideo');
var r = v.buffered;
var total = v.duration;
var current=v.currentTime;
var start = r.start(0);
var end = r.end(0);
var downloadPercent= Math.round((end / total)*100)
$("#loadProgress").css('width',downloadPercent+ '%');
if(downloadPercent==100){
$("#preloaderWrapper").fadeOut(function(){
document.getElementById('myVideo').play();
clearInterval(ratoteLoad);
$(this).remove();
});
}
}
$('#myVideo').bind('progress', function()
{
loaded();
});
any idea?
thank you
try this instead:
myVideoTag = document.getElementById('video');
myVideoTag.addEventListener('progress', function(e) {
var percent = null;
// FF4+, Chrome
if (myVideoTag && myVideoTag.buffered && myVideoTag.buffered.length > 0 && myVideoTag.buffered.end && myVideoTag.duration) {
percent = myVideoTag.buffered.end(0) / myVideoTag.duration;
}
// Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
// to be anything other than 0. If the byte count is available we use this instead.
// Browsers that support the else if do not seem to have the bufferedBytes value and
// should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
else if (myVideoTag && myVideoTag.bytesTotal != undefined && myVideoTag.bytesTotal > 0 && myVideoTag.bufferedBytes != undefined) {
percent = myVideoTag.bufferedBytes / myVideoTag.bytesTotal;
}
if (percent !== null) {
percent = 100 * Math.min(1, Math.max(0, percent));
// ... do something with var percent here (e.g. update the progress bar)
}
}, false);
... comments copied from mediaelement.js, code as well but adjusted for easier display here. I omitted the code for Firefox 3.0 as it's less than relevant.
working fine in all current browsers
PS: thx to John Dyer for mejs - great stuff ;)