Errechnet dir die Downloadzeit bei Angaben von Größe der Datei und Internet geschwindigkeit
Code
<html data-lt-installed="true"><head>
<meta charset="UTF-8">
<title>Download time calculator</title>
<style>
window,body{
width: 100%;
height: 100%;
}
body{
font-family: Helvetica, Arial, sans-serif;
background-color: #f8f8f8;
}
.content{
display:block;
margin-left:auto;
margin-right:auto;
width: 600px;
}
h1,h2,h3,h4{
color: #444;
}
.content #speed,
.content #file,
.content #results,
.content #downloadSimulatorWindow_{
margin-bottom: 20px;
border: 1px solid red;
border: 1px solid gray;
border-radius: 3px;
background-color: #EEE;
box-shadow: 0px 2px 3px rgba(0,0,0,0.5);
}
input, button{
font-size: 16pt;
}
#speed {
text-align: center;
}
#speed input{
font-size: 16pt;
text-align: right;
}
#speed .idkSpeed{
font-size: 8pt;
}
#speed .idkSpeed.mobile{
font-size: 11pt;
}
.overhead-p{
font-size: 8pt;
}
#file{
text-align: center;
}
#file input{
font-size: 16pt;
text-align: right;
}
.examples-p{
font-size: 8pt;
}
#results{
background-color: #FFF !important;
text-align: center;
visibility: hidden;
}
#results .time{
font-style:normal;
font-size:24px;
}
#results .time em{
font-style:normal;
font-size:32px;
}
#downloadSimulatorWindow {
position: relative;
width: 600px;
height: 99px;
color: gray;
opacity: 0.5;
border: 1px solid gray;
border-radius: 5px;
visibility: hidden;
box-shadow: 0px 1px 16px rgba(0,0,0,0.5);
}
#downloadSimulatorWindow .filename {
position: absolute;
left: 85px;
top: 18px;
width: 355px;
height: 15px;
}
#downloadSimulatorWindow .progresrbar {
position: absolute;
left: 85px;
top: 38px;
width: 398px;
height: 22px;
}
#downloadSimulatorWindow progress{
width: 100%;
}
#downloadSimulatorWindow .percent {
position: absolute;
left: 435px;
top: 15px;
width: 49px;
height: 17px;
text-align: right;
}
#downloadSimulatorWindow .details {
position: absolute;
left: 85px;
top: 63px;
width: 401px;
height: 19px;
padding-left: 0.5em;
font-size: 14px;
}
#downloadSimulatorWindow .icon {
position: absolute;
left: 10px;
top: 18px;
width: 64px;
height: 64px;
}
#downloadSimulatorWindow .ps {
position: absolute;
right: 0px;
bottom: -20px;
width: 514px;
height: 18px;
font-size: 10px;
text-align: right;
}
.footer{
text-align: center;
font-size: 9pt;
padding: 1em;
}
#calculateButton{
padding-left: 1em;
padding-right: 1em;
}
#speedtest_mobile{
display: none;
margin: 30px;
background: #333;
color: #FFF;
}
#speedtest_mobile a{
color: #FFF;
margin:20px;
}
.mobile-iphone-btn,
.mobile-windows-btn,
.mobile-android-btn,
.mobile-amazon-btn{
width: 230px;
height: 74px;
background: url(http://www.speedtest.net/mobile/../images/app-store-sprite.png);
background-position: 0px -2px;
display: block;
float: left;
display: inline-block;
}
.mobile-iphone-btn{
background-position: 0px -2px;
}
.mobile-windows-btn{
background-position: 245px -2px;
}
.mobile-android-btn{
background-position: 483px -2px;
}
.mobile-amazon-btn{
background-position: 0 -2px;
background: url(http://www.speedtest.net/mobile/../images/app-store-amazon.png);
}
.speedtest-mobile-ico{
width: 124px;
height: 124px;
background-image: url(http://www.speedtest.net/mobile/../images/placeholder-mobile-header.png);
-webkit-background-size: 124px 124px;
-moz-background-size: 124px 124px;
background-size: 124px 124px;
background-repeat: no-repeat;
width: 70px;
height: 70px;
-webkit-background-size: 70px 70px;
-moz-background-size: 70px 70px;
background-size: 70px 70px;
float: left;
margin-left: 8px;
margin-right: 15px;
margin-left: 50px;
margin-top: 35px;
display: inline-block;
}
/******/
.collapse{
font-size: 8pt;
display: block;
line-height: 44px;
color: gray;
}
.collapse:hover{
color: white;
-background-color: #FCFCFC;
}
.collapse + input{
display:none;
}
.collapse + input + div{
display:none;
}
.collapse+ input:checked + div{
display:block;
}
</style>
<script>
(function(a) {
function b() {
return {
empty: !1,
unusedTokens: [],
unusedInput: [],
overflow: -2,
charsLeftOver: 0,
nullInput: !1,
invalidMonth: null,
invalidFormat: !1,
userInvalidated: !1,
iso: !1
}
}
function c(a, b) {
return function(c) {
return k(a.call(this, c), b)
}
}
function d(a, b) {
return function(c) {
return this.lang().ordinal(a.call(this, c), b)
}
}
function e() {}
function f(a) {
w(a),
h(this, a)
}
function g(a) {
var b = q(a)
, c = b.year || 0
, d = b.month || 0
, e = b.week || 0
, f = b.day || 0
, g = b.hour || 0
, h = b.minute || 0
, i = b.second || 0
, j = b.millisecond || 0;
this._milliseconds = +j + 1e3 * i + 6e4 * h + 36e5 * g,
this._days = +f + 7 * e,
this._months = +d + 12 * c,
this._data = {},
this._bubble()
}
function h(a, b) {
for (var c in b)
b.hasOwnProperty(c) && (a[c] = b[c]);
return b.hasOwnProperty("toString") && (a.toString = b.toString),
b.hasOwnProperty("valueOf") && (a.valueOf = b.valueOf),
a
}
function i(a) {
var b, c = {};
for (b in a)
a.hasOwnProperty(b) && qb.hasOwnProperty(b) && (c[b] = a[b]);
return c
}
function j(a) {
return 0 > a ? Math.ceil(a) : Math.floor(a)
}
function k(a, b, c) {
for (var d = "" + Math.abs(a), e = a >= 0; d.length < b; )
d = "0" + d;
return (e ? c ? "+" : "" : "-") + d
}
function l(a, b, c, d) {
var e, f, g = b._milliseconds, h = b._days, i = b._months;
g && a._d.setTime(+a._d + g * c),
(h || i) && (e = a.minute(),
f = a.hour()),
h && a.date(a.date() + h * c),
i && a.month(a.month() + i * c),
g && !d && db.updateOffset(a),
(h || i) && (a.minute(e),
a.hour(f))
}
function m(a) {
return "[object Array]" === Object.prototype.toString.call(a)
}
function n(a) {
return "[object Date]" === Object.prototype.toString.call(a) || a instanceof Date
}
function o(a, b, c) {
var d, e = Math.min(a.length, b.length), f = Math.abs(a.length - b.length), g = 0;
for (d = 0; e > d; d++)
(c && a[d] !== b[d] || !c && s(a[d]) !== s(b[d])) && g++;
return g + f
}
function p(a) {
if (a) {
var b = a.toLowerCase().replace(/(.)s$/, "$1");
a = Tb[a] || Ub[b] || b
}
return a
}
function q(a) {
var b, c, d = {};
for (c in a)
a.hasOwnProperty(c) && (b = p(c),
b && (d[b] = a[c]));
return d
}
function r(b) {
var c, d;
if (0 === b.indexOf("week"))
c = 7,
d = "day";
else {
if (0 !== b.indexOf("month"))
return;
c = 12,
d = "month"
}
db[b] = function(e, f) {
var g, h, i = db.fn._lang[b], j = [];
if ("number" == typeof e && (f = e,
e = a),
h = function(a) {
var b = db().utc().set(d, a);
return i.call(db.fn._lang, b, e || "")
}
,
null != f)
return h(f);
for (g = 0; c > g; g++)
j.push(h(g));
return j
}
}
function s(a) {
var b = +a
, c = 0;
return 0 !== b && isFinite(b) && (c = b >= 0 ? Math.floor(b) : Math.ceil(b)),
c
}
function t(a, b) {
return new Date(Date.UTC(a, b + 1, 0)).getUTCDate()
}
function u(a) {
return v(a) ? 366 : 365
}
function v(a) {
return a % 4 === 0 && a % 100 !== 0 || a % 400 === 0
}
function w(a) {
var b;
a._a && -2 === a._pf.overflow && (b = a._a[jb] < 0 || a._a[jb] > 11 ? jb : a._a[kb] < 1 || a._a[kb] > t(a._a[ib], a._a[jb]) ? kb : a._a[lb] < 0 || a._a[lb] > 23 ? lb : a._a[mb] < 0 || a._a[mb] > 59 ? mb : a._a[nb] < 0 || a._a[nb] > 59 ? nb : a._a[ob] < 0 || a._a[ob] > 999 ? ob : -1,
a._pf._overflowDayOfYear && (ib > b || b > kb) && (b = kb),
a._pf.overflow = b)
}
function x(a) {
return null == a._isValid && (a._isValid = !isNaN(a._d.getTime()) && a._pf.overflow < 0 && !a._pf.empty && !a._pf.invalidMonth && !a._pf.nullInput && !a._pf.invalidFormat && !a._pf.userInvalidated,
a._strict && (a._isValid = a._isValid && 0 === a._pf.charsLeftOver && 0 === a._pf.unusedTokens.length)),
a._isValid
}
function y(a) {
return a ? a.toLowerCase().replace("_", "-") : a
}
function z(a, b) {
return b._isUTC ? db(a).zone(b._offset || 0) : db(a).local()
}
function A(a, b) {
return b.abbr = a,
pb[a] || (pb[a] = new e),
pb[a].set(b),
pb[a]
}
function B(a) {
delete pb[a]
}
function C(a) {
var b, c, d, e, f = 0, g = function(a) {
if (!pb[a] && rb)
try {
require("./lang/" + a)
} catch (b) {}
return pb[a]
};
if (!a)
return db.fn._lang;
if (!m(a)) {
if (c = g(a))
return c;
a = [a]
}
for (; f < a.length; ) {
for (e = y(a[f]).split("-"),
b = e.length,
d = y(a[f + 1]),
d = d ? d.split("-") : null; b > 0; ) {
if (c = g(e.slice(0, b).join("-")))
return c;
if (d && d.length >= b && o(e, d, !0) >= b - 1)
break;
b--
}
f++
}
return db.fn._lang
}
function D(a) {
return a.match(/\[[\s\S]/) ? a.replace(/^\[|\]$/g, "") : a.replace(/\\/g, "")
}
function E(a) {
var b, c, d = a.match(vb);
for (b = 0,
c = d.length; c > b; b++)
d[b] = Yb[d[b]] ? Yb[d[b]] : D(d[b]);
return function(e) {
var f = "";
for (b = 0; c > b; b++)
f += d[b]instanceof Function ? d[b].call(e, a) : d[b];
return f
}
}
function F(a, b) {
return a.isValid() ? (b = G(b, a.lang()),
Vb[b] || (Vb[b] = E(b)),
Vb[b](a)) : a.lang().invalidDate()
}
function G(a, b) {
function c(a) {
return b.longDateFormat(a) || a
}
var d = 5;
for (wb.lastIndex = 0; d >= 0 && wb.test(a); )
a = a.replace(wb, c),
wb.lastIndex = 0,
d -= 1;
return a
}
function H(a, b) {
var c, d = b._strict;
switch (a) {
case "DDDD":
return Ib;
case "YYYY":
case "GGGG":
case "gggg":
return d ? Jb : zb;
case "Y":
case "G":
case "g":
return Lb;
case "YYYYYY":
case "YYYYY":
case "GGGGG":
case "ggggg":
return d ? Kb : Ab;
case "S":
if (d)
return Gb;
case "SS":
if (d)
return Hb;
case "SSS":
if (d)
return Ib;
case "DDD":
return yb;
case "MMM":
case "MMMM":
case "dd":
case "ddd":
case "dddd":
return Cb;
case "a":
case "A":
return C(b._l)._meridiemParse;
case "X":
return Fb;
case "Z":
case "ZZ":
return Db;
case "T":
return Eb;
case "SSSS":
return Bb;
case "MM":
case "DD":
case "YY":
case "GG":
case "gg":
case "HH":
case "hh":
case "mm":
case "ss":
case "ww":
case "WW":
return d ? Hb : xb;
case "M":
case "D":
case "d":
case "H":
case "h":
case "m":
case "s":
case "w":
case "W":
case "e":
case "E":
return xb;
default:
return c = new RegExp(P(O(a.replace("\\", "")), "i"))
}
}
function I(a) {
a = a || "";
var b = a.match(Db) || []
, c = b[b.length - 1] || []
, d = (c + "").match(Qb) || ["-", 0, 0]
, e = +(60 * d[1]) + s(d[2]);
return "+" === d[0] ? -e : e
}
function J(a, b, c) {
var d, e = c._a;
switch (a) {
case "M":
case "MM":
null != b && (e[jb] = s(b) - 1);
break;
case "MMM":
case "MMMM":
d = C(c._l).monthsParse(b),
null != d ? e[jb] = d : c._pf.invalidMonth = b;
break;
case "D":
case "DD":
null != b && (e[kb] = s(b));
break;
case "DDD":
case "DDDD":
null != b && (c._dayOfYear = s(b));
break;
case "YY":
e[ib] = s(b) + (s(b) > 68 ? 1900 : 2e3);
break;
case "YYYY":
case "YYYYY":
case "YYYYYY":
e[ib] = s(b);
break;
case "a":
case "A":
c._isPm = C(c._l).isPM(b);
break;
case "H":
case "HH":
case "h":
case "hh":
e[lb] = s(b);
break;
case "m":
case "mm":
e[mb] = s(b);
break;
case "s":
case "ss":
e[nb] = s(b);
break;
case "S":
case "SS":
case "SSS":
case "SSSS":
e[ob] = s(1e3 * ("0." + b));
break;
case "X":
c._d = new Date(1e3 * parseFloat(b));
break;
case "Z":
case "ZZ":
c._useUTC = !0,
c._tzm = I(b);
break;
case "w":
case "ww":
case "W":
case "WW":
case "d":
case "dd":
case "ddd":
case "dddd":
case "e":
case "E":
a = a.substr(0, 1);
case "gg":
case "gggg":
case "GG":
case "GGGG":
case "GGGGG":
a = a.substr(0, 2),
b && (c._w = c._w || {},
c._w[a] = b)
}
}
function K(a) {
var b, c, d, e, f, g, h, i, j, k, l = [];
if (!a._d) {
for (d = M(a),
a._w && null == a._a[kb] && null == a._a[jb] && (f = function(b) {
var c = parseInt(b, 10);
return b ? b.length < 3 ? c > 68 ? 1900 + c : 2e3 + c : c : null == a._a[ib] ? db().weekYear() : a._a[ib]
}
,
g = a._w,
null != g.GG || null != g.W || null != g.E ? h = Z(f(g.GG), g.W || 1, g.E, 4, 1) : (i = C(a._l),
j = null != g.d ? V(g.d, i) : null != g.e ? parseInt(g.e, 10) + i._week.dow : 0,
k = parseInt(g.w, 10) || 1,
null != g.d && j < i._week.dow && k++,
h = Z(f(g.gg), k, j, i._week.doy, i._week.dow)),
a._a[ib] = h.year,
a._dayOfYear = h.dayOfYear),
a._dayOfYear && (e = null == a._a[ib] ? d[ib] : a._a[ib],
a._dayOfYear > u(e) && (a._pf._overflowDayOfYear = !0),
c = U(e, 0, a._dayOfYear),
a._a[jb] = c.getUTCMonth(),
a._a[kb] = c.getUTCDate()),
b = 0; 3 > b && null == a._a[b]; ++b)
a._a[b] = l[b] = d[b];
for (; 7 > b; b++)
a._a[b] = l[b] = null == a._a[b] ? 2 === b ? 1 : 0 : a._a[b];
l[lb] += s((a._tzm || 0) / 60),
l[mb] += s((a._tzm || 0) % 60),
a._d = (a._useUTC ? U : T).apply(null, l)
}
}
function L(a) {
var b;
a._d || (b = q(a._i),
a._a = [b.year, b.month, b.day, b.hour, b.minute, b.second, b.millisecond],
K(a))
}
function M(a) {
var b = new Date;
return a._useUTC ? [b.getUTCFullYear(), b.getUTCMonth(), b.getUTCDate()] : [b.getFullYear(), b.getMonth(), b.getDate()]
}
function N(a) {
a._a = [],
a._pf.empty = !0;
var b, c, d, e, f, g = C(a._l), h = "" + a._i, i = h.length, j = 0;
for (d = G(a._f, g).match(vb) || [],
b = 0; b < d.length; b++)
e = d[b],
c = (h.match(H(e, a)) || [])[0],
c && (f = h.substr(0, h.indexOf(c)),
f.length > 0 && a._pf.unusedInput.push(f),
h = h.slice(h.indexOf(c) + c.length),
j += c.length),
Yb[e] ? (c ? a._pf.empty = !1 : a._pf.unusedTokens.push(e),
J(e, c, a)) : a._strict && !c && a._pf.unusedTokens.push(e);
a._pf.charsLeftOver = i - j,
h.length > 0 && a._pf.unusedInput.push(h),
a._isPm && a._a[lb] < 12 && (a._a[lb] += 12),
a._isPm === !1 && 12 === a._a[lb] && (a._a[lb] = 0),
K(a),
w(a)
}
function O(a) {
return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function(a, b, c, d, e) {
return b || c || d || e
})
}
function P(a) {
return a.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&")
}
function Q(a) {
var c, d, e, f, g;
if (0 === a._f.length)
return a._pf.invalidFormat = !0,
a._d = new Date(0 / 0),
void 0;
for (f = 0; f < a._f.length; f++)
g = 0,
c = h({}, a),
c._pf = b(),
c._f = a._f[f],
N(c),
x(c) && (g += c._pf.charsLeftOver,
g += 10 * c._pf.unusedTokens.length,
c._pf.score = g,
(null == e || e > g) && (e = g,
d = c));
h(a, d || c)
}
function R(a) {
var b, c, d = a._i, e = Mb.exec(d);
if (e) {
for (a._pf.iso = !0,
b = 0,
c = Ob.length; c > b; b++)
if (Ob[b][1].exec(d)) {
a._f = Ob[b][0] + (e[6] || " ");
break
}
for (b = 0,
c = Pb.length; c > b; b++)
if (Pb[b][1].exec(d)) {
a._f += Pb[b][0];
break
}
d.match(Db) && (a._f += "Z"),
N(a)
} else
a._d = new Date(d)
}
function S(b) {
var c = b._i
, d = sb.exec(c);
c === a ? b._d = new Date : d ? b._d = new Date(+d[1]) : "string" == typeof c ? R(b) : m(c) ? (b._a = c.slice(0),
K(b)) : n(c) ? b._d = new Date(+c) : "object" == typeof c ? L(b) : b._d = new Date(c)
}
function T(a, b, c, d, e, f, g) {
var h = new Date(a,b,c,d,e,f,g);
return 1970 > a && h.setFullYear(a),
h
}
function U(a) {
var b = new Date(Date.UTC.apply(null, arguments));
return 1970 > a && b.setUTCFullYear(a),
b
}
function V(a, b) {
if ("string" == typeof a)
if (isNaN(a)) {
if (a = b.weekdaysParse(a),
"number" != typeof a)
return null
} else
a = parseInt(a, 10);
return a
}
function W(a, b, c, d, e) {
return e.relativeTime(b || 1, !!c, a, d)
}
function X(a, b, c) {
var d = hb(Math.abs(a) / 1e3)
, e = hb(d / 60)
, f = hb(e / 60)
, g = hb(f / 24)
, h = hb(g / 365)
, i = 45 > d && ["s", d] || 1 === e && ["m"] || 45 > e && ["mm", e] || 1 === f && ["h"] || 22 > f && ["hh", f] || 1 === g && ["d"] || 25 >= g && ["dd", g] || 45 >= g && ["M"] || 345 > g && ["MM", hb(g / 30)] || 1 === h && ["y"] || ["yy", h];
return i[2] = b,
i[3] = a > 0,
i[4] = c,
W.apply({}, i)
}
function Y(a, b, c) {
var d, e = c - b, f = c - a.day();
return f > e && (f -= 7),
e - 7 > f && (f += 7),
d = db(a).add("d", f),
{
week: Math.ceil(d.dayOfYear() / 7),
year: d.year()
}
}
function Z(a, b, c, d, e) {
var f, g, h = U(a, 0, 1).getUTCDay();
return c = null != c ? c : e,
f = e - h + (h > d ? 7 : 0) - (e > h ? 7 : 0),
g = 7 * (b - 1) + (c - e) + f + 1,
{
year: g > 0 ? a : a - 1,
dayOfYear: g > 0 ? g : u(a - 1) + g
}
}
function $(a) {
var b = a._i
, c = a._f;
return null === b ? db.invalid({
nullInput: !0
}) : ("string" == typeof b && (a._i = b = C().preparse(b)),
db.isMoment(b) ? (a = i(b),
a._d = new Date(+b._d)) : c ? m(c) ? Q(a) : N(a) : S(a),
new f(a))
}
function _(a, b) {
db.fn[a] = db.fn[a + "s"] = function(a) {
var c = this._isUTC ? "UTC" : "";
return null != a ? (this._d["set" + c + b](a),
db.updateOffset(this),
this) : this._d["get" + c + b]()
}
}
function ab(a) {
db.duration.fn[a] = function() {
return this._data[a]
}
}
function bb(a, b) {
db.duration.fn["as" + a] = function() {
return +this / b
}
}
function cb(a) {
var b = !1
, c = db;
"undefined" == typeof ender && (a ? (gb.moment = function() {
return !b && console && console.warn && (b = !0,
console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),
c.apply(null, arguments)
}
,
h(gb.moment, c)) : gb.moment = db)
}
for (var db, eb, fb = "2.5.1", gb = this, hb = Math.round, ib = 0, jb = 1, kb = 2, lb = 3, mb = 4, nb = 5, ob = 6, pb = {}, qb = {
_isAMomentObject: null,
_i: null,
_f: null,
_l: null,
_strict: null,
_isUTC: null,
_offset: null,
_pf: null,
_lang: null
}, rb = "undefined" != typeof module && module.exports && "undefined" != typeof require, sb = /^\/?Date\((\-?\d+)/i, tb = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, ub = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, vb = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, wb = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, xb = /\d\d?/, yb = /\d{1,3}/, zb = /\d{1,4}/, Ab = /[+\-]?\d{1,6}/, Bb = /\d+/, Cb = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, Db = /Z|[\+\-]\d\d:?\d\d/gi, Eb = /T/i, Fb = /[\+\-]?\d+(\.\d{1,3})?/, Gb = /\d/, Hb = /\d\d/, Ib = /\d{3}/, Jb = /\d{4}/, Kb = /[+-]?\d{6}/, Lb = /[+-]?\d+/, Mb = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, Nb = "YYYY-MM-DDTHH:mm:ssZ", Ob = [["YYYYYY-MM-DD", /[+-]\d{6}-\d{2}-\d{2}/], ["YYYY-MM-DD", /\d{4}-\d{2}-\d{2}/], ["GGGG-[W]WW-E", /\d{4}-W\d{2}-\d/], ["GGGG-[W]WW", /\d{4}-W\d{2}/], ["YYYY-DDD", /\d{4}-\d{3}/]], Pb = [["HH:mm:ss.SSSS", /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], ["HH:mm:ss", /(T| )\d\d:\d\d:\d\d/], ["HH:mm", /(T| )\d\d:\d\d/], ["HH", /(T| )\d\d/]], Qb = /([\+\-]|\d\d)/gi, Rb = "Date|Hours|Minutes|Seconds|Milliseconds".split("|"), Sb = {
Milliseconds: 1,
Seconds: 1e3,
Minutes: 6e4,
Hours: 36e5,
Days: 864e5,
Months: 2592e6,
Years: 31536e6
}, Tb = {
ms: "millisecond",
s: "second",
m: "minute",
h: "hour",
d: "day",
D: "date",
w: "week",
W: "isoWeek",
M: "month",
y: "year",
DDD: "dayOfYear",
e: "weekday",
E: "isoWeekday",
gg: "weekYear",
GG: "isoWeekYear"
}, Ub = {
dayofyear: "dayOfYear",
isoweekday: "isoWeekday",
isoweek: "isoWeek",
weekyear: "weekYear",
isoweekyear: "isoWeekYear"
}, Vb = {}, Wb = "DDD w W M D d".split(" "), Xb = "M D H h m s w W".split(" "), Yb = {
M: function() {
return this.month() + 1
},
MMM: function(a) {
return this.lang().monthsShort(this, a)
},
MMMM: function(a) {
return this.lang().months(this, a)
},
D: function() {
return this.date()
},
DDD: function() {
return this.dayOfYear()
},
d: function() {
return this.day()
},
dd: function(a) {
return this.lang().weekdaysMin(this, a)
},
ddd: function(a) {
return this.lang().weekdaysShort(this, a)
},
dddd: function(a) {
return this.lang().weekdays(this, a)
},
w: function() {
return this.week()
},
W: function() {
return this.isoWeek()
},
YY: function() {
return k(this.year() % 100, 2)
},
YYYY: function() {
return k(this.year(), 4)
},
YYYYY: function() {
return k(this.year(), 5)
},
YYYYYY: function() {
var a = this.year()
, b = a >= 0 ? "+" : "-";
return b + k(Math.abs(a), 6)
},
gg: function() {
return k(this.weekYear() % 100, 2)
},
gggg: function() {
return k(this.weekYear(), 4)
},
ggggg: function() {
return k(this.weekYear(), 5)
},
GG: function() {
return k(this.isoWeekYear() % 100, 2)
},
GGGG: function() {
return k(this.isoWeekYear(), 4)
},
GGGGG: function() {
return k(this.isoWeekYear(), 5)
},
e: function() {
return this.weekday()
},
E: function() {
return this.isoWeekday()
},
a: function() {
return this.lang().meridiem(this.hours(), this.minutes(), !0)
},
A: function() {
return this.lang().meridiem(this.hours(), this.minutes(), !1)
},
H: function() {
return this.hours()
},
h: function() {
return this.hours() % 12 || 12
},
m: function() {
return this.minutes()
},
s: function() {
return this.seconds()
},
S: function() {
return s(this.milliseconds() / 100)
},
SS: function() {
return k(s(this.milliseconds() / 10), 2)
},
SSS: function() {
return k(this.milliseconds(), 3)
},
SSSS: function() {
return k(this.milliseconds(), 3)
},
Z: function() {
var a = -this.zone()
, b = "+";
return 0 > a && (a = -a,
b = "-"),
b + k(s(a / 60), 2) + ":" + k(s(a) % 60, 2)
},
ZZ: function() {
var a = -this.zone()
, b = "+";
return 0 > a && (a = -a,
b = "-"),
b + k(s(a / 60), 2) + k(s(a) % 60, 2)
},
z: function() {
return this.zoneAbbr()
},
zz: function() {
return this.zoneName()
},
X: function() {
return this.unix()
},
Q: function() {
return this.quarter()
}
}, Zb = ["months", "monthsShort", "weekdays", "weekdaysShort", "weekdaysMin"]; Wb.length; )
eb = Wb.pop(),
Yb[eb + "o"] = d(Yb[eb], eb);
for (; Xb.length; )
eb = Xb.pop(),
Yb[eb + eb] = c(Yb[eb], 2);
for (Yb.DDDD = c(Yb.DDD, 3),
h(e.prototype, {
set: function(a) {
var b, c;
for (c in a)
b = a[c],
"function" == typeof b ? this[c] = b : this["_" + c] = b
},
_months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
months: function(a) {
return this._months[a.month()]
},
_monthsShort: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
monthsShort: function(a) {
return this._monthsShort[a.month()]
},
monthsParse: function(a) {
var b, c, d;
for (this._monthsParse || (this._monthsParse = []),
b = 0; 12 > b; b++)
if (this._monthsParse[b] || (c = db.utc([2e3, b]),
d = "^" + this.months(c, "") + "|^" + this.monthsShort(c, ""),
this._monthsParse[b] = new RegExp(d.replace(".", ""),"i")),
this._monthsParse[b].test(a))
return b
},
_weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
weekdays: function(a) {
return this._weekdays[a.day()]
},
_weekdaysShort: "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
weekdaysShort: function(a) {
return this._weekdaysShort[a.day()]
},
_weekdaysMin: "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
weekdaysMin: function(a) {
return this._weekdaysMin[a.day()]
},
weekdaysParse: function(a) {
var b, c, d;
for (this._weekdaysParse || (this._weekdaysParse = []),
b = 0; 7 > b; b++)
if (this._weekdaysParse[b] || (c = db([2e3, 1]).day(b),
d = "^" + this.weekdays(c, "") + "|^" + this.weekdaysShort(c, "") + "|^" + this.weekdaysMin(c, ""),
this._weekdaysParse[b] = new RegExp(d.replace(".", ""),"i")),
this._weekdaysParse[b].test(a))
return b
},
_longDateFormat: {
LT: "h:mm A",
L: "MM/DD/YYYY",
LL: "MMMM D YYYY",
LLL: "MMMM D YYYY LT",
LLLL: "dddd, MMMM D YYYY LT"
},
longDateFormat: function(a) {
var b = this._longDateFormat[a];
return !b && this._longDateFormat[a.toUpperCase()] && (b = this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function(a) {
return a.slice(1)
}),
this._longDateFormat[a] = b),
b
},
isPM: function(a) {
return "p" === (a + "").toLowerCase().charAt(0)
},
_meridiemParse: /[ap]\.?m?\.?/i,
meridiem: function(a, b, c) {
return a > 11 ? c ? "pm" : "PM" : c ? "am" : "AM"
},
_calendar: {
sameDay: "[Today at] LT",
nextDay: "[Tomorrow at] LT",
nextWeek: "dddd [at] LT",
lastDay: "[Yesterday at] LT",
lastWeek: "[Last] dddd [at] LT",
sameElse: "L"
},
calendar: function(a, b) {
var c = this._calendar[a];
return "function" == typeof c ? c.apply(b) : c
},
_relativeTime: {
future: "in %s",
past: "%s ago",
s: "a few seconds",
m: "a minute",
mm: "%d minutes",
h: "an hour",
hh: "%d hours",
d: "a day",
dd: "%d days",
M: "a month",
MM: "%d months",
y: "a year",
yy: "%d years"
},
relativeTime: function(a, b, c, d) {
var e = this._relativeTime[c];
return "function" == typeof e ? e(a, b, c, d) : e.replace(/%d/i, a)
},
pastFuture: function(a, b) {
var c = this._relativeTime[a > 0 ? "future" : "past"];
return "function" == typeof c ? c(b) : c.replace(/%s/i, b)
},
ordinal: function(a) {
return this._ordinal.replace("%d", a)
},
_ordinal: "%d",
preparse: function(a) {
return a
},
postformat: function(a) {
return a
},
week: function(a) {
return Y(a, this._week.dow, this._week.doy).week
},
_week: {
dow: 0,
doy: 6
},
_invalidDate: "Invalid date",
invalidDate: function() {
return this._invalidDate
}
}),
db = function(c, d, e, f) {
var g;
return "boolean" == typeof e && (f = e,
e = a),
g = {},
g._isAMomentObject = !0,
g._i = c,
g._f = d,
g._l = e,
g._strict = f,
g._isUTC = !1,
g._pf = b(),
$(g)
}
,
db.utc = function(c, d, e, f) {
var g;
return "boolean" == typeof e && (f = e,
e = a),
g = {},
g._isAMomentObject = !0,
g._useUTC = !0,
g._isUTC = !0,
g._l = e,
g._i = c,
g._f = d,
g._strict = f,
g._pf = b(),
$(g).utc()
}
,
db.unix = function(a) {
return db(1e3 * a)
}
,
db.duration = function(a, b) {
var c, d, e, f = a, h = null;
return db.isDuration(a) ? f = {
ms: a._milliseconds,
d: a._days,
M: a._months
} : "number" == typeof a ? (f = {},
b ? f[b] = a : f.milliseconds = a) : (h = tb.exec(a)) ? (c = "-" === h[1] ? -1 : 1,
f = {
y: 0,
d: s(h[kb]) * c,
h: s(h[lb]) * c,
m: s(h[mb]) * c,
s: s(h[nb]) * c,
ms: s(h[ob]) * c
}) : (h = ub.exec(a)) && (c = "-" === h[1] ? -1 : 1,
e = function(a) {
var b = a && parseFloat(a.replace(",", "."));
return (isNaN(b) ? 0 : b) * c
}
,
f = {
y: e(h[2]),
M: e(h[3]),
d: e(h[4]),
h: e(h[5]),
m: e(h[6]),
s: e(h[7]),
w: e(h[8])
}),
d = new g(f),
db.isDuration(a) && a.hasOwnProperty("_lang") && (d._lang = a._lang),
d
}
,
db.version = fb,
db.defaultFormat = Nb,
db.updateOffset = function() {}
,
db.lang = function(a, b) {
var c;
return a ? (b ? A(y(a), b) : null === b ? (B(a),
a = "en") : pb[a] || C(a),
c = db.duration.fn._lang = db.fn._lang = C(a),
c._abbr) : db.fn._lang._abbr
}
,
db.langData = function(a) {
return a && a._lang && a._lang._abbr && (a = a._lang._abbr),
C(a)
}
,
db.isMoment = function(a) {
return a instanceof f || null != a && a.hasOwnProperty("_isAMomentObject")
}
,
db.isDuration = function(a) {
return a instanceof g
}
,
eb = Zb.length - 1; eb >= 0; --eb)
r(Zb[eb]);
for (db.normalizeUnits = function(a) {
return p(a)
}
,
db.invalid = function(a) {
var b = db.utc(0 / 0);
return null != a ? h(b._pf, a) : b._pf.userInvalidated = !0,
b
}
,
db.parseZone = function(a) {
return db(a).parseZone()
}
,
h(db.fn = f.prototype, {
clone: function() {
return db(this)
},
valueOf: function() {
return +this._d + 6e4 * (this._offset || 0)
},
unix: function() {
return Math.floor(+this / 1e3)
},
toString: function() {
return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")
},
toDate: function() {
return this._offset ? new Date(+this) : this._d
},
toISOString: function() {
var a = db(this).utc();
return 0 < a.year() && a.year() <= 9999 ? F(a, "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]") : F(a, "YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")
},
toArray: function() {
var a = this;
return [a.year(), a.month(), a.date(), a.hours(), a.minutes(), a.seconds(), a.milliseconds()]
},
isValid: function() {
return x(this)
},
isDSTShifted: function() {
return this._a ? this.isValid() && o(this._a, (this._isUTC ? db.utc(this._a) : db(this._a)).toArray()) > 0 : !1
},
parsingFlags: function() {
return h({}, this._pf)
},
invalidAt: function() {
return this._pf.overflow
},
utc: function() {
return this.zone(0)
},
local: function() {
return this.zone(0),
this._isUTC = !1,
this
},
format: function(a) {
var b = F(this, a || db.defaultFormat);
return this.lang().postformat(b)
},
add: function(a, b) {
var c;
return c = "string" == typeof a ? db.duration(+b, a) : db.duration(a, b),
l(this, c, 1),
this
},
subtract: function(a, b) {
var c;
return c = "string" == typeof a ? db.duration(+b, a) : db.duration(a, b),
l(this, c, -1),
this
},
diff: function(a, b, c) {
var d, e, f = z(a, this), g = 6e4 * (this.zone() - f.zone());
return b = p(b),
"year" === b || "month" === b ? (d = 432e5 * (this.daysInMonth() + f.daysInMonth()),
e = 12 * (this.year() - f.year()) + (this.month() - f.month()),
e += (this - db(this).startOf("month") - (f - db(f).startOf("month"))) / d,
e -= 6e4 * (this.zone() - db(this).startOf("month").zone() - (f.zone() - db(f).startOf("month").zone())) / d,
"year" === b && (e /= 12)) : (d = this - f,
e = "second" === b ? d / 1e3 : "minute" === b ? d / 6e4 : "hour" === b ? d / 36e5 : "day" === b ? (d - g) / 864e5 : "week" === b ? (d - g) / 6048e5 : d),
c ? e : j(e)
},
from: function(a, b) {
return db.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)
},
fromNow: function(a) {
return this.from(db(), a)
},
calendar: function() {
var a = z(db(), this).startOf("day")
, b = this.diff(a, "days", !0)
, c = -6 > b ? "sameElse" : -1 > b ? "lastWeek" : 0 > b ? "lastDay" : 1 > b ? "sameDay" : 2 > b ? "nextDay" : 7 > b ? "nextWeek" : "sameElse";
return this.format(this.lang().calendar(c, this))
},
isLeapYear: function() {
return v(this.year())
},
isDST: function() {
return this.zone() < this.clone().month(0).zone() || this.zone() < this.clone().month(5).zone()
},
day: function(a) {
var b = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
return null != a ? (a = V(a, this.lang()),
this.add({
d: a - b
})) : b
},
month: function(a) {
var b, c = this._isUTC ? "UTC" : "";
return null != a ? "string" == typeof a && (a = this.lang().monthsParse(a),
"number" != typeof a) ? this : (b = this.date(),
this.date(1),
this._d["set" + c + "Month"](a),
this.date(Math.min(b, this.daysInMonth())),
db.updateOffset(this),
this) : this._d["get" + c + "Month"]()
},
startOf: function(a) {
switch (a = p(a)) {
case "year":
this.month(0);
case "month":
this.date(1);
case "week":
case "isoWeek":
case "day":
this.hours(0);
case "hour":
this.minutes(0);
case "minute":
this.seconds(0);
case "second":
this.milliseconds(0)
}
return "week" === a ? this.weekday(0) : "isoWeek" === a && this.isoWeekday(1),
this
},
endOf: function(a) {
return a = p(a),
this.startOf(a).add("isoWeek" === a ? "week" : a, 1).subtract("ms", 1)
},
isAfter: function(a, b) {
return b = "undefined" != typeof b ? b : "millisecond",
+this.clone().startOf(b) > +db(a).startOf(b)
},
isBefore: function(a, b) {
return b = "undefined" != typeof b ? b : "millisecond",
+this.clone().startOf(b) < +db(a).startOf(b)
},
isSame: function(a, b) {
return b = b || "ms",
+this.clone().startOf(b) === +z(a, this).startOf(b)
},
min: function(a) {
return a = db.apply(null, arguments),
this > a ? this : a
},
max: function(a) {
return a = db.apply(null, arguments),
a > this ? this : a
},
zone: function(a) {
var b = this._offset || 0;
return null == a ? this._isUTC ? b : this._d.getTimezoneOffset() : ("string" == typeof a && (a = I(a)),
Math.abs(a) < 16 && (a = 60 * a),
this._offset = a,
this._isUTC = !0,
b !== a && l(this, db.duration(b - a, "m"), 1, !0),
this)
},
zoneAbbr: function() {
return this._isUTC ? "UTC" : ""
},
zoneName: function() {
return this._isUTC ? "Coordinated Universal Time" : ""
},
parseZone: function() {
return this._tzm ? this.zone(this._tzm) : "string" == typeof this._i && this.zone(this._i),
this
},
hasAlignedHourOffset: function(a) {
return a = a ? db(a).zone() : 0,
(this.zone() - a) % 60 === 0
},
daysInMonth: function() {
return t(this.year(), this.month())
},
dayOfYear: function(a) {
var b = hb((db(this).startOf("day") - db(this).startOf("year")) / 864e5) + 1;
return null == a ? b : this.add("d", a - b)
},
quarter: function() {
return Math.ceil((this.month() + 1) / 3)
},
weekYear: function(a) {
var b = Y(this, this.lang()._week.dow, this.lang()._week.doy).year;
return null == a ? b : this.add("y", a - b)
},
isoWeekYear: function(a) {
var b = Y(this, 1, 4).year;
return null == a ? b : this.add("y", a - b)
},
week: function(a) {
var b = this.lang().week(this);
return null == a ? b : this.add("d", 7 * (a - b))
},
isoWeek: function(a) {
var b = Y(this, 1, 4).week;
return null == a ? b : this.add("d", 7 * (a - b))
},
weekday: function(a) {
var b = (this.day() + 7 - this.lang()._week.dow) % 7;
return null == a ? b : this.add("d", a - b)
},
isoWeekday: function(a) {
return null == a ? this.day() || 7 : this.day(this.day() % 7 ? a : a - 7)
},
get: function(a) {
return a = p(a),
this[a]()
},
set: function(a, b) {
return a = p(a),
"function" == typeof this[a] && this[a](b),
this
},
lang: function(b) {
return b === a ? this._lang : (this._lang = C(b),
this)
}
}),
eb = 0; eb < Rb.length; eb++)
_(Rb[eb].toLowerCase().replace(/s$/, ""), Rb[eb]);
_("year", "FullYear"),
db.fn.days = db.fn.day,
db.fn.months = db.fn.month,
db.fn.weeks = db.fn.week,
db.fn.isoWeeks = db.fn.isoWeek,
db.fn.toJSON = db.fn.toISOString,
h(db.duration.fn = g.prototype, {
_bubble: function() {
var a, b, c, d, e = this._milliseconds, f = this._days, g = this._months, h = this._data;
h.milliseconds = e % 1e3,
a = j(e / 1e3),
h.seconds = a % 60,
b = j(a / 60),
h.minutes = b % 60,
c = j(b / 60),
h.hours = c % 24,
f += j(c / 24),
h.days = f % 30,
g += j(f / 30),
h.months = g % 12,
d = j(g / 12),
h.years = d
},
weeks: function() {
return j(this.days() / 7)
},
valueOf: function() {
return this._milliseconds + 864e5 * this._days + this._months % 12 * 2592e6 + 31536e6 * s(this._months / 12)
},
humanize: function(a) {
var b = +this
, c = X(b, !a, this.lang());
return a && (c = this.lang().pastFuture(b, c)),
this.lang().postformat(c)
},
add: function(a, b) {
var c = db.duration(a, b);
return this._milliseconds += c._milliseconds,
this._days += c._days,
this._months += c._months,
this._bubble(),
this
},
subtract: function(a, b) {
var c = db.duration(a, b);
return this._milliseconds -= c._milliseconds,
this._days -= c._days,
this._months -= c._months,
this._bubble(),
this
},
get: function(a) {
return a = p(a),
this[a.toLowerCase() + "s"]()
},
as: function(a) {
return a = p(a),
this["as" + a.charAt(0).toUpperCase() + a.slice(1) + "s"]()
},
lang: db.fn.lang,
toIsoString: function() {
var a = Math.abs(this.years())
, b = Math.abs(this.months())
, c = Math.abs(this.days())
, d = Math.abs(this.hours())
, e = Math.abs(this.minutes())
, f = Math.abs(this.seconds() + this.milliseconds() / 1e3);
return this.asSeconds() ? (this.asSeconds() < 0 ? "-" : "") + "P" + (a ? a + "Y" : "") + (b ? b + "M" : "") + (c ? c + "D" : "") + (d || e || f ? "T" : "") + (d ? d + "H" : "") + (e ? e + "M" : "") + (f ? f + "S" : "") : "P0D"
}
});
for (eb in Sb)
Sb.hasOwnProperty(eb) && (bb(eb, Sb[eb]),
ab(eb.toLowerCase()));
bb("Weeks", 6048e5),
db.duration.fn.asMonths = function() {
return (+this - 31536e6 * this.years()) / 2592e6 + 12 * this.years()
}
,
db.lang("en", {
ordinal: function(a) {
var b = a % 10
, c = 1 === s(a % 100 / 10) ? "th" : 1 === b ? "st" : 2 === b ? "nd" : 3 === b ? "rd" : "th";
return a + c
}
}),
rb ? (module.exports = db,
cb(!0)) : "function" == typeof define && define.amd ? define("moment", function(b, c, d) {
return d.config && d.config() && d.config().noGlobal !== !0 && cb(d.config().noGlobal === a),
db
}) : cb()
}
).call(this);
</script>
</head>
<body>
<div class="content">
<h1>Download time calculator</h1>
<h3>How long will take to download this?</h3>
<form onsubmit="return false">
<div id="speed">
<h3>How fast is your connection speed?</h3>
<p>
<label for="internetSpeed">Download Speed</label>
<input id="internetSpeed" type="number" min="0" step="0.01" value="10" placeholder="Download speed" autofocus="">
<input id="internetSpeed_p" type="button" value="+" onclick="internetSpeed.value = (parseInt(internetSpeed.value)+1).toFixed(2)">
<input id="internetSpeed_p" type="button" value="-" onclick="internetSpeed.value = (parseInt(internetSpeed.value)-1).toFixed(2)">
<select id="internetSpeedBase">
<option value="10^3">Kbps</option>
<option value="10^6" selected="">Mbps</option>
</select>
</p>
<p class="idkSpeed"><a id="speedtestLink" href="http://speedtest.net" target="new">I don't know my internet speed</a></p>
<div>
<label class="collapse" for="_1">▼</label>
<input id="_1" type="checkbox">
<div>
<p class="overhead-p"><label for="internetOverhead">Overhead</label>
<select id="internetOverhead">
<option value="1" selected="">None</option>
<option value="0.99">1%</option>
<option value="0.95">5%</option>
<option value="0.9">10% (Tipical TCP overhead)</option>
<option value="0.85">15%</option>
<option value="0.8">20%</option>
<option value="0.75">25%</option>
<option value="0.7">30%</option>
<option value="0.6">40%</option>
<option value="0.5">50%</option>
<option value="0.4">60%</option>
<option value="0.3">70%</option>
<option value="0.2">80%</option>
<option value="0.1">90%</option>
<option value="0.05">95%</option>
<option value="0.01">99%</option>
</select>
<a href="#" onclick="alert('If you just measured your internet speed, you don\'t need to change this.\n\nBut if enter your contracted speed e.g. 10Mbps, keep in mind this value is a teorical maximum, there will always be overhead.\nFor a conservative value use 10% (tipical TCP overhead) or for more realistic results use 20%.')">Help</a>
</p>
</div>
</div>
</div>
<div id="file">
<h3>What is the size of what you want to download?</h3>
<p>
<label for="fileSize">Size</label>
<input type="number" id="fileSize" value="1" step="0.01" min="0">
<input id="internetSpeed_p" type="button" value="+" onclick="fileSize.value = (parseInt(fileSize.value)+1).toFixed(2)">
<input id="internetSpeed_p" type="button" value="-" onclick="fileSize.value = (parseInt(fileSize.value)-1).toFixed(2)">
<select id="fileSizeBase">
<option value="2^10">KB (KiloBytes)</option>
<option value="2^20" selected="">MB (MegaBytes)</option>
<option value="2^30">GB (GigaBytes)</option>
<option value="2^40">TB (TeraBytes)</option>
</select>
</p>
<p class="examples-p" style="display:none">
<label for="fileSizeEx">Examples</label>
<select id="fileSizeEx">
<option></option>
<optgroup label="iTunes Store">
<option value="4">4-minute song</option>
<option value="30">5-minute video</option>
<option value="110">9-hour audiobook</option>
<option value="200">45-minute TV show</option>
<option value="600">45-minute HDTV show</option>
<option value="1.5">2-hour SD movie</option>
<option value="4">2-hour HD movie</option>
<option value="40">iPod Game</option>
</optgroup>
<optgroup label="Playstation Network">
<option value="9">PS3 Game</option>
<option value="24">PS4 Game</option>
</optgroup>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</p>
<p>
<button id="calculateButton">Calculate</button>
</p>
</div>
</form>
<div id="results" style="visibility: visible;">
<div id="results_inner">
<p class="time"></p>
<p class=""> <span class="size"></span> </p>
<p class=""> <span class="speed"></span></p>
</div>
<hr>
<div id="downloadSimulatorWindow" style="visibility: visible;">
<div class="filename">Simulation</div>
<div class="icon"></div>
<div class="percent"></div>
<div class="progresrbar"><progress max="100" value="0"></progress></div>
<div class="details">
<span class="downloaded"></span> of <span class="size"></span> (<span class="speed"></span>/sec) <span> - </span> <span class="remaining"></span> remaining
</div>
<div class="ps">* this is not an actual transfer, this is just a simulation of how much time it would take</div>
</div>
</div>
<div class="footer">
<a href="#">Download-Calculator</a>
</div>
</div>
<script>
var downloadSimulator = null;
window.onload=function(){
calculateButton.onclick = calc;
var hasFlash = function() {
if(typeof navigator.plugins == "undefined" || navigator.plugins.length == 0){
try{
return !!(new ActiveXObject("ShockwaveFlash.ShockwaveFlash"));
}catch(e){
return undefined;
}
}else{
return navigator.plugins["Shockwave Flash"];
}
};
if(!hasFlash()){
speedtest.style.display = 'none';
speedtestLink.innerHTML = "Test my internet speed";
document.querySelector('.idkSpeed').classList.add("mobile");
}
downloadSimulator = new Downloader(document.getElementById('downloadSimulatorWindow'));
if(window.location.hash){
var uri = window.location.hash;
internetSpeed.value = uri.match(/speed=([\d.]+)x(\d+\^\d+)/)[1];
internetSpeedBase.value = uri.match(/speed=([\d.]+)x(\d+\^\d+)/)[2];
internetOverhead.value = uri.match(/overhead=([\d.]+)/)[1];
fileSize.value = uri.match(/file=([\d.]+)x(\d+\^\d+)/)[1];
fileSizeBase.value = uri.match(/file=([\d.]+)x(\d+\^\d+)/)[2];
calc();
}else if(window.localStorage){
if(window.localStorage.getItem('downloadtime.speed')){
internetSpeed.value = window.localStorage.getItem('downloadtime.speed');
internetSpeedBase.value = window.localStorage.getItem('downloadtime.speedBase');
internetOverhead.value = window.localStorage.getItem('downloadtime.overhead');
fileSize.value = window.localStorage.getItem('downloadtime.file');
fileSizeBase.value = window.localStorage.getItem('downloadtime.fileBase');
}else defaults();
}else defaults();
document.getElementsByTagName("form")[0].onsubmit = function(e){
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
if (e.preventDefault) e.preventDefault();
else e.returnValue = false;
this.returnValue = false;
calc();
return false;
}
};
function defaults(){
internetSpeed.value = "10";
internetSpeedBase.value = "10^6";
internetOverhead.value = "0.9";
fileSize.value = "1";
fileSizeBase.value = "2^30";
}
function calc(){
var internet = {
speed: internetSpeed.value,
factor: internetSpeedBase.value,
overhead: internetOverhead.value,
}
internet.speed = parseFloat(internet.speed);
internet.overhead = parseFloat(internet.overhead);
internet.factor = {
base: internet.factor.match(/(\d+)\^(\d+)/)[1],
power: internet.factor.match(/(\d+)\^(\d+)/)[2]
}
internet.bitsPerSec = internet.speed * Math.pow(internet.factor.base, internet.factor.power);
internet.bytesPerSec = internet.bitsPerSec/8;
var file = {
size: fileSize.value,
factor: fileSizeBase.value,
}
file.size = parseFloat(file.size);
file.factor = {
base: file.factor.match(/(\d+)\^(\d+)/)[1],
power: file.factor.match(/(\d+)\^(\d+)/)[2]
}
file.bytes = file.size * Math.pow(file.factor.base, file.factor.power);
internet.effectiveBytesPerSec = internet.bytesPerSec * internet.overhead;
var transferTime_ms = (file.bytes/internet.effectiveBytesPerSec)*1000;
document.querySelector("#results .time").innerHTML = moment.preciseDiff(0, transferTime_ms);
document.querySelector("#results .size").innerHTML = prefixByteLong(file.bytes);
document.querySelector("#results .speed").innerHTML = prefixByte(internet.effectiveBytesPerSec);
document.getElementById("results").style.visibility = "visible";
document.getElementById("downloadSimulatorWindow").style.visibility = "visible";
downloadSimulator.start(file.bytes, internet.effectiveBytesPerSec, "Simulation");
if(window.location){
var uri=[];
uri.push("file="+fileSize.value+"x"+fileSizeBase.value);
uri.push("speed="+internetSpeed.value+"x"+internetSpeedBase.value);
uri.push("overhead="+internetOverhead.value);
window.location.hash = uri.join("&");
}
if(window.localStorage){
window.localStorage.setItem('downloadtime.speed', internetSpeed.value);
window.localStorage.setItem('downloadtime.speedBase', internetSpeedBase.value);
window.localStorage.setItem('downloadtime.overhead', internetOverhead.value);
window.localStorage.setItem('downloadtime.file', fileSize.value);
window.localStorage.setItem('downloadtime.fileBase', fileSizeBase.value);
}
var t = msToTime(transferTime);
console.log(t);
str = [];
if(t.years >= 1) str.push( t.years + " year" + (t.years>=2?"s":"") );
if(t.months >= 1) str.push( t.months + " month" + (t.months>=2?"s":"") );
if(t.weeks >= 1) str.push( t.weeks + " week" + (t.weeks>=2?"s":"") );
if(t.days >= 1) str.push( t.days + " day" + (t.days>=2?"s":"") );
if(t.hours >= 1) str.push( t.hours + " hour" + (t.hours>=2?"s":"") );
if(t.minutes >= 1) str.push( t.minutes + " minute" + (t.minutes>=2?"s":"") );
if(t.seconds >= 1) str.push( t.seconds + " second" + (t.seconds>=2?"s":"") );
if(t.ms >= 1) str.push( t.ms + " ms" );
time.innerHTML = str.join(", ")+".";
time.innerHTML = moment.duration(transferTime).humanize();
}
function msToTime(ms) {
debugger;;
var t={};
t.ms = ms % 1000;
ms = (ms - t.ms) / 1000;
t.seconds = ms % 60;
ms = (ms - t.seconds) / 60;
t.minutes = ms % 60;
ms = (ms - t.minutes) / 60;
t.hours = ms % 60;
ms = (ms - t.hours) / 60;
t.days = ms % 24;
ms = (ms - t.days) / 24;
t.weeks = ms % 7;
ms = (ms - t.weeks) / 7;
t.months = ms % ((365/12)/7);
ms = (ms - t.months) / ((365/12)/7);
t.years = ms % (365/12);
ms = (ms - t.years) / (365/12);
console.log(JSON.stringify(t));
return t;
}
(function(moment) {
var STRINGS = {
nodiff: '',
year: 'year',
years: 'years',
month: 'month',
months: 'months',
day: 'day',
days: 'days',
hour: 'hour',
hours: 'hours',
minute: 'minute',
minutes: 'minutes',
second: 'second',
seconds: 'seconds',
delimiter: ' '
};
moment.fn.preciseDiff = function(d2) {
return moment.preciseDiff(this, d2);
};
moment.preciseDiff = function(d1, d2) {
var m1 = moment(d1), m2 = moment(d2);
if (m1.isSame(m2)) {
return STRINGS.nodiff;
}
if (m1.isAfter(m2)) {
var tmp = m1;
m1 = m2;
m2 = tmp;
}
var yDiff = m2.year() - m1.year();
var mDiff = m2.month() - m1.month();
var dDiff = m2.date() - m1.date();
var hourDiff = m2.hour() - m1.hour();
var minDiff = m2.minute() - m1.minute();
var secDiff = m2.second() - m1.second();
if (secDiff < 0) {
secDiff = 60 + secDiff;
minDiff--;
}
if (minDiff < 0) {
minDiff = 60 + minDiff;
hourDiff--;
}
if (hourDiff < 0) {
hourDiff = 24 + hourDiff;
dDiff--;
}
if (dDiff < 0) {
var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1), "YYYY-MM").subtract('months', 1).daysInMonth();
if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
dDiff = daysInLastFullMonth + dDiff + (m1.date() - daysInLastFullMonth);
} else {
dDiff = daysInLastFullMonth + dDiff;
}
mDiff--;
}
if (mDiff < 0) {
mDiff = 12 + mDiff;
yDiff--;
}
function pluralize(num, word) {
return num + ' ' + STRINGS[word + (num === 1 ? '' : 's')];
}
var result = [];
if (yDiff) {
result.push(pluralize(yDiff, 'year'));
}
if (mDiff) {
result.push(pluralize(mDiff, 'month'));
}
if (dDiff) {
result.push(pluralize(dDiff, 'day'));
}
if (hourDiff) {
result.push(pluralize(hourDiff, 'hour'));
}
if (minDiff) {
result.push(pluralize(minDiff, 'minute'));
}
if (secDiff) {
result.push(pluralize(secDiff, 'second'));
}
return result.join(STRINGS.delimiter);
};
}(moment));
function Downloader(elm){
var self = this;
this.fileSize;
this.speed;
this.DOM = {
progress: elm.querySelector('progress'),
percent: elm.querySelector('.percent'),
downloaded: elm.querySelector('.downloaded'),
details: elm.querySelector('.details'),
size: elm.querySelector('.size'),
speed: elm.querySelector('.speed'),
remaining: elm.querySelector('.remaining'),
filename: elm.querySelector('.filename')
}
var _transferTime;
var _startTime;
var _elapsedTime;
var _remainingTime;
var _downloaded;
var _percent;
var _timer;
this.start = function(fileSize, speed, filename){
this.DOM.filename.innerHTML = filename;
clearInterval(_timer);
_startTime = Date.now();
_downloaded = 0;
_percent = 0;
self.fileSize = fileSize;
self.speed = speed;
_transferTime = (fileSize / speed)*1000;
this.DOM.details.style.display = "";
self.update();
_timer = setInterval(function(){self.update()},500);
}
this.update = function(){
var now = Date.now();
_elapsedTime = now - _startTime;
_remainingTime = _transferTime - _elapsedTime;
_percent = (_elapsedTime / _transferTime) * 100;
_downloaded = this.fileSize * (_elapsedTime / _transferTime);
this.DOM.progress.value = _percent;
this.DOM.percent.innerHTML = (_percent<<0) + "%";
this.DOM.downloaded.innerHTML = prefixByte(_downloaded);
this.DOM.size.innerHTML = prefixByte(this.fileSize);
this.DOM.speed.innerHTML = prefixByte(this.speed);
this.DOM.remaining.innerHTML = moment.duration(_remainingTime).humanize();
if(_elapsedTime>=_transferTime){
this.stop();
}
}
this.stop = function(){
clearInterval(_timer);
_elapsedTime = -1;
_remainingTime = 0;
_percent = 100;
_downloaded = this.fileSize;
this.DOM.progress.value = 100;
this.DOM.percent.innerHTML = "100%";
this.DOM.downloaded.innerHTML = prefixByte(this.fileSize);
this.DOM.size.innerHTML = prefixByte(this.fileSize);
this.DOM.speed.innerHTML = prefixByte(this.speed);
this.DOM.remaining.innerHTML = "0";
this.DOM.details.style.display = "none";
}
}
function Prefixer(unit, prefix, format){
for(var i=0; i<prefix.length; i++){
prefix[i][4] = Math.pow(prefix[i][0], prefix[i][1]);
}
return function(x){
x=parseFloat(x);
var r, n=x<0?-1:1;
x = x*n;
for(var i=0; i<prefix.length; i++){
if(x>=prefix[i][4]-1){
r = prefix[i];
}
else break;
}
x = x*n;
x = (x/r[4]);
var obj = {
value: x,
symbol: r[2],
prefix: r[3],
base: r[0],
factor: r[1],
plural: x!=1?true:false,
s: x!=1?"s":"",
unit: unit,
units: x!=1?unit+"s":unit
};
return format?format.apply(obj):obj;
}
}
var prefixByte = new Prefixer("B",[
[2, 0, '', ''],
[2, 10, 'K', 'Kilo'],
[2, 20, 'M', 'Mega'],
[2, 30, 'G', 'Giga'],
[2, 40, 'T', 'Tera'],
[2, 50, 'P', 'Peta'],
[2, 60, 'E', 'Exa'],
[2, 70, 'Z', 'Zetta'],
[2, 80, 'Y', 'Yotta']
], function(){
return parseFloat(this.value.toFixed(2))+" "+this.symbol+this.unit;
}
);
var prefixByteLong = new Prefixer("byte",[
[2, 0, '', ''],
[2, 10, 'K', 'Kilo'],
[2, 20, 'M', 'Mega'],
[2, 30, 'G', 'Giga'],
[2, 40, 'T', 'Tera'],
[2, 50, 'P', 'Peta'],
[2, 60, 'E', 'Exa'],
[2, 70, 'Z', 'Zetta'],
[2, 80, 'Y', 'Yotta']
], function(){
return parseFloat(this.value.toFixed(2))+" "+this.prefix+this.units;
}
);
var prefixBit = new Prefixer("bit",[
[10, 0, '', ''],
[10, 3, 'K', 'Kilo'],
[10, 6, 'M', 'Mega'],
[10, 9, 'G', 'Giga'],
[10, 12, 'T', 'Tera'],
[10, 15, 'P', 'Peta'],
[10, 18, 'E', 'Exa'],
[10, 21, 'Z', 'Zetta'],
[10, 24, 'Y', 'Yotta']
], function(){
return this.value+" "+this.symbol+this.unit;
}
);
var prefixBitLong = new Prefixer("bit",[
[10, 0, '', ''],
[10, 3, 'K', 'Kilo'],
[10, 6, 'M', 'Mega'],
[10, 9, 'G', 'Giga'],
[10, 12, 'T', 'Tera'],
[10, 15, 'P', 'Peta'],
[10, 18, 'E', 'Exa'],
[10, 21, 'Z', 'Zetta'],
[10, 24, 'Y', 'Yotta']
], function(){
return this.value+" "+this.prefix+this.units;
}
);
</script>
</body></html>