در این فصل چه میسازی#
فرمهایی که در ترم ۱ ساختی قشنگ بودند ولی گنگ: دکمه را میزدی و هیچکس جواب نمیداد. این فصل صفحه خودش جواب میدهد: چیزی که کاربر نوشته را با value میخوانی، با preventDefault جلوی عادتِ قدیمیِ مرورگر را میگیری، و با if/else اولین تصمیمِ واقعیِ کدت را میگیری. آخرش فرمِ عضویتِ یک باشگاهِ کتاب را داری که همان لحظه، بدونِ هیچ سروری، به کاربر بازخورد میدهد.

آخر این فصل میتوانی:
- نوشتهٔ داخلِ یک
<input>را باvalueبخوانی - به رویدادِ
submitفرم گوش بدهی و باpreventDefaultجلوی بارگذاریِ دوبارهٔ صفحه را بگیری - با
if/elseبر اساسِ ورودیِ کاربر دو جوابِ متفاوت بدهی - توضیح بدهی چرا listener را روی خودِ
<form>میگذاریم، نه روی کلیکِ دکمه
قبل از شروع#
- از فصل ۴:
addEventListenerو شیءِevent— امروز بالاخره قدرتِ واقعیاش را میبینی. - از فصل ۲: template literal.
- از ترم ۱:
<form>،<label>،<input>و<button>.
مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.
۱. فرمی که هنوز گنگ است#
صفحهٔ این فصل یک فرمِ آشناست — همان تگهای ترم ۱:
<section class="signup">
<h1>باشگاه کتاب</h1>
<p>اسمت را بنویس و عضو شو؛ جواب همین پایین ظاهر میشود.</p>
<form class="signup-form">
<label for="name">اسمت چیست؟</label>
<input id="name" type="text">
<button>عضو شو</button>
</form>
<p class="feedback"></p>
</section>
آن <p class="feedback"> خالی است — جای جوابِ صفحه. قرار است JS پُرش کند.
۲. رویدادِ submit و خواندنِ value#
فرم رویدادِ مخصوصِ خودش را دارد: submit، یعنی «کاربر فرم را فرستاد». و هر <input> یک value دارد: چیزی که همین الان تویش نوشته شده. اولین نسخه را بنویس:
const form = document.querySelector('.signup-form');
const nameInput = document.querySelector('#name');
const feedback = document.querySelector('.feedback');
form.addEventListener('submit', function () {
feedback.textContent = `خوش آمدی، ${nameInput.value}!`;
});
اسمت را بنویس و «عضو شو» را بزن. در یک فایلِ واقعی — همین صفحه را روی دیسک بسازی و در مرورگر باز کنی — برای یک لحظه پیامِ خوشآمد را میبینی و بعد صفحه چشمک میزند، از نو بار میشود، input خالی میشود و پیام غیبش میزند. همهچیز پرید. (در آزمایشگاه این پریدن را نمیبینی؛ چند خط پایینتر میگویم چرا.)
🔧 اگر کار نکرد: این رفتارِ پیشفرضِ
submitاست، یادگاری از دورانِ قبل از JavaScript: مرورگر فرم را برای یک سرور میفرستد و صفحه را از نو میگیرد (در فایلِ واقعی به آدرس هم نگاه کن — یک?تهش آمده). listener تو اجرا شد، ولی بلافاصله صفحه عوض شد و همهچیز از دست رفت. راهِ حل داخلِ همان بستهای است که فصل ۴ شناختی: شیءِeventیک دستورِpreventDefaultدارد، یعنی «کارِ پیشفرضت را نکن».
form.addEventListener('submit', function (event) {
event.preventDefault();
feedback.textContent = `خوش آمدی، ${nameInput.value}!`;
});
✅ چک کن: حالا «عضو شو» را بزن — پیامِ خوشآمد میآید و میماند؛ صفحه دیگر از نو بار نمیشود.
⚠️ مواظب باش: آزمایشگاهِ ما فرم را داخلِ یک iframe امن اجرا میکند: listener ات کامل اجرا میشود و
preventDefaultهم همان رفتارِ همیشگی را دارد. فقط یک تفاوت هست: اگرpreventDefaultرا ننویسی، آزمایشگاه خودش پریدنِ صفحه را بیسروصدا مهار میکند — یعنی خرابی سرِ جایش است، ولی چشمکزدن و ازنوبارشدن را آنجا نمیبینی. برای دیدنِ این خرابی با چشمِ خودت، همین سه فایل را مثل ترمِ ۶ روی دیسک بساز و در مرورگر باز کن.preventDefaultرا همیشه بنویس.
Checkpoint. قبل از ادامه، جواب بده: اگر داخلِ input باشی و Enter بزنی چه میشود؟ (جواب: باز هم submit اتفاق میافتد و همان listener اجرا میشود — برای همین به رویدادِ فرم گوش دادیم، نه به کلیکِ دکمه. Enter هیچ کلیکی نیست، ولی فرستادنِ فرم هست.)
۳. if/else: اولین تصمیم#
الان اگر هیچ اسمی ننویسی و «عضو شو» را بزنی، صفحه با افتخار میگوید «خوش آمدی، !» — جوابِ درست به ورودیِ غلط. کد باید بتواند تصمیم بگیرد: اگر input خالی است، تذکر بده؛ وگرنه خوشآمد بگو. این کارِ if/else است:
form.addEventListener('submit', function (event) {
event.preventDefault();
if (nameInput.value === '') {
feedback.textContent = 'اسمت را ننوشتهای! اول اسمت را بنویس.';
feedback.classList.add('error');
} else {
feedback.textContent = `خوش آمدی، ${nameInput.value}! عضویتت ثبت شد.`;
feedback.classList.remove('error');
}
});
if یک شرط را داخلِ پرانتز میسنجد؛ اگر برقرار بود block اول اجرا میشود، وگرنه block بعد از else. آن === یعنی «دقیقاً برابر است با» — اینجا میپرسد: نوشتهٔ input دقیقاً یک stringِ خالی است؟ و به classList.add('error') نگاه کن: JS فقط اسمِ حالت را میگذارد، قرمزیِ متن را قاعدهٔ .feedback.error در CSS میسازد — همان پلِ فصلِ قبل.
✅ چک کن: یکبار خالی بفرست — تذکرِ قرمز؛ یکبار با اسم — خوشآمدِ عادی. یک صفحه، دو جوابِ متفاوت: کدت دارد تصمیم میگیرد.
Checkpoint. قبل از ادامه، جواب بده: اگر فقط یک فاصله (space) تایپ کنی و بفرستی چه میشود؟ (جواب: از شرط رد میشود و خوشآمد میگیرد، چون ' ' با '' دقیقاً برابر نیست. این سوراخ را فعلاً میشناسیم و میپذیریم؛ ابزارِ تمیزکردنِ متن جزءِ ادامهٔ مسیرِ JS است، بیرون از این پل.)
🤖 با AI: از دستیار AI ات بپرس: «
preventDefaultغیر از فرم کجاها به کار میآید؟ سه مثال بزن.» یکی از مثالهایش را در آزمایشگاه امتحان کن و با چشمِ خودت چک کن که واقعاً همان رفتارِ پیشفرض متوقف میشود.
کد کاملِ این فصل#
<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>باشگاه کتاب</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<section class="signup">
<h1>باشگاه کتاب</h1>
<p>اسمت را بنویس و عضو شو؛ جواب همین پایین ظاهر میشود.</p>
<form class="signup-form">
<label for="name">اسمت چیست؟</label>
<input id="name" type="text">
<button>عضو شو</button>
</form>
<p class="feedback"></p>
</section>
</main>
<script src="script.js"></script>
</body>
</html>
/* styles.css */
body {
font-family: Tahoma, sans-serif;
background-color: #f6edda;
color: #2c2114;
line-height: 1.7;
padding: 24px;
}
.signup {
background-color: #ffffff;
border: 1px solid #d8ccae;
border-radius: 12px;
padding: 16px;
max-width: 360px;
}
label {
display: block;
margin-block-end: 4px;
}
input {
font-family: inherit;
font-size: 1rem;
padding: 8px;
border: 1px solid #d8ccae;
border-radius: 8px;
margin-block-end: 8px;
width: 100%;
box-sizing: border-box;
}
button {
font-family: inherit;
font-size: 1rem;
padding: 8px 16px;
border: 1px solid #b98a2f;
border-radius: 8px;
background-color: #f3d491;
cursor: pointer;
}
.feedback.error {
color: #a33520;
}
// script.js
const form = document.querySelector('.signup-form');
const nameInput = document.querySelector('#name');
const feedback = document.querySelector('.feedback');
form.addEventListener('submit', function (event) {
event.preventDefault();
if (nameInput.value === '') {
feedback.textContent = 'اسمت را ننوشتهای! اول اسمت را بنویس.';
feedback.classList.add('error');
} else {
feedback.textContent = `خوش آمدی، ${nameInput.value}! عضویتت ثبت شد.`;
feedback.classList.remove('error');
}
});
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
value |
وَلیو | چیزی که همین الان داخلِ یک <input> نوشته شده |
submit |
سابمیت | رویدادِ فرستادنِ فرم — با دکمه یا با Enter |
preventDefault |
پریوِنت دیفالت | به رویداد میگوید «کارِ پیشفرضت را نکن» |
if / else |
ایف / اِلس | اگر شرط برقرار بود این کار، وگرنه آن کار |
=== |
سهمساوی | «دقیقاً برابر است با» — مقایسهٔ سختگیرانه |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
حالا صفحهات میشنود، تصمیم میگیرد و جواب میدهد — ولی هنوز یکییکی. فصل بعد با array و حلقه آشنا میشوی: فهرستی از دادهها که JS خودش برایشان عنصر میسازد و داخلِ صفحه میچیند — همان کاری که هر سایتِ واقعی با فهرستِ محصولها و پیامهایش میکند.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.