Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
As we can see from HTML/CSS, the slider is a `<div>` with a colored background, that contains a runner -- another `<div>` with `position:relative`.
Як можна бачити з `HTML/CSS`, слайдер - це `<div>`, з кольровим фоном, всередині якого знаходиться інший `<div>`, оформлений як бігунок, з `position: relative`.

To position the runner we use `position:relative`, to provide the coordinates relative to its parent, here it's more convenient here than `position:absolute`.
Використовуємо для його позиціювання `position: relative`, тобто координати встановлюються не абсолютні, а відносно зовнішнього родича, так як це зручніше.

Then we implement horizontal-only Drag'n'Drop with limitation by width.
І далі реалізуємо Drag'n'Drop тільки по горизонталі, з обмеженням по ширині.
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
let thumb = slider.querySelector('.thumb');

thumb.onmousedown = function(event) {
event.preventDefault(); // prevent selection start (browser action)
event.preventDefault(); // запобігти запуск виділення (дія браузера)

let shiftX = event.clientX - thumb.getBoundingClientRect().left;
// shiftY not needed, the thumb moves only horizontally
// shiftY не потрібен, слайдер рухається тільки по горизонталі

document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);

function onMouseMove(event) {
let newLeft = event.clientX - shiftX - slider.getBoundingClientRect().left;

// the pointer is out of slider => lock the thumb within the bounaries
// курсор вийшов зі слайдера => залишити бігунок в його межах.
if (newLeft < 0) {
newLeft = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</div>

<script>
// ...your code...
// ...ваш код...
</script>

</body>
Expand Down
10 changes: 5 additions & 5 deletions 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ importance: 5

# Slider

Create a slider:
Створіть слайдер:

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

Drag the blue thumb with the mouse and move it.
Натисніть мишею на синій бігунок і рухайте його.

Important details:
Важливі деталі:

- When the mouse button is pressed, during the dragging the mouse may go over or below the slider. The slider will still work (convenient for the user).
- If the mouse moves very fast to the left or to the right, the thumb should stop exactly at the edge.
- При натиснутому бігунці курсор миші може виходити за межі смуги слайдера, але слайдер нехай все одно працює (це зручно для користувача).
- Слайдер повинен нормально працювати при різкому русі миші вліво або вправо за межі смуги. При цьому бігунок повинен зупинятися чітко в потрібному кінці смуги.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
To drag the element we can use `position:fixed`, it makes coordinates easier to manage. At the end we should switch it back to `position:absolute` to lay the element into the document.
Щоб перетягнути елемент, ми можемо використовувати `position: fixed`, це робить управління координатами простіше. В кінці слід переключитися назад на `position: absolute`, щоб покласти елемент в документ.

When coordinates are at window top/bottom, we use `window.scrollTo` to scroll it.
Коли координати знаходяться у верхній/нижній частині вікна, ми використовуємо `window.scrollTo` для прокрутки.

More details in the code, in comments.
Деталі рішення розписані в коментарях в вихідному коді.
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@

<body>

<h2>Place superheroes around the soccer field.</h2>

<p>Superheroes and the ball are elements with the class "draggable". Make them really draggable.</p>

<p>Important: limit dragging by the window. If a draggable reaches window top or bottom, then the page should scroll to let us drag it further.</p>

<p>If your screen is big enough to fit the whole document -- make the window smaller to get vertical scrolling, so that you could test it.</p>

<p>In this task it's enough to handle vertical scrolling. There's no horizontal scrolling usually, and it's handled the similar way if needed.</p>

<p>And one more thing: heroes may never leave the page. If they reach the edge of the document, no dragging outside of it.</p>

<h2>Розставте супергероїв по полю.</h2>

<p>Супергерої і м’яч - це елементи з класом "draggable". Зробіть так, щоб їх можна було переносити.</p>
<p>Важливо: обмежити перетягування межами вікна. Якщо супергероя підносять до верхньої або нижньої межі сторінки, вона повинна автоматично прокручуватися.</p>
<p>Якщо сторінка поміщається на вашому екрані цілком і не має вертикальної прокрутки - зробіть вікно браузера менше, щоб протестувати цю можливість.</p>
<p>У цьому завданні достатньо впоратися з вертикальною прокруткою. Зазвичай немає горизонтальної прокрутки, і вона обробляється аналогічним чином, якщо це необхідно.</p>
<p>Так, і ще: супергерої ні за яких умов не повинні потрапити за край екрану.</p>
<div id="field">

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ html, body {
float: left;
}

/* heroes and the ball (dragables) */
/* герої і м'яч (dragables) */

.hero {
background: url(https://js.cx/drag-heroes/heroes.png);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ document.addEventListener('mousedown', function(event) {
moveAt(event.clientX, event.clientY);
}

// on drag start:
// remember the initial shift
// move the element position:fixed and a direct child of body
// на початку переміщення елемента:
// запам'ятовуємо місце кліку по елементу (shiftX, shiftY) ,
// перемикаємо позиціонування елемента (position: fixed) і рухаємо елемент
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// перемикаємо позиціонування елемента (position: fixed) і рухаємо елемент
// перемикаємо позиціонування елемента (position: fixed) і рухаємо елемент

function startDrag(element, clientX, clientY) {
if(isDragging) {
return;
Expand All @@ -45,7 +45,8 @@ document.addEventListener('mousedown', function(event) {
moveAt(clientX, clientY);
};

// switch to absolute coordinates at the end, to fix the element in the document
// перемикаємося назад на абсолютні координати
// щоб закріпити елемент відносно документа
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут відбулося додавання рядка (48), це не можна роботи, щоб зберегти відповідність англійської версії до української. Переклад має займати той самий рядок, і не додавати інших

function finishDrag() {
if(!isDragging) {
return;
Expand All @@ -61,49 +62,50 @@ document.addEventListener('mousedown', function(event) {
}

function moveAt(clientX, clientY) {
// new window-relative coordinates
// обчислюємо нові координати (відносно вікна)
let newX = clientX - shiftX;
let newY = clientY - shiftY;

// check if the new coordinates are below the bottom window edge
let newBottom = newY + dragElement.offsetHeight; // new bottom
// перевіряємо, чи не переходять нові координати за нижній край вікна:
// спочатку обчислюємо гіпотетичний новий нижній край вікна
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Додано рядок, цього не можна робити

let newBottom = newY + dragElement.offsetHeight;

// below the window? let's scroll the page
// новий край вікна виходить за межі документа? прокручуємо сторінку
if (newBottom > document.documentElement.clientHeight) {
// window-relative coordinate of document end
// координата нижнього краю документа щодо вікна
let docBottom = document.documentElement.getBoundingClientRect().bottom;

// scroll the document down by 10px has a problem
// it can scroll beyond the end of the document
// Math.min(how much left to the end, 10)
// скролл документа на 10px вниз має проблему -
// він може прокручувати документ за його межі,
// тому використовуємо Math.min (відстань до кінця, 10)
let scrollY = Math.min(docBottom - newBottom, 10);

// calculations are imprecise, there may be rounding errors that lead to scrolling up
// that should be impossible, fix that here
// обчислення можуть бути не зовсім точні - трапляються помилки при округленні,
// які призводять до негативного значенням прокрутки. відфільтруємо їх:
if (scrollY < 0) scrollY = 0;

window.scrollBy(0, scrollY);

// a swift mouse move make put the cursor beyond the document end
// if that happens -
// limit the new Y by the maximally possible (right at the bottom of the document)
// швидке переміщення миші може помістити курсор за межі документа вниз
// якщо це сталося -
// обмежуємо нове значення Y максимально можливим виходячи з розміру документа:
newY = Math.min(newY, document.documentElement.clientHeight - dragElement.offsetHeight);
}

// check if the new coordinates are above the top window edge (similar logic)
// перевіряємо, чи не переходять нові координати за верхній край вікна (по схожому алгоритму)
if (newY < 0) {
// scroll up
let scrollY = Math.min(-newY, 10);
if (scrollY < 0) scrollY = 0; // check precision errors
if (scrollY < 0) scrollY = 0; // перевіряємо помилки точності

window.scrollBy(0, -scrollY);
// a swift mouse move can put the cursor beyond the document start
newY = Math.max(newY, 0); // newY may not be below 0
// швидке переміщення миші може помістити курсор за межі документа вгору
newY = Math.max(newY, 0); // newY не може бути менше нуля
}


// limit the new X within the window boundaries
// there's no scroll here so it's simple
// обмежимо newX розмірами вікна
// згідно з умовою, горизонтальна прокрутка відсутня, тому це не складно:
if (newX < 0) newX = 0;
if (newX > document.documentElement.clientWidth - dragElement.offsetWidth) {
newX = document.documentElement.clientWidth - dragElement.offsetWidth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@

<body>

<h2>Place superheroes around the soccer field.</h2>

<p>Superheroes and the ball are elements with the class "draggable". Make them really draggable.</p>

<p>Important: limit dragging by the window. If a draggable reaches window top or bottom, then the page should scroll to let us drag it further.</p>

<p>If your screen is big enough to fit the whole document -- make the window smaller to get vertical scrolling, so that you could test it.</p>

<p>In this task it's enough to handle vertical scrolling. There's no horizontal scrolling usually, and it's handled the similar way if needed.</p>

<p>And one more thing: heroes may never leave the page. If they reach the edge of the document, no dragging outside of it.</p>

<h2>Розставте супергероїв по полю.</h2>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Будь ласка, змініть цей файл, відповідно до моїх коменьтарів вище


<p>Супергерої і м’яч - це елементи з класом "draggable". Зробіть так, щоб їх можна було переносити.</p>
<p>Важливо: обмежити перетягування межами вікна. Якщо супергероя підносять до верхньої або нижньої межі сторінки, вона повинна автоматично прокручуватися.</p>
<p>Якщо сторінка поміщається на вашому екрані цілком і не має вертикальної прокрутки - зробіть вікно браузера менше, щоб протестувати цю можливість.</p>
<p>У цьому завданні достатньо впоратися з вертикальною прокруткою. Зазвичай немає горизонтальної прокрутки, і вона обробляється аналогічним чином, якщо це необхідно.</p>
<p>Так, і ще: супергерої ні за яких умов не повинні потрапити за край екрану.</p>
<div id="field">

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ html, body {
float: left;
}

/* heroes and the ball (dragables) */
/* герої і м'яч (dragables) */

.hero {
background: url(https://js.cx/drag-heroes/heroes.png);
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// Your code
// Ваш код
18 changes: 9 additions & 9 deletions 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ importance: 5

---

# Drag superheroes around the field
# Розставити супергероїв по полю

This task can help you to check understanding of several aspects of Drag'n'Drop and DOM.
У цьому завданні ви можете перевірити своє розуміння відразу декількох аспектів Drag'n'Drop і DOM .

Make all elements with class `draggable` -- draggable. Like a ball in the chapter.
Зробіть так, щоб елементи з класом `draggable` -- можна було переносити мишкою. Як м’яч в цьому розділі.

Requirements:
Вимоги до реалізації:

- Use event delegation to track drag start: a single event handler on `document` for `mousedown`.
- If elements are dragged to top/bottom window edges -- the page scrolls up/down to allow further dragging.
- There is no horizontal scroll (this makes the task a bit simpler, adding it is easy).
- Draggable elements or their parts should never leave the window, even after swift mouse moves.
- Використовуйте делегування подій для відстеження початку перетягування: тільки один обробник подій `mousedown` на `document`.
- Якщо елементи підносять до верхньої/нижньої межі вікна - вікно повинне прокручуватися вгору/вниз, щоб дозволити подальше перетягування.
- Горизонтальна прокрутка відсутня (трохи спрощує завдання, її просто додати).
- Елемент при перенесенні, навіть при різких рухах мишкою, не повинен навіть частково потрапити поза вікно.

The demo is too big to fit it here, so here's the link.
Демо занадто велике для розміщення тут, перейдіть за посиланням нижче.

[demo src="solution"]
Loading