(function (d, w, undefined) {
const ww = new Worker(getInlineJS());
const tresholdselector = d.querySelector('#treshold');
const print = Helpers.log2Screen;
tresholdselector.addEventListener('change', start);
start();
ww.onmessage = e => {
// status message during calculation
if (e.data.status) {
return print( 'Found <code>' + e.data.found +
'</code> prime numbers',
{clear: true, direct: true} );
}
d.querySelector('#waiting').classList.add("hidden");
$('#warning').addClass('hidden');
// print result
print( e.data.msg, ', calculation took ', e.data.duration,
' millisecond', e.data.duration != 1 ? 's': '',
e.data.primes && e.data.primes.length > 10000 ?
'<br><b class="warn">Busy</b> ' +
'(reflow/repaint takes time and unfortunaly that\'s blocking)' : '',
'<h3>Prime numbers listing</h3>', {clear: true, direct: true} );
warnWait();
setTimeout(() => {
let xresult = d.createElement('div');
xresult.id = "PRIMES";
xresult.style.display = "none";
xresult.innerHTML = e.data.primes.join(' ');
d.body.appendChild(xresult);
xresult.style.display = "";
warnWait(true, "Done");
}, 10);
};
function warnWait(end, replaceText) {
const warner = d.querySelector('b.warn');
if (!warner) {return true;}
var action = end ? "remove" : "add";
warner.classList[action]("spin");
warner.textContent = replaceText || warner.textContent;
}
function start() {
const previous = d.querySelector("#PRIMES");
if (previous) {d.body.removeChild(previous);}
print('start working...', {clear:true, direct: true});
$('#warning')[+tresholdselector.value > 100000 ? 'removeClass' : 'addClass']('hidden');
d.querySelector('#waiting').classList.remove("hidden");
ww.postMessage({value: tresholdselector.value});
}
function getInlineJS() {
const ecmaCode = d.querySelector('[data-isworker]').textContent;
const ecmaBlob = new Blob([ecmaCode], {"type": "application\/javascript"});
return URL.createObjectURL(ecmaBlob);
}
}(document, window))
<div class="solink" data-linkid="26312971"></div>
<h3>Using a web worker to calculate prime numbers from 0 to [Threshold]</h3>
<p id="chunking"></p>
<div id="waiting" class="hidden"><b class="working spin">Working</b> (Browser is <i>not</i> blocked)</div>
Threshold: <select id="treshold">
<option value="10">10</option>
<option value="100" selected="selected">100</option>
<option value="1000">1000</option>
<option value="10000">10,000</option>
<option value="100000">100,000</option>
<option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option>
<option value="100000000">100,000,000</option>
</select>
<script type="text/ecmaworker" data-isworker="true">
String.prototype.padLeft = String.prototype.padLeft ||
function padLeft(base, chr) {
var len = (String(base || 10).length - String(this).length) + 1;
return len > 0 ? new Array(len).join(chr || '0') + this : this;
};
Number.prototype.pretty = function (usa, noprecision){
const somenum = this;
const dec = (''+somenum).split(/[.,]/);
const lendec = dec[1] ? dec[1].length : 0
const precision = lendec && !noprecision ? decPrecise(somenum,lendec) : dec[1]
const sep = usa ? ',' : '.';
const decsep = usa ? '.' : ',';
// from http://stackoverflow.com/questions/10473994/javascript-adding-decimal-numbers-issue/10474209
function decPrecise(d,l){
return String(d.toFixed(12)).split(/[.,]/)[1].substr(0,l);
}
function xsep(num,sep) {
let n = String(num).split('');
let i = -3;
while (n.length + i > 0) {
n.splice(i, 0, sep);
i -= 4;
}
return n.join('');
}
return xsep(dec[0],sep) + (dec[1] ? decsep+precision :'');
}
onmessage = function (e) {
let n = 0;
let total = 0;
const THRESHOLD = +e.data.value;
const startTime = new Date;
const padFactor = Math.floor(THRESHOLD/10);
let primes = [];
while (++n < THRESHOLD) {
let isprime = isPrime(n);
total += isprime ? 1 : 0;
void( isprime && (primes.push(String(n).padLeft(padFactor, ' ')),
primes.length % 100 < 1 && postMessage({status: true, found: primes.length})) );
}
postMessage({ msg: 'Found <code>' + total.pretty(1) +
'</code> prime numbers using threshold <code>' +
THRESHOLD.pretty(1) + '</code>',
primes: primes,
duration: (new Date - startTime).pretty(1)});
function isPrime(number) {
if (number % 2 === 0 && number > 2) { return false; }
let start = 2;
const limit = Math.sqrt(number);
while (start <= limit) {
if (number % start++ < 1) return false;
}
return number > 1;
}
}
</script>
#theChunks {
margin-top: 1.5em;
}
#warning {
color: red;
font-weight: bold;
}
.hidden {
display: none;
}
.numbers {
font-family: courier new;
}
#PRIMES {
font-family: courier new;
white-space: pre-line;
}
#waiting {
width: 300px;
height: 1.2em;
position: relative;
margin-bottom: 1em;
}
.wait {
width: 20px;
position: absolute;
top: 0;
bottom: 0;
background-color: red;
transition: all ease-in-out 0.1s 0s;
}
@keyframes spinner {
from {
-moz-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-moz-transform: rotateY(-360deg);
-ms-transform: rotateY(-360deg);
transform: rotateY(-360deg);
}
}
.warn, .working {
color: red;
}
.spin {
display: inline-block;
animation: spinner 1s linear infinite;
}