FunnLearn FREE ONLINE TOOLS Explore Tools →

About Us

At funnlearn, we blend play with learning to help children grow confidently through creative resources and supportive tools.

Playful Learning

Creative activities that turn learning into joyful play for kids.

Parent Support

Helpful tips to guide your child’s growth and confidence.

Learning Tools

Resources designed to make lessons engaging and effective.

Growth Tips

Simple advice to nurture your child’s curiosity every day.

Join Us

Start making learning joyful and effective for your child today.
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); } })();