![ظاهر برنامه](https://quera.org/qbox/view/h6UyYGFnYU/dk_js_router_org.gif)
*شکرستون* یک شهرِ به شدت در حال رشد است و میزان خرید شهروندانش بسیار بالا رفته، اما از آنجایی که مشکلات زیرساختی زیادی درونش وجود دارد، روی تجربهی کاربری خیلی از محصولاتش تأثیر گذاشته است. مهدی یک مهندس نرمافزار در دیجیکالای *شکرستون* است و قصد دارد طی یه حرکت خفن، تجربهی کاربری این سایت را بهتر کند!
یکی از مواردی که از نظر مهدی خیلی روی تجربهی کاربری سایت تأثیرگذار است، *refresh* شدن صفحات پس از کلیک کردن روی لینکها است. پس از کمی سرچ و مشورت، او متوجه شد که راهحل مشکلش، استفاده از کتابخانهی `react-router` است اما متأسفانه دیجیکالا در *شکرستون* با جاوااسکریپت خام نوشته شده!
مهدی تصمیم گرفته که وارد میدان شود و با کمک شما، یک کتابخانهی *client router* بسازد. از آنجایی که تجربهی کاربر برای مهدی خیلی مهم است، جابهجایی بین صفحات نباید باعث *refresh* شدن صفحه شود تا سرعت برنامه بالاتر رود. همچنین زمانی که کاربر روی دکمههای جلو و عقب مرورگر کلیک میکند، باید صفحهی قبلی یا بعدی بدون تأخیر نمایش داده شود.
مهدی به تنهایی نمیتواند کل این کتابخانه را پیادهسازی کند. او از شما خواسته که در پیادهسازی این کتابخانه به او کمک کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/39252/download_problem_initial_project/135563/) دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای پروژه
</summary>
```
client-router
├── assets
│ ├── css
│ │ └── style.css
│ ├── fonts
│ │ └── vazir.woff2
│ └── product_data.json
├── clientRouter.js
├── index.html
├── main.js
└── package.json
```
</details>
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
برای اجرای پروژه، باید *Node.js* و *npm* را از قبل نصب کرده باشید.
- پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `client-router` دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
</details>
یکی از جذابترین مواردی که مهدی در `react-router` دیده بود، قابلیت *route params* است. مهدی نیز تصمیم گرفته این قابلیت را به کتابخانهاش اضافه کند. این قابلیت به اینصورت کار میکند که هنگام تعریف *route* ، اگر قبل از یکی از پارامترها `:` گذاشته شود، آن بخش از *URL* هنگام *render* به فانکشنش پاس داده میشود. مثال:
%align_right_start%
### *route*:
%align_end%
```
/product/:id/comments/:user
```
%align_right_start%
### *render function*:
%align_end%
```javascript
({id, user}) => { `<div>${id}-${user}</div>` }
```
پروژه شامل دو فایل `main.js` و `clientRouter.js` است.
فایل `main.js` شامل صفحات برنامه است. هر صفحه یک فانکشن است که *route params* را بهعنوان ورودی دریافت کرده و یک رشتهی *HTML* را در جواب برمیگرداند.
در انتها نیز کتابخانهی `clientRouter` صدا زده شده و صفحات بهعنوان یک پارامتر به آن پاس داده میشوند.
شما باید فایل `clientRouter.js` را طوری پیادهسازی کنید که برنامه همانند ویدیوی موجود در ابتدای صورت سؤال کار کند.
فایل `clientRouter.js` شامل توابع زیر است:
- تابع `processRoutes`: این تابع پس از هر تغییر در صفحه صدا زده میشود و وظیفهی پردازش و مقایسهی *route* ها را برعهده دارد.
- تابع `handleLinks`: این تابع وظیفهی اضافه کردن *event listener* ها را به لینکهای موجود در صفحه برعهده دارد.
- تابع `handleRouteChange`: این تابع وظیفهی گوش کردن به تغییرات *URL* و اجرای توابع بالا بر حسب نیاز را برعهده دارد و از قبل پیادهسازی شده است.
# نکات
- فایل `clientRouter` باید به گونهای طراحی شود که تنها با اجرای تابع `initializeRouter` و پاس دادن ورودی های مناسب، برنامه بهصورت یک *SPA* شروع به کار کند.
- صفحات در قالب توابعی که یک رشتهی *HTML* برمیگردانند تعریف میشوند و *route param* ها بهعنوان یک آبجکت به این توابع پاس داده میشوند.
- اگر `clientRouter` نتوانست با هیچکدام از صفحات مچ شود، باید صفحه ی `404` به کاربر نشان داده شود.
- لینکهایی که توسط *client router* هندل می شوند، به جای استفاده از اتریبیوت `href`، از اتریبیوت `data-href` استفاده میکنند تا از لینک های معمولی متمایز شوند.
نمونه:
```html
<a data-href="/products">test link</a>
```
- هنگام هندل کردن *event* های مربوط به لینکها، به جای استفاده از `event.target`، از `event.currentTarget` استفاده کنید تا هنگام کلیک روی *element* های زیرمجموعه لینک شما، بتوانید به *element* والد دسترسی داشته باشید. [جزئیات بیشتر](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget)
- شما تنها مجاز به اعمال تغییرات در فایل `clientRouter.js` هستید.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، فایل `clientRouter.js` را آپلود کنید.