Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

<body>

<input type="button" id="hider" value="Click to hide the text" />
<input type="button" id="hider" value="کلیک کنید تا متن مخفی شود" />

<div id="text">Text</div>
<div id="text">متن</div>

<script>
// Here it doesn't matter how we hide the text,
// could also use style.display:
// در اینجا چگونگی مخفی کردن متن اهمیت ندارد،
// همچنین می‌توانید از style.display استفاده کنید:
document.getElementById('hider').onclick = function() {
document.getElementById('text').hidden = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

<body>

<input type="button" id="hider" value="Click to hide the text" />
<input type="button" id="hider" value="کلیک کنید تا متن مخفی شود" />

<div id="text">Text</div>
<div id="text">متن</div>

<script>
/* your code */
/* کد شما */
</script>

</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ importance: 5

---

# Hide on click
# مخفی کردن در صورت کلیک

Add JavaScript to the `button` to make `<div id="text">` disappear when we click it.
یک کد جاوا‌اسکریپتی به `button` اضافه کنید تا `<div id="text">` در زمان کلیک شدن مخفی شود.

The demo:
دمو:

[iframe border=1 src="solution" height=80]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Can use `this` in the handler to reference "the element itself" here:
برای دسترسی به "خود عنصر" می‌توانیم درون کنترل‌کننده از `this` استفاده کنیم:

```html run height=50
<input type="button" onclick="this.hidden=true" value="Click to hide">
<input type="button" onclick="this.hidden=true" value="کلیک کنید تا مخفی شود">
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Hide self
# مخفی کردن خود عنصر

Create a button that hides itself on click.
یک button بسازید که وقتی کلیک می‌شود خودش را مخفی کند.

```online
Like this:
<input type="button" onclick="this.hidden=true" value="Click to hide">
مثل این:
<input type="button" onclick="this.hidden=true" value="کلیک کنید تا مخفی شود">
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
The answer: `1` and `2`.
جواب: `1` و `2`.

The first handler triggers, because it's not removed by `removeEventListener`. To remove the handler we need to pass exactly the function that was assigned. And in the code a new function is passed, that looks the same, but is still another function.
کنترل‌کننده اول اجرا می‌شود زیرا توسط `removeEventListener` حذف نمی‌شود. برای حذف کنترل‌کننده باید دقیقا خود تابعی که استفاده کردیم را به ورودی بدهیم. و در این کد یک تابع جدید به عنوان ورودی استفاده شده که فقط شبیه هستند، اما یک تابع نیستند.

To remove a function object, we need to store a reference to it, like this:
برای حذف یک شئ تابع باید آنرا در یک متغیر به عنوان مرجع ذخیره کنیم. مانند:

```js
function handler() {
Expand All @@ -13,4 +13,4 @@ button.addEventListener("click", handler);
button.removeEventListener("click", handler);
```

The handler `button.onclick` works independently and in addition to `addEventListener`.
کنترل‌کننده `button.onclick` جدا و علاوه بر `addEventListener` کار می‌کند.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Which handlers run?
# کدام کنترل‌کننده اجرا شود؟

There's a button in the variable. There are no handlers on it.
یک دکمه درون متغیر ذخیره شده. ولی هیچ کنترل‌کننده به آن اختصاص نیافته.

Which handlers run on click after the following code? Which alerts show up?
با توجه به کد زیر، کدام کنترل‌کننده بعد از کلیک اجرا می‌شود؟ کدوم پیغام نمایش داده می‌شود؟

```js no-beautify
button.addEventListener("click", () => alert("1"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

First we need to choose a method of positioning the ball.
اول نیاز داریم که روش قرارگیری توپ را انتخاب کنیم.

We can't use `position:fixed` for it, because scrolling the page would move the ball from the field.
نمی‌توانیم از `position:fixed` به این منظور استفاده کنیم. چون اسکرول کردن صفحه باید توپ را در زمین جابجا کند.

So we should use `position:absolute` and, to make the positioning really solid, make `field` itself positioned.
پس باید از `position:absolute` استفاده کنیم و برای اینکه از موقعیت توپ مطمئن شویم، روش قرارگیری `field` را نیز تنظیم می‌کنیم.

Then the ball will be positioned relatively to the field:
در این صورت، توپ نسبت به زمین قرار گرفته می‌شود:

```css
#field {
Expand All @@ -16,36 +16,36 @@ Then the ball will be positioned relatively to the field:

#ball {
position: absolute;
left: 0; /* relative to the closest positioned ancestor (field) */
left: 0; /* نسبت به نزدیکترین والدی که موقعیت آن تنظیم شده (field) */
top: 0;
transition: 1s all; /* CSS animation for left/top makes the ball fly */
transition: 1s all; /* انیمیشن‌های CSS برای چپ/بالا، انگار توپ پرتاب شده */
}
```

Next we need to assign the correct `ball.style.left/top`. They contain field-relative coordinates now.
حال باید مقدارهای درستی به `ball.style.left/top` بدهیم. این مقدار نسبت به زمین خواهد بود.

Here's the picture:
مانند این تصویر:

![](move-ball-coords.svg)

We have `event.clientX/clientY` -- window-relative coordinates of the click.
ما `event.clientX/clientY` را داریم، مختصات اشاره‌گر موس نسبت به پنجره.

To get field-relative `left` coordinate of the click, we can substract the field left edge and the border width:
برای اینکه مقدار `left` مختصات اشاره‌گر موس در زمان کلیک را نسبت به زمین بگیریم، باید چپ زمین و عرض حاشیه را از هم کم کنیم.

```js
let left = event.clientX - fieldCoords.left - field.clientLeft;
```

Normally, `ball.style.left` means the "left edge of the element" (the ball). So if we assign that `left`, then the ball edge, not center, would be under the mouse cursor.
معمولا، `ball.style.left` به معنی "حاشیه چپ عنصر" (توپ) است. پس اگر که به `left` مقدار دهیم، پس گوشیه توپ، و نه وسط آن زیر موس قرار می‌گیرد.

We need to move the ball half-width left and half-height up to make it center.
باید که توپ را به اندازه نصف طولش به چپ، و به اندازه نصف ارتفاع آن به بالا ببریم تا وسط قرار گیرد.

So the final `left` would be:
پس مقدار نهایی `left` به صورت زیر است:

```js
let left = event.clientX - fieldCoords.left - field.clientLeft - ball.offsetWidth/2;
```

The vertical coordinate is calculated using the same logic.
مختصات عمودی نیز با همین منطق محاسبه می‌شود.

Please note that the ball width/height must be known at the time we access `ball.offsetWidth`. Should be specified in HTML or CSS.
لطفا توجه کنید که طول/ارتفاع توب باید در زمانی که به `ball.offsetWidth` معلوم باشد. پس باید در HTML یا CSS آنها را مقدار دهی کنیم.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<body style="height:2000px">

Click on a field to move the ball there.
روی زمین کلیک کنید تا توپ حرکت کند.
<br>


Expand All @@ -39,29 +39,29 @@
<script>
field.onclick = function(event) {

// window-relative field coordinates
// مختصات زمین نسبت به پنجره
let fieldCoords = this.getBoundingClientRect();

// the ball has position:absolute, the field: position:relative
// so ball coordinates are relative to the field inner left-upper corner
// توپ موقعیت position:absolute و زمین موقعیت position:relative دارد
// پس مختصات توپ نسبت به گوشه بالا چپ درون زمین است
let ballCoords = {
top: event.clientY - fieldCoords.top - field.clientTop - ball.clientHeight / 2,
left: event.clientX - fieldCoords.left - field.clientLeft - ball.clientWidth / 2
};

// prevent crossing the top field boundary
// جلوگیری از عبور از مرز بالای زمین
if (ballCoords.top < 0) ballCoords.top = 0;

// prevent crossing the left field boundary
// جلوگیری از عبور از مرز چپ زمین
if (ballCoords.left < 0) ballCoords.left = 0;


// // prevent crossing the right field boundary
// جلوگیری از عبور از مرز راست زمین
if (ballCoords.left + ball.clientWidth > field.clientWidth) {
ballCoords.left = field.clientWidth - ball.clientWidth;
}

// prevent crossing the bottom field boundary
// جلوگیری از عبور از مرز پایین زمین
if (ballCoords.top + ball.clientHeight > field.clientHeight) {
ballCoords.top = field.clientHeight - ball.clientHeight;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

<body style="height:2000px">

Click on a field to move the ball there.
<br> The ball should never leave the field.
روی زمین کلیک کنید تا توپ حرکت کند.
<br> توپ نباید هیچ‌وقت زمین را ترک کند.


<div id="field">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ importance: 5

---

# Move the ball across the field
# توپ را طول زمین حرکت دهید

Move the ball across the field to a click. Like this:
باید یک کلیک توپ را در طول زمین حرکت کنید. مانند:

[iframe src="solution" height="260" link]

Requirements:
نیازها:

- The ball center should come exactly under the pointer on click (if possible without crossing the field edge).
- CSS-animation is welcome.
- The ball must not cross field boundaries.
- When the page is scrolled, nothing should break.
- در زمان کلیک، وسط توپ باید دقیقا زیر وس قرار بگیرید (در صورت امکان بدون خروج از حاشیه‌های زمین).
- استفاده از انیمیشن‌های CSS توصیه می‌شود.
- توپ نباید از حدود زمین عبور کند.
- در صورت پیمایش صفحه، نباید چیزی خراب شود.

Notes:
نکات:

- The code should also work with different ball and field sizes, not be bound to any fixed values.
- Use properties `event.clientX/event.clientY` for click coordinates.
- کد شما باید با توپ‌ها و اندازه‌های مختلف زمین کارکند، و مقید به مقادیر ثابتی نباشد.
- از خصوصیات `event.clientX/event.clientY` برای گرفتن مختصات اشاره‌گر موس استفاده کنید.
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@

# HTML/CSS
First let's create HTML/CSS.
اول باید که HTML/CSS را بسازیم.

A menu is a standalone graphical component on the page, so it's better to put it into a single DOM element.
منو یک جزء گرافیکی مستقل روی صفحه است. پس بهتر است که همه آنرا را درون یک عنصر DOM قرار دهیم.

A list of menu items can be laid out as a list `ul/li`.
یک لیست از آیتم‌های منو می‌تواند مانند لیستی از `ul/li` باشد.

Here's the example structure:
در اینجا یک ساختار نمونه آمده:

```html
<div class="menu">
<span class="title">Sweeties (click me)!</span>
<span class="title">شیرینی‌ها (کلیک کنید)!</span>
<ul>
<li>Cake</li>
<li>Donut</li>
<li>Honey</li>
<li>کیک</li>
<li>دونات</li>
<li>عسل</li>
</ul>
</div>
```

We use `<span>` for the title, because `<div>` has an implicit `display:block` on it, and it will occupy 100% of the horizontal width.
برای عنوان از `<spcan>` استفاده می‌کنیم، زیرا `<div>` از قبل یک ویژگی خاص `display: block` دارد و 100% عرض افقی را پر می‌کند.

Like this:
مانند این:

```html autorun height=50
<div style="border: solid red 1px" onclick="alert(1)">Sweeties (click me)!</div>
<div style="border: solid red 1px" onclick="alert(1)">شیرینی‌ها (کلیک کنید)!</div>
```

So if we set `onclick` on it, then it will catch clicks to the right of the text.
پس اگر `onclick` را روی آن تعریف کنیم، کلیک‌ها را در سمت راست متن نیز دریافت می‌کند.

As `<span>` has an implicit `display: inline`, it occupies exactly enough place to fit all the text:
در صورتی که `<span>` از قبل یک ویژگی خاص `display: inline‍` دارد، تنها فضای مورد نیاز متن را اشغال می‌کند:

```html autorun height=50
<span style="border: solid red 1px" onclick="alert(1)">Sweeties (click me)!</span>
<span style="border: solid red 1px" onclick="alert(1)">شیرینی‌ها (کلیک کنید)!</span>
```

# Toggling the menu
# باز و بسته کردن منو

Toggling the menu should change the arrow and show/hide the menu list.
باز و بسته کردن منو باید کمان‌ها را تغییر دهد و آیتم‌های درون لیست منو را نشان دهد یا مخفی کند.

All these changes are perfectly handled by CSS. In JavaScript we should label the current state of the menu by adding/removing the class `.open`.
همه‌ی این تغییرات کاملا توسط CSS کنترل می‌شود. در جاوااسکریپت باید وضعیت باز و بسته رودن را با اضافه کردن یا حذف کردن کلاس `.open` مشخص کنیم.

Without it, the menu will be closed:
بدون این کلاس، منو بسته است:

```css
.menu ul {
Expand All @@ -58,7 +58,7 @@ Without it, the menu will be closed:
}
```

...And with `.open` the arrow changes and the list shows up:
... و با `.open` کمان‌ها تغییر می‌کنند و لیست نمایش داده می‌شود:

```css
.menu.open .title::before {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
<body>

<div id="sweeties" class="menu">
<span class="title">Sweeties (click me)!</span>
<span class="title">شیرینی‌ها (کلیک کنید)!</span>
<ul>
<li>Cake</li>
<li>Donut</li>
<li>Honey</li>
<li>کیک</li>
<li>دونات</li>
<li>عسل</li>
</ul>

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
</head>
<body>

▶ ▼ Sweeties (click me)!
▶ ▼ شیرینی‌ها (کلیک کنید)!
<ul>
<li>Cake</li>
<li>Donut</li>
<li>Honey</li>
<li>کلیک</li>
<li>دونات</li>
<li>عسل</li>
</ul>

</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ importance: 5

---

# Create a sliding menu
# ساخت یک منوی کشویی

Create a menu that opens/collapses on click:
یک منویی بسازید که در زمان کلیک باز/بسته شود:

[iframe border=1 height=100 src="solution"]

P.S. HTML/CSS of the source document is to be modified.
پی‌نوشت: سورس کد HTML/CSS سند باید تغییر کند.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

To add the button we can use either `position:absolute` (and make the pane `position:relative`) or `float:right`. The `float:right` has the benefit that the button never overlaps the text, but `position:absolute` gives more freedom. So the choice is yours.
برای اضافه کردن دکمه می‌توانیم از `position:absoulute` (و روی pane از `position:relative` استفاده کنیم) یا اینکه از `float:right` استفاده کنیم. استفاده از `float:right` این مزیت را دارد که دکمه هیچ‌وقت روی متن قرار نمیگیرد. اما `position:absolute` ازادی عمل بیشتری در اختیار ما می‌گذار. انتخاب بر عهده شماست.

Then for each pane the code can be like:
بعد برای هر پیام کد چیزی شبیه این خواهد بود:
```js
pane.insertAdjacentHTML("afterbegin", '<button class="remove-button">[x]</button>');
```

Then the `<button>` becomes `pane.firstChild`, so we can add a handler to it like this:
سپس `<button>` همان `pane.firstChild` می‌شود. پس می‌توانیم یک کنترل‌کننده به آن اختصاص دهیم. مانند زیر:

```js
pane.firstChild.onclick = () => pane.remove();
Expand Down
Loading