FunnLearn FREE ONLINE TOOLS Explore Tools →

Creative Play

Engage kids with hands-on activities that spark imagination and make learning joyful.

Printable Worksheets

Easy-to-use, fun worksheets designed to reinforce key skills and concepts.

Parent Tips

Helpful advice to support your child’s learning journey every day.

Our Gallery

Snapshots of joyful learning moments with funnlearn activities.

Join Us

Dive into fun learning activities that spark curiosity and growth every day.
if(n!==0&&Math.abs(n)<0.000001){return n.toExponential(3);} return FMT?FMT.format(n):String(n); } function parseNum(raw){ var s=String(raw).replace(/[\s\u00a0]/g,''); if(s.charAt(s.length-1)==='%'){s=s.slice(0,-1);} if(s===''){return {empty:true};} var hasComma=s.indexOf(',')!==-1,hasDot=s.indexOf('.')!==-1; if(hasComma&&hasDot){ if(s.lastIndexOf(',')>s.lastIndexOf('.')){s=s.replace(/\./g,'').replace(',','.');} else{s=s.replace(/,/g,'');} }else if(hasComma){ if(/^[+-]?\d{1,3}(,\d{3})+$/.test(s)){s=s.replace(/,/g,'');} else{s=s.replace(',','.');} } if(!/^[+-]?(\d+\.?\d*|\.\d+)$/.test(s)){return {invalid:true};} var n=Number(s); if(!isFinite(n)){return {invalid:true};} return {value:n}; } var MINUS=' \u2212 ',TIMES=' \u00d7 ',DIV=' \u00f7 '; var CALCS={ percentOf:function(x,y){ var r=x/100*y; return {num:r,main:fmt(r),detail:fmt(x)+'% of '+fmt(y)+' = '+fmt(x)+DIV+'100'+TIMES+fmt(y)+' = '+fmt(r)}; }, whatPercent:function(x,y){ if(y===0){return {error:'Y cannot be zero, because dividing by zero is not possible.'};} var r=x/y*100; return {num:r,main:fmt(r)+'%',detail:fmt(x)+' is '+fmt(r)+'% of '+fmt(y)+'. Formula: '+fmt(x)+DIV+fmt(y)+TIMES+'100 = '+fmt(r)+'%'}; }, change:function(x,y){ if(x===0){return {error:'X (the starting value) cannot be zero, because a percentage change from zero is undefined.'};} var r=(y-x)/Math.abs(x)*100; var rc=clean(r); var word=rc>0?'an increase of ':'a decrease of '; var formula='Formula: ('+fmt(y)+MINUS+fmt(x)+')'+DIV+fmt(Math.abs(x))+TIMES+'100 = '+fmt(r)+'%'; if(rc===0){return {num:r,main:'0%',detail:'No change from '+fmt(x)+' to '+fmt(y)+'. '+formula};} return {num:r,main:(rc>0?'+':'')+fmt(r)+'%',detail:'From '+fmt(x)+' to '+fmt(y)+' is '+word+fmt(Math.abs(r))+'%. '+formula}; }, addSub:function(x,y,mode){ var amount=x*y/100; var sub=(mode==='subtract'); var r=sub?x-amount:x+amount; return {num:r,main:fmt(r),detail:fmt(x)+(sub?MINUS:' + ')+fmt(y)+'% = '+fmt(x)+(sub?MINUS:' + ')+fmt(amount)+' = '+fmt(r)}; }, ofWhat:function(x,y){ if(y===0){return {error:'Y (the percentage) cannot be zero, because dividing by zero is not possible.'};} var r=x/(y/100); return {num:r,main:fmt(r),detail:fmt(x)+' is '+fmt(y)+'% of '+fmt(r)+'. Formula: '+fmt(x)+DIV+'('+fmt(y)+DIV+'100) = '+fmt(r)} } }; function fallbackCopy(str,done){ var ta=document.createElement('textarea'); ta.value=str;ta.setAttribute('readonly',''); ta.style.position='fixed';ta.style.top='-1000px';ta.style.opacity='0'; root.appendChild(ta);ta.select(); try{ta.setSelectionRange(0,str.length);}catch(e){} var ok=false; try{ok=document.execCommand('copy');}catch(e){ok=false;} root.removeChild(ta); done(ok); } function copyText(str,done){ if(navigator.clipboard){ if(window.isSecureContext){ navigator.clipboard.writeText(str).then(function(){done(true);},function(){fallbackCopy(str,done);}); return; } } fallbackCopy(str,done); } function setupCard(card){ var name=card.getAttribute('data-calc'); var inputs=Array.prototype.slice.call(card.querySelectorAll('input[data-field]')); var sel=card.querySelector('select[data-field]'); var out=card.querySelector('.fl-pc__out'); var mainEl=card.querySelector('[data-main]'); var detailEl=card.querySelector('[data-detail]'); var btnCopy=card.querySelector('[data-act="copy"]'); var btnClear=card.querySelector('[data-act="clear"]'); var msgEl=card.querySelector('[data-msg]'); if(!CALCS[name]||!out||!mainEl||!detailEl||!btnCopy||!btnClear||inputs.length<2){throw new Error('a calculator card is incomplete');} var copyValue='',timer,msgTimer; function show(state,main,detail,copy){ out.className='fl-pc__out'+(state?' is-'+state:''); mainEl.textContent=main; detailEl.textContent=detail; copyValue=copy; btnCopy.disabled=!copy; } function update(){ var vals={},anyEmpty=false,bad=null; inputs.forEach(function(inp){ inp.removeAttribute('aria-invalid'); var p=parseNum(inp.value); if(p.empty){anyEmpty=true;return;} if(p.invalid){ inp.setAttribute('aria-invalid','true'); if(!bad){bad=inp;} return; } vals[inp.getAttribute('data-field')]=p.value; }); if(bad){ show('error','','Please enter a valid number in the "'+bad.getAttribute('data-name')+'" box. Use digits with an optional minus sign and decimal point.',''); return; } if(anyEmpty){ show('','','Enter both numbers to see the result.',''); return; } var r; try{r=CALCS[name](vals.x,vals.y,sel?sel.value:'');}catch(e){r={error:'Sorry, this could not be calculated.'};} if(r.error){show('error','',r.error,'');return;} if(!isFinite(r.num)){show('error','','The result is too large to display.','');return;} show('ok',r.main,r.detail,r.main); } inputs.forEach(function(inp){ inp.addEventListener('input',function(){clearTimeout(timer);timer=setTimeout(update,250);}); }); if(sel){sel.addEventListener('change',update);} btnCopy.addEventListener('click',function(){ if(!copyValue){return;} copyText(copyValue,function(ok){ msgEl.textContent=ok?'Copied.':'Copy failed. Please copy it manually.'; msgEl.style.color=ok?'':'#b91c1c'; clearTimeout(msgTimer); msgTimer=setTimeout(function(){msgEl.textContent='';},2500); }); }); btnClear.addEventListener('click',function(){ clearTimeout(timer); inputs.forEach(function(inp){inp.value='';}); update(); inputs[0].focus(); }); update(); } cardEls.forEach(setupCard); if(loadingEl){loadingEl.hidden=true;} } function init(root){ if(root.getAttribute('data-init')==='1'){return;} root.setAttribute('data-init','1'); var loadingEl=root.querySelector('#fl-pc-loading'); try{ build(root,loadingEl); }catch(err){ if(loadingEl){ loadingEl.hidden=false; loadingEl.textContent='Sorry, this calculator could not start ('+(err&&err.message?err.message:'unknown error')+'). Please reload the page.'; } } } function start(){ var root=document.getElementById('fl-pc'); if(!root){return false;} init(root); return true; } if(!start()){ var tries=0; var tmr=setInterval(function(){ tries=tries+1; if(start()||tries>=50){clearInterval(tmr);} },200); document.addEventListener('DOMContentLoaded',start); } })();