آموزش ساخت ماشین حساب حرفه ای با جاوا اسکریپت
ماشین حساب جاوا اسکریپت – در این مقاله با استفاده از Vanilla Js ( جاوا اسکریپت خالص ) بدون هیچ کتابخانه ای یک ماشین حساب calculator شیک و زیبا بسازیم که علاوه بر دکمه خود امکان استفاده از صفحه کلید را هم داشته باشد .
همچنین در این پروژه از حالت روشن / تاریک هم بهره می بریم برای کاربردی تر شدن ماشین حساب .
دموی برنامه
صفحه index.html
<!DOCTYPE html> <html lang="fa"> <head> <meta charset="UTF-8"> <title>Rapidcode.iR - سورس کد</title> <link rel="stylesheet" href="static/css/main.css"> </head> <body> <div class="container"> <a id="introduce" href="https://rapidcode.ir" target="_blank">رپید کد • کتابخانه مجازی برنامه نویسان</a> <label for="dark-mode">حالت نمایشی :</label> <select id="dark-mode"> <option value="light">روشن</option> <option value="dark">تاریک</option> </select> <form id="calculator" name="form"> <div class="display"> <input type="text" placeholder="0" id="displayResult" name="displayResult" readonly="readonly"/> </div> <div class="buttons"> <div class="row"> <input type="button" class="func-btn wid-2" name="clear" value="C"> <input type="button" class="func-btn wid-2" name="backspace" value="←"> </div> <div class="row"> <input type="button" class="func-btn" name="b7" value="7"> <input type="button" class="func-btn" name="b8" value="8"> <input type="button" class="func-btn" name="b9" value="9"> <input type="button" class="func-btn" name="addb" value="+"> </div> <div class="row"> <input type="button" class="func-btn" name="b4" value="4"> <input type="button" class="func-btn" name="b5" value="5"> <input type="button" class="func-btn" name="b6" value="6"> <input type="button" class="func-btn" name="subb" value="-"> </div> <div class="row"> <input type="button" class="func-btn" name="b1" value="1"> <input type="button" class="func-btn" name="b2" value="2"> <input type="button" class="func-btn" name="b3" value="3"> <input type="button" class="func-btn" name="mulb" value="*"> </div> <div class="row"> <input type="button" class="func-btn" name="b0" value="0"> <input type="button" class="func-btn" name="potb" value="."> <input type="button" class="func-btn" name="divb" value="/"> <input type="button" class="func-btn red" name="equal" value="="> </div> </div> </form> </div> <script src="static/js/app.js"></script> </body> </html>
اسکریپت app.js
// DOM const darkModeDOM = document.getElementById("dark-mode"); const calculatorDOM = document.getElementById("calculator"); const buttonsDOM = document.getElementsByClassName("func-btn"); const displayResultDOM = document.getElementById('displayResult'); // Property let displayResultDOMScrollWidth = displayResultDOM.scrollWidth; let displayResultDOMScrollX = 0; // set handler darkModeDOM.onchange = darkModeDOMChangeHandler; loopThrowDOMS(buttonsDOM, function(element) { element.onclick = buttonsDOMClick; }); window.onkeyup = globalKeyPressedHandler; // handlers function darkModeDOMChangeHandler(event) { const thisElementValue = event.target.value; const darkModeClass = "dark"; loopThrowDOMS(buttonsDOM, function(element) { if (thisElementValue == "light" && element.classList.contains(darkModeClass)) element.classList.remove(darkModeClass); else if (thisElementValue == "dark" && !element.classList.contains(darkModeClass)) element.classList.add(darkModeClass); }); if (thisElementValue == "light" && calculatorDOM.classList.contains(darkModeClass)) calculatorDOM.classList.remove(darkModeClass) else if (thisElementValue == "dark" && !calculatorDOM.classList.contains(darkModeClass)) calculatorDOM.classList.add(darkModeClass); } function globalKeyPressedHandler(event) { const pressedKey = event.key; const validKeys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "=", "-", "+", "*", "/", "Enter", "Backspace", "Delete"]; const functionalKey = { "equal": ["Enter", "="], "backspace": ["Backspace"], "clear": ["Delete"] }; var btnName = pressedKey; loopThrowObject(functionalKey, function(element1, index, mainArray) { const currentElement = functionalKey[element1]; currentElement.forEach(function(element2) { if (element2 == pressedKey) { btnName = element1; } }); }); const target = { value: pressedKey, name: btnName } const thisEvent = { target: target } if (validKeys.includes(pressedKey)) { buttonsDOMClick(thisEvent); } } function buttonsDOMClick(event) { const thisElementValue = event.target.value; const thisElementName = event.target.name; const specialFunctionalityHandlerNames = ["equal", "clear", "backspace"]; if (specialFunctionalityHandlerNames.includes(thisElementName)) { switch (thisElementName) { case 'equal': try { equalDOMHandler(); } catch (err) { alert("خطای ورودی عملیات ریاضی"); } break; case 'clear': try { clearDOMHandler(); } catch (err) { alert("خطای ورودی عملیات ریاضی"); } break; case 'backspace': try { backspaceDOMHandler(); } catch (err) { alert("خطای ورودی عملیات ریاضی"); } break; } displayResultDOMScrollHandler(); return; } displayResultDOM.value += thisElementValue; displayResultDOMScrollHandler(); } function displayResultDOMScrollHandler() { displayResultDOMScrollX = displayResultDOM.scrollWidth - displayResultDOMScrollWidth; displayResultDOM.scrollLeft = displayResultDOMScrollX; } function equalDOMHandler() { const mathOperation = displayResult.value; const result = eval(mathOperation); if(!isFinite(result)){ alert("امکان محاسبه این عملیات ریاضی وجود ندارد !"); return; } displayResult.value = result; } function clearDOMHandler() { displayResult.value = ""; } function backspaceDOMHandler() { let mathOperation = displayResult.value; mathOperation = mathOperation.substring(0, (mathOperation.length) - 1); displayResult.value = mathOperation; } // helpers function loopThrowDOMS(doms, funcHandler) { const tmpDOMS = Array.from(doms); tmpDOMS.forEach(funcHandler); } function loopThrowObject(obj, funcHandler) { const tmpObjectKeys = Object.keys(obj); tmpObjectKeys.forEach(funcHandler); }
- در بخش DOM از element های مورد نیاز مان دسترسی خواهیم گرفت با استفاده از id و class
- Property ها شامل ScrollX یا همان بخش scroll افقی نمایشگر اطلاعات ریاضی هست
- set handler برای دکمه های ماشین حساب در زمانی که فشرده شدن عملی را انجام دهد ، همچنین برای زمانی که صفحه کلید فشرده شد تابعی را تعریف می کنیم
- قسمت handlers شامل توابعی هست جهت کنترل کلید های صفحه کلید و دکمه های خود ماشین حساب و حالت روشن / تاریک ماشین حساب
- darkModeDOMChangeHandler تابعی برای تغییر از حالت روشن به تاریک یا برعکس
- globalKeyPressedHandler برای انجام عملیات ریاضی از طریق صفحه کلید فیزیکی
- buttonsDOMClick برای کنترل دکمه های ماشین حساب در زمانی که کلیک شود
- displayResultDOMScrollHandler زمانی که مقدار داده های نمایشی زیاد شود نیاز است که برای نمایش آخرین اعداد کاربر scroll شود که با این تابع امکان پذیر است .
- equalDOMHandler زمانی که = زده شود یا دکمه Enter زده شود محاسبه را انجام داده و عدد نهایی را نمایش می دهد
- clearDOMHandler در صورتی که دکمه C زده شود با این تابع تمامی مقادیر را reset یا پاک می کنیم
- backspaceDOMHandler زمانی که میخواهیم یک عمل به قبل برگردیم مثلا 123 را با این تابع به 12 تبدیل و نمایش می دهیم
- helpers : شامل توابع کمکی است که در توسعه راحت تر برنامه ما را یاری می کند
- loopThrowDOMS : جهت چرخش در بین element هایی که دارای یک کلاس می باشند
- loopThrowObject : جهت چرخش در object ها
فایل main.css جهت استایل دادن به برنامه
#calculator{ position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #fff; box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.2); border-radius: 14px; padding-bottom: 20px; width: 320px; } #calculator.dark{ background: #6b6969; } .display { width: 100%; height: 60px; padding: 40px 0; background: #FF0509; border-top-left-radius: 14px; border-top-right-radius: 14px; } .buttons { padding: 20px 20px 0 20px; } .row { width: 280px; float: left; } .func-btn { width: 60px; height: 60px; float: left; padding: 0; margin: 5px; box-sizing: border-box; background: #ecedef; border: none; font-size: 30px; line-height: 30px; border-radius: 50%; font-weight: 700; color: #5E5858; cursor: pointer; } .wid-2{ width: 130px; border-radius: 4px; } .func-btn.dark{ background: #424242; color: #fff; border: 1px solid #fff; } input[type=text] { width: 270px; height: 60px; float: left; direction: ltr; text-align: left; padding: 0; box-sizing: border-box; border: none; background: none; color: #ffffff; font-weight: 700; font-size: 60px; line-height: 60px; margin: 0 25px; outline: none; } .red { background: #FF0509 !important; color: #ffffff !important; } .red.dark{ border:1px solid #FF0509; }
ارسال نظر