تاروپود — خودآموز HTML و CSS

فصل ۳ از ۹

پیشرفت ترم
۰٪

ترم ۷ · پل به JavaScript

پیدا کردن و تغییرِ عنصر

فصل ۳پیش‌نمایش رایگان
۷ دقیقه مطالعه فصل ۳

در این فصل چه می‌سازی#

این فصل JavaScript را به صفحه وصل می‌کند: با document.querySelector عنصر را با همان selector های CSS که از ترم ۲ بلدی پیدا می‌کنی، متنش را با textContent می‌خوانی و عوض می‌کنی، و ظاهرش را با classList و style تغییر می‌دهی. آخر فصل کارتی داری که وقتی صفحه باز می‌شود، JavaScript تیترش را عوض می‌کند، وضعیتش را می‌نویسد و برجسته‌اش می‌کند — بدون این‌که دستت به HTML بخورد.

ذره‌بینی که از میان چند کارتِ هم‌شکل روی یک صفحه، یکی را پیدا کرده و یک قلم‌مو همان یک کارت را رنگ و متنِ تازه می‌زند

آخر این فصل می‌توانی:

  • عنصر را با querySelector و selector های آشنا پیدا کنی و در یک const نگه داری
  • textContent یک عنصر را بخوانی و عوض کنی
  • با classList یک class آماده را روشن و خاموش کنی و با style یک property را مستقیم بدهی
  • خطای null را بشناسی و دو علتِ همیشگی‌اش را پیدا کنی

قبل از شروع#

  • از ترم ۲: selector ها — .class، نوع، descendant. querySelector دقیقاً همین زبان را حرف می‌زند.
  • از فصل ۱: قانونِ «<script> آخرِ <body>» — امروز بالاخره می‌فهمی چرا.
  • از فصل ۲: const و template literal.

مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.

۱. پلی به چیزی که از قبل بلدی#

خبرِ خوبِ این فصل: چیزِ تازه‌ای برای «پیدا کردن» یاد نمی‌گیری. document.querySelector یک جمله بیشتر نیست: «ای سند، اولین عنصری را که به این selector می‌خورد بده به من.» و selector همان زبانی است که دو ترم است با آن CSS می‌نویسی.

HTML کارتِ این فصل این است:

<article class="card">
  <h1 class="card__title">کارت من</h1>
  <p class="card__status">هنوز خبری نیست.</p>
</article>

حالا در تب JS، تیتر را پیدا کن و متنش را بخوان:

const title = document.querySelector(".card__title");
console.log(title.textContent);

querySelector خودِ عنصر را برمی‌گرداند و ما در جعبهٔ title نگهش می‌داریم — همان const فصل قبل. بعد title.textContent یعنی «متنِ داخل این عنصر».

چک کن: در console نوشته: کارت من. JavaScript صفحه را خواند.

اگر selector به چند عنصر بخورد چه؟ querySelector فقط اولین را می‌دهد و تمام.

۲. نوشتن روی صفحه — قولِ فصل ۱#

خواندن تماشاست؛ نوشتن قدرت است. به textContent مقدار بده تا متنِ عنصر عوض شود:

title.textContent = "کارتِ زنده";

const writer = "JavaScript";
const status = document.querySelector(".card__status");
status.textContent = `این متن را ${writer} نوشت، نه HTML.`;

چک کن: روی خودِ صفحه، تیترِ کارت شده «کارتِ زنده» و زیرش نوشته «این متن را JavaScript نوشت، نه HTML.» — template literal فصل قبل هم سرِ کار آمد.

این همان راهِ درستی است که فصل ۱ قولش را دادیم: document.write فقط بلد بود متن را تهِ صفحه بریزد؛ این‌جا دقیقاً همان عنصری را که می‌خواهی نشانه می‌گیری و عوض می‌کنی.

۳. وقتی querySelector چیزی پیدا نمی‌کند#

حالا مهم‌ترین خرابیِ این فصل را عمداً بساز. در selector یک غلطِ تایپی بگذار:

const title = document.querySelector(".card__titel");
console.log(title.textContent);

صفحه بی‌تغییر می‌ماند و console سرخ می‌شود:

Uncaught TypeError: Cannot read properties of null (reading 'textContent')
    at script.js:3

🔧 اگر کار نکرد: این پیام دو تکه دارد. null یعنی «هیچ‌چیز»: وقتی querySelector عنصری با آن selector پیدا نکند، بی‌سروصدا null برمی‌گرداند و شکایتی نمی‌کند. خطا تازه وقتی می‌ترکد که از دلِ آن هیچ‌چیز، چیزی بخواهی — این‌جا reading 'textContent'. پس ترجمهٔ واقعیِ این پیام تقریباً همیشه این است: «selector ات به هیچ عنصری نخورد.» selector را حرف‌به‌حرف با HTML مقایسه کن: titel باید title باشد. (در آزمایشگاه، جای script.js:3 چیزی مثل about:srcdoc با شماره‌خطِ دیگری می‌نشیند — سندِ پیش‌نمایشِ آزمایشگاه است؛ خطا را با متنِ پیام بشناس، نه با فایل و شماره‌خط.)

