[{"data":1,"prerenderedAt":289},["ShallowReactive",2],{"lesson:t7-s09-js-capstone":3,"course:taropood":61},{"meta":4,"prev":11,"next":15,"sections":16},{"free_preview":5,"order":6,"slug":7,"source":8,"term":9,"title_fa":10},true,9,"t7-s09-js-capstone","book",7,"فصل ۰۹ — پروژهٔ نهایی: یک صفحهٔ قدیمی را تعاملی کن",{"free_preview":5,"order":12,"slug":13,"source":8,"term":9,"title_fa":14},8,"t7-s08-fetch-data","فصل ۰۸ — گرفتن داده از اینترنت",null,[17,21,24,29,32,35,38,41,44,46,48,51,54,58],{"kind":18,"heading":19,"html":20},"normal","در این فصل چه می‌سازی","\u003Ch2 id=\"در-این-فصل-چه-می‌سازی\">در این فصل چه می‌سازی\u003Ca class=\"head-anchor\" href=\"#%D8%AF%D8%B1-%D8%A7%DB%8C%D9%86-%D9%81%D8%B5%D9%84-%DA%86%D9%87-%D9%85%DB%8C%E2%80%8C%D8%B3%D8%A7%D8%B2%DB%8C\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>این فصل هیچ مفهومِ تازه‌ای ندارد — و این بهترین خبرِ ممکن است: یعنی برای ساختنِ همه‌چیزِ این پروژه، همین حالا همه‌چیز را بلدی. یک صفحهٔ نمونه‌کار — از همان جنسی که در ترم‌های قبل ساختی — تحویل می‌گیری و سه قابلیتِ واقعی به آن اضافه می‌کنی: یک کلیدِ تمِ روشن\u002Fتیره، فهرستِ پروژه‌هایی که فیلتر می‌شود، و فرمی که به کاربرش جوابِ درست می‌دهد. آخرِ این فصل، آخرِ تاروپود است.\u003C\u002Fp>\n\u003Cp>\u003Cpicture>\u003Csource type=\"image\u002Fwebp\" srcset=\"\u002F_img\u002F01-image-interactive-portfolio.cf6658107b.160.webp 160w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.320.webp 320w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.640.webp 640w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.1280.webp 1280w\" sizes=\"(max-width: 900px) 100vw, 800px\">\u003Cimg src=\"\u002F_img\u002F01-image-interactive-portfolio.cf6658107b.1280.jpg\" srcset=\"\u002F_img\u002F01-image-interactive-portfolio.cf6658107b.160.jpg 160w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.320.jpg 320w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.640.jpg 640w, \u002F_img\u002F01-image-interactive-portfolio.cf6658107b.1280.jpg 1280w\" sizes=\"(max-width: 900px) 100vw, 800px\" alt=\"صفحهٔ نمونه‌کار که نیمی روشن و نیمی تیره است، با یک کلید تغییر حالت، فهرستی در حال فیلترشدن از میان یک قیف، و فرمی با علامت تأیید سبز\" width=\"1376\" height=\"768\" loading=\"lazy\" decoding=\"async\">\u003C\u002Fpicture>\u003C\u002Fp>\n\u003Cp>آخر این فصل می‌توانی:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>با \u003Ccode>classList.toggle\u003C\u002Fcode> و custom property ها تمِ کلِ صفحه را عوض کنی\u003C\u002Fli>\n\u003Cli>یک فهرست را از روی چند آرایه، بسته به انتخابِ کاربر، از نو بسازی\u003C\u002Fli>\n\u003Cli>به فرم بازخوردِ خطا و موفقیت بدهی\u003C\u002Fli>\n\u003Cli>پروژه را با یک چک‌لیستِ تحویل، مثل یک حرفه‌ای ببندی\u003C\u002Fli>\n\u003C\u002Ful>\n",{"kind":18,"heading":22,"html":23},"قبل از شروع","\u003Ch2 id=\"قبل-از-شروع\">قبل از شروع\u003Ca class=\"head-anchor\" href=\"#%D9%82%D8%A8%D9%84-%D8%A7%D8%B2-%D8%B4%D8%B1%D9%88%D8%B9\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>از فصل ۵:\u003C\u002Fstrong> \u003Ccode>classList.toggle\u003C\u002Fcode> — و \u003Cstrong>از ترم ۲:\u003C\u002Fstrong> custom property ها.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>از فصل ۷:\u003C\u002Fstrong> آرایه، \u003Ccode>for...of\u003C\u002Fcode>، \u003Ccode>createElement\u003C\u002Fcode>\u002F\u003Ccode>append\u003C\u002Fcode> و الگوی «اول خالی کن، بعد از نو بساز».\u003C\u002Fli>\n\u003Cli>\u003Cstrong>از فصل ۶:\u003C\u002Fstrong> \u003Ccode>value\u003C\u002Fcode>، \u003Ccode>submit\u003C\u002Fcode>، \u003Ccode>preventDefault\u003C\u002Fcode> و \u003Ccode>if\u003C\u002Fcode>\u002F\u003Ccode>else\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.\u003C\u002Fp>\n",{"kind":25,"heading":26,"html":27,"embed":28},"lab","","— صفحهٔ نمونه‌کار با استایلِ کامل و پنجرهٔ JS تقریباً خالی منتظرِ توست. هر سه قابلیت را همین‌جا می‌سازی","\u002Flab\u002Fembed\u002Ftaropood\u002Fterm-7-javascript\u002Fsession-09-js-capstone",{"kind":18,"heading":30,"html":31},"۱. صفحه‌ای که تحویل می‌گیری","\u003Ch2 id=\"۱-صفحه‌ای-که-تحویل-می‌گیری\">۱. صفحه‌ای که تحویل می‌گیری\u003Ca class=\"head-anchor\" href=\"#%DB%B1-%D8%B5%D9%81%D8%AD%D9%87%E2%80%8C%D8%A7%DB%8C-%DA%A9%D9%87-%D8%AA%D8%AD%D9%88%DB%8C%D9%84-%D9%85%DB%8C%E2%80%8C%DA%AF%DB%8C%D8%B1%DB%8C\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>صفحه یک نمونه‌کارِ کوچک است: سرصفحه‌ای با اسم و دکمهٔ «تغییر تم» که هنوز کاری نمی‌کند، بخشِ پروژه‌ها با سه دکمهٔ فیلتر، فرمِ تماس، و پاصفحه:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>&lt;!-- index.html --&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;fa&quot; dir=&quot;rtl&quot;&gt;\n  &lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n    &lt;title&gt;نمونه‌کارهای پروانه&lt;\u002Ftitle&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;&gt;\n  &lt;\u002Fhead&gt;\n  &lt;body&gt;\n    &lt;header class=&quot;site-header&quot;&gt;\n      &lt;h1&gt;نمونه‌کارهای پروانه&lt;\u002Fh1&gt;\n      &lt;button id=&quot;theme-btn&quot; type=&quot;button&quot;&gt;تغییر تم&lt;\u002Fbutton&gt;\n    &lt;\u002Fheader&gt;\n\n    &lt;main&gt;\n      &lt;section class=&quot;projects&quot;&gt;\n        &lt;h2&gt;پروژه‌های من&lt;\u002Fh2&gt;\n        &lt;button id=&quot;all-btn&quot; class=&quot;filter&quot; type=&quot;button&quot;&gt;همه&lt;\u002Fbutton&gt;\n        &lt;button id=&quot;web-btn&quot; class=&quot;filter&quot; type=&quot;button&quot;&gt;سایت‌ها&lt;\u002Fbutton&gt;\n        &lt;button id=&quot;fun-btn&quot; class=&quot;filter&quot; type=&quot;button&quot;&gt;تمرین‌های سرگرمی&lt;\u002Fbutton&gt;\n        &lt;ul id=&quot;project-list&quot;&gt;\n          &lt;li&gt;کارت پروفایل&lt;\u002Fli&gt;\n          &lt;li&gt;وبلاگ شخصی&lt;\u002Fli&gt;\n          &lt;li&gt;صفحهٔ فرود محصول&lt;\u002Fli&gt;\n          &lt;li&gt;گالری عکس&lt;\u002Fli&gt;\n          &lt;li&gt;کارت تبریک&lt;\u002Fli&gt;\n        &lt;\u002Ful&gt;\n      &lt;\u002Fsection&gt;\n\n      &lt;section class=&quot;contact&quot;&gt;\n        &lt;h2&gt;پیام بده&lt;\u002Fh2&gt;\n        &lt;form id=&quot;contact-form&quot;&gt;\n          &lt;label for=&quot;name-input&quot;&gt;اسمت:&lt;\u002Flabel&gt;\n          &lt;input type=&quot;text&quot; id=&quot;name-input&quot;&gt;\n          &lt;button type=&quot;submit&quot;&gt;بفرست&lt;\u002Fbutton&gt;\n        &lt;\u002Fform&gt;\n        &lt;p id=&quot;form-note&quot;&gt;&lt;\u002Fp&gt;\n      &lt;\u002Fsection&gt;\n    &lt;\u002Fmain&gt;\n\n    &lt;footer class=&quot;site-footer&quot;&gt;\n      &lt;p&gt;ساختهٔ پروانه — پایانِ تاروپود&lt;\u002Fp&gt;\n    &lt;\u002Ffooter&gt;\n\n    &lt;script src=&quot;script.js&quot;&gt;&lt;\u002Fscript&gt;\n  &lt;\u002Fbody&gt;\n&lt;\u002Fhtml&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>به یک تصمیم دقت کن: فهرستِ پروژه‌ها را عمداً در HTML هم نوشته‌ایم تا صفحه حتی بدونِ JavaScript هم کامل دیده شود — همان درسِ فصلِ قبل: JS تزئین است، نه ستون.\u003C\u002Fp>\n\u003Cp>CSS صفحه با custom property ها نوشته شده و یک قاعدهٔ آماده هم منتظرِ توست:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>body.dark {\n  --bg: #201a12;\n  --surface: #2c2114;\n  --ink: #f6edda;\n  --accent: #7fb4d6;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>یعنی هر وقت \u003Ccode>body\u003C\u002Fcode> یک class به اسمِ \u003Ccode>dark\u003C\u002Fcode> بگیرد، همهٔ رنگ‌های صفحه با هم عوض می‌شوند. CSS اش هست؛ فقط مانده کسی آن class را روشن و خاموش کند — کارِ تو.\u003C\u002Fp>\n",{"kind":18,"heading":33,"html":34},"۲. کلیدِ تم","\u003Ch2 id=\"۲-کلیدِ-تم\">۲. کلیدِ تم\u003Ca class=\"head-anchor\" href=\"#%DB%B2-%DA%A9%D9%84%DB%8C%D8%AF%D9%90-%D8%AA%D9%85\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>با دانشِ فصل ۵، اولین تلاشِ خیلی‌ها این است:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>const themeBtn = document.querySelector('#theme-btn');\n\nthemeBtn.addEventListener('click', function () {\n  themeBtn.classList.toggle('dark');\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>دکمه را بزن. \u003Cstrong>هیچ اتفاقی نمی‌افتد.\u003C\u002Fstrong> نه خطایی در console، نه تغییری روی صفحه — از همان خرابی‌های بی‌صدا که از ترم‌های CSS خوب می‌شناسی.\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>🔧 \u003Cstrong>اگر کار نکرد:\u003C\u002Fstrong> در DevTools به عنصرها نگاه کن: class \u003Ccode>dark\u003C\u002Fcode> دارد اضافه و کم می‌شود، ولی روی \u003Cstrong>دکمه\u003C\u002Fstrong>. selector تو در CSS \u003Ccode>body.dark\u003C\u002Fcode> است — قاعده منتظرِ \u003Ccode>dark\u003C\u002Fcode> روی \u003Ccode>body\u003C\u002Fcode> است، نه روی دکمه. class را همان‌جایی toggle کن که CSS منتظرش است — و \u003Ccode>document.body\u003C\u002Fcode> میان‌برِ همیشگیِ JS به خودِ \u003Ccode>&lt;body&gt;\u003C\u002Fcode> است، بدونِ نیاز به \u003Ccode>querySelector\u003C\u002Fcode>:\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>themeBtn.addEventListener('click', function () {\n  document.body.classList.toggle('dark');\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>✅ \u003Cstrong>چک کن:\u003C\u002Fstrong> با هر کلیک، کلِ صفحه بینِ روشن و تیره می‌رود — و آن transition ی که از ترم ۵ می‌شناسی، جابه‌جایی را نرم کرده است.\u003C\u002Fp>\n",{"kind":18,"heading":36,"html":37},"۳. فیلترِ پروژه‌ها","\u003Ch2 id=\"۳-فیلترِ-پروژه‌ها\">۳. فیلترِ پروژه‌ها\u003Ca class=\"head-anchor\" href=\"#%DB%B3-%D9%81%DB%8C%D9%84%D8%AA%D8%B1%D9%90-%D9%BE%D8%B1%D9%88%DA%98%D9%87%E2%80%8C%D9%87%D8%A7\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>داده را مثل فصل ۷ نگه می‌داریم: هر دسته یک آرایه، و «همه» را هم با همان \u003Ccode>push\u003C\u002Fcode> و حلقه می‌سازیم:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>const webProjects = ['کارت پروفایل', 'وبلاگ شخصی', 'صفحهٔ فرود محصول'];\nconst funProjects = ['گالری عکس', 'کارت تبریک'];\n\nconst allProjects = [];\nfor (const project of webProjects) {\n  allProjects.push(project);\n}\nfor (const project of funProjects) {\n  allProjects.push(project);\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>بعد سه دکمه، سه listener — هرکدام همان الگوی آشنا: اول خالی کن، بعد بساز:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>webBtn.addEventListener('click', function () {\n  projectList.textContent = '';\n  for (const project of webProjects) {\n    const item = document.createElement('li');\n    item.textContent = project;\n    projectList.append(item);\n  }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>دو listener دیگر همین‌اند، فقط با آرایهٔ خودشان (کدِ کامل پایین است). بله — سه تکهٔ تقریباً یکسان نوشتیم و این تکرار آزاردهنده است. قرار هم هست باشد: کوتاه‌کردنِ این تکرار یعنی تعریفِ functionِ خودت، و آن دقیقاً اولین درسِ مسیرِ JavaScript بعد از این پل است. امروز، تکرارِ صادقانه بهتر از ابزاری است که هنوز یاد نگرفته‌ای.\u003C\u002Fp>\n\u003Cp>✅ \u003Cstrong>چک کن:\u003C\u002Fstrong> «سایت‌ها» سه پروژه نشان می‌دهد، «تمرین‌های سرگرمی» دو تا، و «همه» هر پنج تا — بدونِ هیچ دوقلوشدنی، چون قبل از هر ساختن خالی می‌کنی.\u003C\u002Fp>\n",{"kind":18,"heading":39,"html":40},"۴. بازخوردِ فرم","\u003Ch2 id=\"۴-بازخوردِ-فرم\">۴. بازخوردِ فرم\u003Ca class=\"head-anchor\" href=\"#%DB%B4-%D8%A8%D8%A7%D8%B2%D8%AE%D9%88%D8%B1%D8%AF%D9%90-%D9%81%D8%B1%D9%85\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>فرمِ بی‌جواب، دیوارِ بی‌در است. با ابزارِ فصل ۶ (سه عنصرِ فرم را هم با \u003Ccode>querySelector\u003C\u002Fcode> گرفته‌ایم — کدِ کامل پایین):\u003C\u002Fp>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>form.addEventListener('submit', function (event) {\n  event.preventDefault();\n\n  if (nameInput.value === '') {\n    formNote.textContent = 'اسمت را ننوشته‌ای — فرمِ خالی جایی نمی‌رود.';\n    formNote.classList.add('error');\n  } else {\n    formNote.textContent = `ممنون ${nameInput.value}! فرمت بی‌نقص پر شده.`;\n    formNote.classList.remove('error');\n  }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>✅ \u003Cstrong>چک کن:\u003C\u002Fstrong> ارسالِ خالی پیامِ قرمز می‌گیرد؛ با اسم، پیامِ عادی و مؤدبانه. (فرستادنِ واقعیِ پیام سرور می‌خواهد — کارِ ما اینجا بازخوردِ صادقانه به کاربر است.)\u003C\u002Fp>\n",{"kind":18,"heading":42,"html":43},"۵. چک‌لیستِ تحویل","\u003Ch2 id=\"۵-چک‌لیستِ-تحویل\">۵. چک‌لیستِ تحویل\u003Ca class=\"head-anchor\" href=\"#%DB%B5-%DA%86%DA%A9%E2%80%8C%D9%84%DB%8C%D8%B3%D8%AA%D9%90-%D8%AA%D8%AD%D9%88%DB%8C%D9%84\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>حرفه‌ای‌ها پروژه را با حس تمام نمی‌کنند؛ با چک‌لیست تمام می‌کنند. یکی‌یکی، واقعاً امتحان کن:\u003C\u002Fp>\n\u003Col>\n\u003Cli>کلیدِ تم کار می‌کند و بعد از ده کلیکِ پشتِ هم هم گیج نمی‌شود.\u003C\u002Fli>\n\u003Cli>در هر دو تم، همهٔ متن‌ها — حتی متنِ روی دکمه‌ها — خوانا هستند.\u003C\u002Fli>\n\u003Cli>هر سه فیلتر فهرستِ درستِ خودشان را نشان می‌دهند و فهرست هرگز دوقلو نمی‌شود.\u003C\u002Fli>\n\u003Cli>ارسالِ فرمِ خالی پیامِ خطا می‌گیرد — نه سکوت.\u003C\u002Fli>\n\u003Cli>با کلیدِ \u003Ccode>Tab\u003C\u002Fcode> به همهٔ دکمه‌ها و فرم می‌رسی، چون همه \u003Ccode>&lt;button&gt;\u003C\u002Fcode> و \u003Ccode>&lt;input&gt;\u003C\u002Fcode> واقعی‌اند (ترم ۱).\u003C\u002Fli>\n\u003Cli>با JavaScript خاموش هم صفحه محتوایش را نشان می‌دهد — فهرست در HTML هست.\u003C\u002Fli>\n\u003Cli>صفحه در عرضِ موبایل هم سالم است (ترم ۴).\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>اگر همهٔ تیک‌ها خورد، پروژه‌ات \u003Cstrong>تحویل‌دادنی\u003C\u002Fstrong> است.\u003C\u002Fp>\n",{"kind":25,"heading":26,"html":45,"embed":28},"می‌خواهی کارَت را با نسخهٔ تمام‌شده مقایسه کنی؟ در  دکمهٔ «نمایش خروجی نهایی» را بزن تا نسخهٔ کامل در ویرایشگر باز شود و خط‌به‌خطش را با مالِ خودت مقایسه کن؛ «بازنشانی» به کدِ شروع برت می‌گرداند",{"kind":18,"heading":26,"html":47},"\n\u003Cp>و یک قدمِ آخرِ حرفه‌ای:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>🤖 \u003Cstrong>با AI:\u003C\u002Fstrong> حالا که پروژه تمام است، کلِ \u003Ccode>script.js\u003C\u002Fcode> ات را به دستیار AI ات بده و بپرس: «این کد چه می‌کند و کجاهایش تکراری است؟» جایی که تکرار را نشانت می‌دهد، همان جایی است که این فصل عمداً ساده نگه داشت. پیشنهادهایش را فقط بخوان و بفهم — با چیزی که در آزمایشگاه می‌بینی مقایسه کن، ولی امروز چیزی را عوض نکن: کدِ کارکردهٔ تحویل‌دادنی، از کدِ «قشنگ‌ترِ» نصفه‌کاره باارزش‌تر است.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n",{"kind":18,"heading":49,"html":50},"کدِ کاملِ پروژه","\u003Ch2 id=\"کدِ-کاملِ-پروژه\">کدِ کاملِ پروژه\u003Ca class=\"head-anchor\" href=\"#%DA%A9%D8%AF%D9%90-%DA%A9%D8%A7%D9%85%D9%84%D9%90-%D9%BE%D8%B1%D9%88%DA%98%D9%87\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cpre class=\"code-block\" dir=\"ltr\">\u003Ccode>\u002F\u002F script.js\n\n\u002F* --- 1) kelid-e theme --- *\u002F\nconst themeBtn = document.querySelector('#theme-btn');\n\nthemeBtn.addEventListener('click', function () {\n  document.body.classList.toggle('dark');\n});\n\n\u002F* --- 2) filter-e prozhe-ha --- *\u002F\nconst webProjects = ['کارت پروفایل', 'وبلاگ شخصی', 'صفحهٔ فرود محصول'];\nconst funProjects = ['گالری عکس', 'کارت تبریک'];\n\nconst allProjects = [];\nfor (const project of webProjects) {\n  allProjects.push(project);\n}\nfor (const project of funProjects) {\n  allProjects.push(project);\n}\n\nconst projectList = document.querySelector('#project-list');\nconst allBtn = document.querySelector('#all-btn');\nconst webBtn = document.querySelector('#web-btn');\nconst funBtn = document.querySelector('#fun-btn');\n\nallBtn.addEventListener('click', function () {\n  projectList.textContent = '';\n  for (const project of allProjects) {\n    const item = document.createElement('li');\n    item.textContent = project;\n    projectList.append(item);\n  }\n});\n\nwebBtn.addEventListener('click', function () {\n  projectList.textContent = '';\n  for (const project of webProjects) {\n    const item = document.createElement('li');\n    item.textContent = project;\n    projectList.append(item);\n  }\n});\n\nfunBtn.addEventListener('click', function () {\n  projectList.textContent = '';\n  for (const project of funProjects) {\n    const item = document.createElement('li');\n    item.textContent = project;\n    projectList.append(item);\n  }\n});\n\n\u002F* --- 3) bazkhord-e form --- *\u002F\nconst form = document.querySelector('#contact-form');\nconst nameInput = document.querySelector('#name-input');\nconst formNote = document.querySelector('#form-note');\n\nform.addEventListener('submit', function (event) {\n  event.preventDefault();\n\n  if (nameInput.value === '') {\n    formNote.textContent = 'اسمت را ننوشته‌ای — فرمِ خالی جایی نمی‌رود.';\n    formNote.classList.add('error');\n  } else {\n    formNote.textContent = `ممنون ${nameInput.value}! فرمت بی‌نقص پر شده.`;\n    formNote.classList.remove('error');\n  }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>index.html\u003C\u002Fcode> را بالا دیدی؛ \u003Ccode>styles.css\u003C\u002Fcode> کامل هم در آزمایشگاه است — تماماً چیزهایی که خودت در هفت ترم ساخته‌ای.\u003C\u002Fp>\n",{"kind":18,"heading":52,"html":53},"واژه‌های تازهٔ این فصل","\u003Ch2 id=\"واژه‌های-تازهٔ-این-فصل\">واژه‌های تازهٔ این فصل\u003Ca class=\"head-anchor\" href=\"#%D9%88%D8%A7%DA%98%D9%87%E2%80%8C%D9%87%D8%A7%DB%8C-%D8%AA%D8%A7%D8%B2%D9%87%D9%94-%D8%A7%DB%8C%D9%86-%D9%81%D8%B5%D9%84\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>کلمه\u003C\u002Fth>\n\u003Cth>تلفظ به حروف فارسی\u003C\u002Fth>\n\u003Cth>یعنی چه\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>capstone\u003C\u002Ftd>\n\u003Ctd>کَپ‌استون\u003C\u002Ftd>\n\u003Ctd>پروژهٔ پایانی که همهٔ آموخته‌ها را یک‌جا به‌کار می‌گیرد\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>ship\u003C\u002Ftd>\n\u003Ctd>شیپ\u003C\u002Ftd>\n\u003Ctd>تحویل‌دادنِ کار، وقتی چک‌لیستش واقعاً پاس شده\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>",{"kind":55,"heading":56,"html":57},"checkpoint","تمرین‌ها","\u003Ch2 id=\"تمرین‌ها\">تمرین‌ها\u003Ca class=\"head-anchor\" href=\"#%D8%AA%D9%85%D8%B1%DB%8C%D9%86%E2%80%8C%D9%87%D8%A7\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>Checkpoint.\u003C\u002Fstrong> قبل از تمرین، بدون نگاه‌کردن به بالا جواب بده: چرا فهرستِ پروژه‌ها را هم در HTML نوشتیم و هم در آرایه؟\u003C\u002Fp>\n\u003Cp>\u003Cstrong>تمرین اجباری:\u003C\u002Fstrong> دستهٔ سومی به پروژه‌ها اضافه کن — مثلاً «آزمایش‌ها» — با آرایهٔ خودش، دکمهٔ خودش و listener خودش؛ و حلقهٔ سومی هم به ساختِ \u003Ccode>allProjects\u003C\u002Fcode> اضافه کن تا «همه» دستهٔ تازه را هم بشمارد.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>تمرین ستاره‌دار ⭐:\u003C\u002Fstrong> دکمهٔ فیلترِ فعال را برجسته کن: یک class به اسمِ \u003Ccode>active\u003C\u002Fcode> در CSS بساز و در هر listener آن را به دکمهٔ خودش \u003Ccode>add\u003C\u002Fcode> و از دو دکمهٔ دیگر \u003Ccode>remove\u003C\u002Fcode> کن — تا کاربر همیشه بداند کدام فیلتر روشن است.\u003C\u002Fp>\n",{"kind":18,"heading":59,"html":60},"در فصل بعد","\u003Ch2 id=\"در-فصل-بعد\">در فصل بعد\u003Ca class=\"head-anchor\" href=\"#%D8%AF%D8%B1-%D9%81%D8%B5%D9%84-%D8%A8%D8%B9%D8%AF\" aria-label=\"پیوند به این بخش\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>فصلِ بعدی وجود ندارد. اینجا پایانِ تاروپود است.\u003C\u002Fp>\n\u003Cp>هفت ترم پیش با یک فایلِ خالی شروع کردی. حالا پشتِ سرت: صفحه‌هایی با اسکلتِ semantic، استایلی که cascade اش را می‌فهمی، layout هایی با flexbox و grid که در هر عرضی سالم می‌مانند، حالت و حرکت، کدِ تمیزِ component محور — و حالا صفحه‌ای که به کاربرش جواب می‌دهد. تار HTML بود، پود CSS، و این ترمِ آخر نخِ جانی بود که پارچه را تکان داد.\u003C\u002Fp>\n\u003Cp>و یک حرفِ صادقانه دربارهٔ ادامهٔ راه: این ترم یک پل بود، نه یک دورهٔ JavaScript. آن‌طرفِ پل دنیای بزرگی است — function هایی که خودت تعریف می‌کنی، object ها، آرایه‌های عمیق‌تر، و بعدها framework ها — و یادگیریِ عمیقش یک خودآموزِ جداست برای وقتی که خواستی. ولی مهم‌ترین ابزار را همین حالا داری، چون هفت ترم است که داری تمرینش می‌کنی: بساز، خرابش کن، بفهم چرا خراب شد، درستش کن.\u003C\u002Fp>\n\u003Cp>وب همیشه همین بوده: آدم‌هایی که چیزی می‌سازند و نشانش می‌دهند. از امروز تو یکی از آن‌هایی. چیزی بساز.\u003C\u002Fp>\n",{"course":62,"entitled":69,"lessons":70,"payments_enabled":69,"terms":288,"live":5},{"active_window":15,"effective_price_toman":63,"free":5,"lesson_count":64,"price_toman":65,"slug":66,"summary_fa":67,"title_fa":68},0,71,1500000,"taropood","از صفر تا ساختن سایت واقعی با HTML و CSS. متن‌محور، با آزمایشگاه زندهٔ داخل مرورگر و اصطلاح‌های اصیل.","تاروپود — خودآموز HTML و CSS",false,[71,75,79,83,87,91,95,98,101,104,108,112,115,118,121,124,127,130,133,136,139,142,145,148,151,154,157,160,163,166,169,172,175,178,181,184,187,190,193,196,199,202,205,208,211,214,217,220,223,226,229,232,235,238,241,244,247,250,253,256,259,262,265,268,271,274,277,280,283,286,287],{"free_preview":5,"order":72,"slug":73,"source":8,"term":72,"title_fa":74},1,"t1-s01-first-page","فصل ۰۱ — اولین صفحهٔ وب تو",{"free_preview":5,"order":76,"slug":77,"source":8,"term":72,"title_fa":78},2,"t1-s02-text","فصل ۰۲ — متن: عنوان و پاراگراف",{"free_preview":5,"order":80,"slug":81,"source":8,"term":72,"title_fa":82},3,"t1-s03-links","فصل ۰۳ — پیوند: چیزی که وب را وب کرد",{"free_preview":5,"order":84,"slug":85,"source":8,"term":72,"title_fa":86},4,"t1-s04-images","فصل ۰۴ — تصویر",{"free_preview":5,"order":88,"slug":89,"source":8,"term":72,"title_fa":90},5,"t1-s05-lists","فصل ۰۵ — فهرست",{"free_preview":5,"order":92,"slug":93,"source":8,"term":72,"title_fa":94},6,"t1-s06-semantic","فصل ۰۶ — اسکلت معنادار صفحه",{"free_preview":5,"order":9,"slug":96,"source":8,"term":72,"title_fa":97},"t1-s07-tables","فصل ۰۷ — جدول، فقط برای داده",{"free_preview":5,"order":12,"slug":99,"source":8,"term":72,"title_fa":100},"t1-s08-forms","فصل ۰۸ — فرم: گرفتن ورودی",{"free_preview":5,"order":6,"slug":102,"source":8,"term":72,"title_fa":103},"t1-s09-accessibility","فصل ۰۹ — دسترس‌پذیری از همان HTML",{"free_preview":5,"order":105,"slug":106,"source":8,"term":72,"title_fa":107},10,"t1-s10-media","فصل ۱۰ — ویدیو و صدا",{"free_preview":5,"order":109,"slug":110,"source":8,"term":72,"title_fa":111},11,"t1-s11-first-project","فصل ۱۱ — پروژه: صفحهٔ معرفی خودت",{"free_preview":5,"order":72,"slug":113,"source":8,"term":76,"title_fa":114},"t2-s01-first-css","فصل ۰۱ — اولین CSS",{"free_preview":5,"order":76,"slug":116,"source":8,"term":76,"title_fa":117},"t2-s02-selectors","فصل ۰۲ — selector ها",{"free_preview":5,"order":80,"slug":119,"source":8,"term":76,"title_fa":120},"t2-s03-cascade","فصل ۰۳ — cascade، specificity و inheritance",{"free_preview":5,"order":84,"slug":122,"source":8,"term":76,"title_fa":123},"t2-s04-box-model","فصل ۰۴ — جعبه‌ها: box model",{"free_preview":5,"order":88,"slug":125,"source":8,"term":76,"title_fa":126},"t2-s05-units-colors","فصل ۰۵ — واحد و رنگ",{"free_preview":5,"order":92,"slug":128,"source":8,"term":76,"title_fa":129},"t2-s06-typography","فصل ۰۶ — تایپوگرافی و فونت فارسی",{"free_preview":5,"order":9,"slug":131,"source":8,"term":76,"title_fa":132},"t2-s07-flow","فصل ۰۷ — جریان عادی صفحه",{"free_preview":5,"order":12,"slug":134,"source":8,"term":76,"title_fa":135},"t2-s08-decoration","فصل ۰۸ — پس‌زمینه، حاشیه، سایه",{"free_preview":5,"order":6,"slug":137,"source":8,"term":76,"title_fa":138},"t2-s09-custom-props","فصل ۰۹ — متغیرهای خودت در CSS",{"free_preview":5,"order":105,"slug":140,"source":8,"term":76,"title_fa":141},"t2-s10-devtools","فصل ۱۰ — DevTools: ابزار واقعی",{"free_preview":5,"order":109,"slug":143,"source":8,"term":76,"title_fa":144},"t2-s11-styled-project","فصل ۱۱ — صفحهٔ ترم ۱ را زنده کن",{"free_preview":5,"order":72,"slug":146,"source":8,"term":80,"title_fa":147},"t3-s01-layout-intro","فصل ۰۱ — چیدمان: از جریان عادی شروع کن",{"free_preview":5,"order":76,"slug":149,"source":8,"term":80,"title_fa":150},"t3-s02-flex-basics","فصل ۰۲ — flexbox: یک محور",{"free_preview":5,"order":80,"slug":152,"source":8,"term":80,"title_fa":153},"t3-s03-flex-align","فصل ۰۳ — چیدن و وسط‌چین کردن",{"free_preview":5,"order":84,"slug":155,"source":8,"term":80,"title_fa":156},"t3-s04-flex-grow","فصل ۰۴ — انعطاف واقعی",{"free_preview":5,"order":88,"slug":158,"source":8,"term":80,"title_fa":159},"t3-s05-grid-basics","فصل ۰۵ — grid: دو محور",{"free_preview":5,"order":92,"slug":161,"source":8,"term":80,"title_fa":162},"t3-s06-grid-placement","فصل ۰۶ — جای‌گذاری در grid",{"free_preview":5,"order":9,"slug":164,"source":8,"term":80,"title_fa":165},"t3-s07-grid-areas","فصل ۰۷ — layout کامل صفحه با grid",{"free_preview":5,"order":12,"slug":167,"source":8,"term":80,"title_fa":168},"t3-s08-position","فصل ۰۸ — position",{"free_preview":5,"order":6,"slug":170,"source":8,"term":80,"title_fa":171},"t3-s09-stacking","فصل ۰۹ — z-index و stacking context",{"free_preview":5,"order":105,"slug":173,"source":8,"term":80,"title_fa":174},"t3-s10-logical","فصل ۱۰ — logical properties",{"free_preview":5,"order":109,"slug":176,"source":8,"term":80,"title_fa":177},"t3-s11-layout-project","فصل ۱۱ — پروژه: layout یک سایت کامل",{"free_preview":5,"order":72,"slug":179,"source":8,"term":84,"title_fa":180},"t4-s01-responsive-intro","فصل ۰۱ — responsive یعنی چه",{"free_preview":5,"order":76,"slug":182,"source":8,"term":84,"title_fa":183},"t4-s02-media-queries","فصل ۰۲ — media query",{"free_preview":5,"order":80,"slug":185,"source":8,"term":84,"title_fa":186},"t4-s03-responsive-images","فصل ۰۳ — تصویر responsive",{"free_preview":5,"order":84,"slug":188,"source":8,"term":84,"title_fa":189},"t4-s04-fluid-type","فصل ۰۴ — تایپوگرافی سیال و ریاضی در CSS",{"free_preview":5,"order":88,"slug":191,"source":8,"term":84,"title_fa":192},"t4-s05-container-queries","فصل ۰۵ — container query",{"free_preview":5,"order":92,"slug":194,"source":8,"term":84,"title_fa":195},"t4-s06-responsive-nav","فصل ۰۶ — ناوبری responsive",{"free_preview":5,"order":9,"slug":197,"source":8,"term":84,"title_fa":198},"t4-s07-dark-mode","فصل ۰۷ — dark mode",{"free_preview":5,"order":12,"slug":200,"source":8,"term":84,"title_fa":201},"t4-s08-responsive-project","فصل ۰۸ — پروژه: سایت کاملاً responsive",{"free_preview":5,"order":72,"slug":203,"source":8,"term":88,"title_fa":204},"t5-s01-states","فصل ۰۱ — حالت‌ها: pseudo-class تعاملی",{"free_preview":5,"order":76,"slug":206,"source":8,"term":88,"title_fa":207},"t5-s02-structural-selectors","فصل ۰۲ — selector های ساختاری و combinator ها",{"free_preview":5,"order":80,"slug":209,"source":8,"term":88,"title_fa":210},"t5-s03-pseudo-elements","فصل ۰۳ — pseudo-element ها",{"free_preview":5,"order":84,"slug":212,"source":8,"term":88,"title_fa":213},"t5-s04-forms-styling","فصل ۰۴ — استایل فرم",{"free_preview":5,"order":88,"slug":215,"source":8,"term":88,"title_fa":216},"t5-s05-forms-validation","فصل ۰۵ — اعتبارسنجی فرم",{"free_preview":5,"order":92,"slug":218,"source":8,"term":88,"title_fa":219},"t5-s06-transforms","فصل ۰۶ — transform",{"free_preview":5,"order":9,"slug":221,"source":8,"term":88,"title_fa":222},"t5-s07-transitions","فصل ۰۷ — transition",{"free_preview":5,"order":12,"slug":224,"source":8,"term":88,"title_fa":225},"t5-s08-animation","فصل ۰۸ — animation و احترام به کاربر",{"free_preview":5,"order":6,"slug":227,"source":8,"term":88,"title_fa":228},"t5-s09-has-selector","فصل ۰۹ — :has() و تعامل بدون JavaScript",{"free_preview":5,"order":105,"slug":230,"source":8,"term":88,"title_fa":231},"t5-s10-interaction-project","فصل ۱۰ — پروژه: یک component تعاملی بدون JS",{"free_preview":5,"order":72,"slug":233,"source":8,"term":92,"title_fa":234},"t6-s01-organizing","فصل ۰۱ — CSS را سازماندهی کن",{"free_preview":5,"order":76,"slug":236,"source":8,"term":92,"title_fa":237},"t6-s02-layers-nesting","فصل ۰۲ — `@layer` و nesting",{"free_preview":5,"order":80,"slug":239,"source":8,"term":92,"title_fa":240},"t6-s03-components","فصل ۰۳ — مثل component فکر کن",{"free_preview":5,"order":84,"slug":242,"source":8,"term":92,"title_fa":243},"t6-s04-design-system","فصل ۰۴ — design system کوچک خودت",{"free_preview":5,"order":88,"slug":245,"source":8,"term":92,"title_fa":246},"t6-s05-svg-icons","فصل ۰۵ — SVG و آیکون",{"free_preview":5,"order":92,"slug":248,"source":8,"term":92,"title_fa":249},"t6-s06-accessibility-deep","فصل ۰۶ — دسترس‌پذیری عمیق",{"free_preview":5,"order":9,"slug":251,"source":8,"term":92,"title_fa":252},"t6-s07-performance","فصل ۰۷ — سرعت",{"free_preview":5,"order":12,"slug":254,"source":8,"term":92,"title_fa":255},"t6-s08-architecture","فصل ۰۸ — معماری CSS در مقیاس بزرگ",{"free_preview":5,"order":6,"slug":257,"source":8,"term":92,"title_fa":258},"t6-s09-debugging","فصل ۰۹ — اشکال‌زدایی مثل حرفه‌ای‌ها",{"free_preview":5,"order":105,"slug":260,"source":8,"term":92,"title_fa":261},"t6-s10-capstone-build","فصل ۱۰ — پروژهٔ نهایی: ساخت سایت چندصفحه‌ای",{"free_preview":5,"order":109,"slug":263,"source":8,"term":92,"title_fa":264},"t6-s11-capstone-ship","فصل ۱۱ — پروژهٔ نهایی: انتشار زنده",{"free_preview":5,"order":72,"slug":266,"source":8,"term":9,"title_fa":267},"t7-s01-why-js","فصل ۰۱ — چرا JavaScript؟ اولین اسکریپت",{"free_preview":5,"order":76,"slug":269,"source":8,"term":9,"title_fa":270},"t7-s02-variables","فصل ۰۲ — متغیر و مقدار",{"free_preview":5,"order":80,"slug":272,"source":8,"term":9,"title_fa":273},"t7-s03-select-change","فصل ۰۳ — پیدا کردن و تغییرِ عنصر",{"free_preview":5,"order":84,"slug":275,"source":8,"term":9,"title_fa":276},"t7-s04-events","فصل ۰۴ — رویداد",{"free_preview":5,"order":88,"slug":278,"source":8,"term":9,"title_fa":279},"t7-s05-toggle-class","فصل ۰۵ — روشن\u002Fخاموش‌کردنِ یک class: پلِ CSS و JS",{"free_preview":5,"order":92,"slug":281,"source":8,"term":9,"title_fa":282},"t7-s06-forms-js","فصل ۰۶ — کار با فرم در JavaScript",{"free_preview":5,"order":9,"slug":284,"source":8,"term":9,"title_fa":285},"t7-s07-lists-loops","فصل ۰۷ — فهرست و حلقه",{"free_preview":5,"order":12,"slug":13,"source":8,"term":9,"title_fa":14},{"free_preview":5,"order":6,"slug":7,"source":8,"term":9,"title_fa":10},[],1784860314233]