و یک دامِ دوم با همان علامت: selector ات درست است ولی <script> را در <head> گذاشته‌ای. مرورگر صفحه را از بالا به پایین می‌خواند؛ در <head> هنوز هیچ <article> ای ساخته نشده، پس querySelector در آن لحظه راست می‌گوید: «چیزی نیست!» این همان چراییِ قانونِ فصل ۱ است: <script> آخرِ <body> می‌نشیند تا وقتی اجرا می‌شود، همهٔ عنصرها ساخته شده باشند.

⚠️ مواظب باش: نقطهٔ اولِ selector جزئی از خودِ selector است — همان‌طور که در CSS بود. querySelector("card__title") بدونِ نقطه یعنی «تگی به نامِ card__title»، که وجود ندارد و باز null می‌گیری.

اگر هر دو مظنون را چک کردی و هنوز گیر بودی، وقتِ کمک‌گرفتن است:

🤖 با AI: وقتی به null خوردی و پیدا نکردی چرا، HTML ات و خطِ querySelector را با هم به دستیار AI ات بده و بپرس: «چرا این selector به چیزی نمی‌خورد؟» جوابش را با دو مظنونِ همین فصل بسنج — غلطِ تایپی و جای <script> — و فقط وقتی قبولش کن که بعد از اصلاح، خطا واقعاً از console رفته باشد.

Checkpoint. قبل از ادامه، جواب بده: اگر صفحه دو <p class="card__status"> داشته باشد، querySelector(".card__status") متنِ کدام را عوض می‌کند؟ (جواب: فقط اولین را. برای گرفتنِ دومی یک نشانیِ دقیق‌تر لازم داری — مثلاً یک id.)

۴. تغییرِ ظاهر: classList و style#

برای ظاهر دو دستگیره داری. اولی و بهترش classList است: class ای را که استایلش را از قبل در CSS نوشته‌ای روشن یا خاموش می‌کند. فرض کن در styles.css این را داری:

.highlight {
  background-color: #fff3c4;
  border-color: #e0a800;
}

حالا از JS روشنش کن:

const card = document.querySelector(".card");
card.classList.add("highlight");

classList.add این class را به عنصر اضافه می‌کند — انگار خودت در HTML نوشته باشی — و classList.remove("highlight") برش می‌دارد.

دستگیرهٔ دوم style است: یک property را مستقیم روی عنصر می‌گذارد:

status.style.color = "#1b7a43";

فقط حواست باشد property های دوکلمه‌ای مثل background-color در JS به شکلِ backgroundColor نوشته می‌شوند — خط تیره در اسمِ JavaScript مجاز نیست.

چک کن: کارت زردِ برجسته شد و جملهٔ وضعیت سبز. همهٔ این‌ها هنگام بازشدنِ صفحه اتفاق افتاد.

💡 نکته: تا می‌توانی classList، نه style. استایل باید در CSS زندگی کند — همان درسِ ترم ۶ — و JS فقط کلید را بزند. style را برای وقتی نگه دار که مقدار واقعاً از دلِ JS می‌آید.

کد کاملِ این فصل#

<!-- 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>
      <article class="card">
        <h1 class="card__title">کارت من</h1>
        <p class="card__status">هنوز خبری نیست.</p>
      </article>
    </main>

    <script src="script.js"></script>
  </body>
</html>

فایل styles.css:

/* styles.css */
body {
  font-family: Tahoma, sans-serif;
  background-color: #f6edda;
  color: #2c2114;
  line-height: 1.7;
  padding: 24px;
}

.card {
  background-color: #ffffff;
  border: 1px solid #d8ccae;
  border-radius: 12px;
  padding: 16px;
  max-width: 360px;
}

.highlight {
  background-color: #fff3c4;
  border-color: #e0a800;
}

و script.js:

// script.js — kart-e zende
const title = document.querySelector(".card__title");
console.log(title.textContent);

title.textContent = "کارتِ زنده";

const writer = "JavaScript";
const status = document.querySelector(".card__status");
status.textContent = `این متن را ${writer} نوشت، نه HTML.`;

const card = document.querySelector(".card");
card.classList.add("highlight");
status.style.color = "#1b7a43";

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
document داکیومِنت خودِ صفحه، از نگاه JavaScript
querySelector کوئری‌سِلِکتور اولین عنصری را که به یک selector می‌خورد برمی‌گرداند
textContent تکست‌کانتِنت متنِ داخل یک عنصر — هم خواندنی، هم نوشتنی
null نال مقدارِ «هیچ‌چیز»؛ جوابِ querySelector وقتی چیزی پیدا نکند
classList کلس‌لیست فهرست class های یک عنصر، با add و remove
style استایل دادنِ مستقیمِ یک property به یک عنصر از داخل JS

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

همهٔ تغییرهای این فصل هنگامِ بازشدنِ صفحه اجرا شدند — کاربر هنوز نقشی ندارد. فصل بعد کد را به دستِ او می‌دهیم: با addEventListener و رویدادِ click، تکه‌کدت فقط وقتی اجرا می‌شود که کاربر واقعاً کلیک کند — و صفحه برای اولین بار به معنای کامل تعاملی می‌شود.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.