Skip to content

Commit 35081a7

Browse files
committed
renovations
1 parent a62682e commit 35081a7

File tree

115 files changed

+439
-325
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+439
-325
lines changed
-4.89 KB
Binary file not shown.
-5.73 KB
Binary file not shown.
Binary file not shown.
-3.68 KB
Binary file not shown.
Binary file not shown.
-5.73 KB
Binary file not shown.
Binary file not shown.
-8.59 KB
Binary file not shown.
Binary file not shown.
-7.86 KB
Binary file not shown.
Binary file not shown.
-13.4 KB
Binary file not shown.
Binary file not shown.

2-ui/5-widgets/6-widget-tasks/6-slider-events/solution.md 2-ui/5-widgets/5-custom-events/4-slider-events/solution.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11

2+
Для решения этой задачи достаточно создать две функции: `valueToPosition` будет получать по значению положение бегунка, а `positionToValue` -- наоборот, транслировать текущую координату бегунка в значение.
3+
24
Как сопоставить позицию слайдера и значение?
35

46
Для этого посмотрим крайние значения слайдера. Допустим, размер бегунка `10px`.
@@ -17,10 +19,16 @@ pixelsPerValue = (sliderElem.clientWidth-thumbElem.clientWidth) / max;
1719

1820
Используя `pixelsPerValue` мы сможем переводить позицию бегунка в значение и обратно.
1921

20-
Крайнее левое значение `thumbElem.style.left` равно нулю, крайнее правой -- как раз ширине доступной области `sliderElem.clientWidth - thumbElem.clientWidth`. Поэтому можно получив значение, поделив его на `pixelsPerValue`:
22+
Крайнее левое значение `thumbElem.style.left` равно нулю, крайнее правой -- как раз ширине доступной области `sliderElem.clientWidth - thumbElem.clientWidth`. Поэтому можно получить значение слайдера, поделив его на `pixelsPerValue`:
2123

2224
```js
23-
value = Math.round( newLeft / pixelsPerValue);
25+
function positionToValue(left) {
26+
return Math.round( left / pixelsPerValue);
27+
}
28+
29+
function valueToPosition(value) {
30+
return pixelsPerValue * value;
31+
}
2432
```
2533

2634

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<script src="https://cdn.polyfill.io/v1/polyfill.js?features=CustomEvents,Element.prototype.closest"></script>
7+
<link rel="stylesheet" href="slider.css">
8+
<script src="slider.js"></script>
9+
</head>
10+
11+
<body>
12+
<div id="slider" class="slider">
13+
<div class="thumb"></div>
14+
</div>
15+
16+
17+
Slide:<span id="slide">&nbsp;</span>
18+
Change:<span id="change">&nbsp;</span>
19+
20+
<button onclick="slider.setValue(50)">slider.setValue(50)</button>
21+
22+
<script>
23+
24+
var sliderElem = document.getElementById('slider');
25+
26+
var slider = new Slider({
27+
elem: sliderElem,
28+
max: 100
29+
});
30+
31+
sliderElem.addEventListener('slide', function(event) {
32+
document.getElementById('slide').innerHTML = event.detail;
33+
});
34+
35+
sliderElem.addEventListener('change', function(event) {
36+
document.getElementById('change').innerHTML = event.detail;
37+
});
38+
39+
</script>
40+
41+
42+
</body>
43+
44+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.slider {
2+
margin: 5px;
3+
width: 310px;
4+
height: 15px;
5+
border-radius: 5px;
6+
background: #E0E0E0;
7+
background: -moz-linear-gradient(left top, #E0E0E0, #EEEEEE) repeat scroll 0 0 transparent;
8+
background: -webkit-gradient(linear, left top, right bottom, from(#E0E0E0), to(#EEEEEE));
9+
background: linear-gradient(left top, #E0E0E0, #EEEEEE);
10+
}
11+
.thumb {
12+
position: relative;
13+
top: -5px;
14+
width: 10px;
15+
height: 25px;
16+
border-radius: 3px;
17+
background: blue;
18+
cursor: pointer;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
function Slider(options) {
2+
var elem = options.elem;
3+
4+
var thumbElem = elem.querySelector('.thumb');
5+
6+
var max = options.max || 100;
7+
var sliderCoords, thumbCoords, shiftX, shiftY;
8+
9+
// [<*>----------------]
10+
// |...............|
11+
// first last
12+
var pixelsPerValue = (elem.clientWidth - thumbElem.clientWidth) / max;
13+
14+
elem.ondragstart = function() {
15+
return false;
16+
};
17+
18+
elem.onmousedown = function(event) {
19+
if (event.target.closest('.thumb')) {
20+
startDrag(event.clientX, event.clientY);
21+
return false; // disable selection start (cursor change)
22+
}
23+
}
24+
25+
function startDrag(startClientX, startClientY) {
26+
thumbCoords = thumbElem.getBoundingClientRect();
27+
shiftX = startClientX - thumbCoords.left;
28+
shiftY = startClientY - thumbCoords.top;
29+
30+
sliderCoords = elem.getBoundingClientRect();
31+
32+
document.addEventListener('mousemove', onDocumentMouseMove);
33+
document.addEventListener('mouseup', onDocumentMouseUp);
34+
}
35+
36+
function moveTo(clientX) {
37+
// вычесть координату родителя, т.к. position: relative
38+
var newLeft = clientX - shiftX - sliderCoords.left;
39+
40+
// курсор ушёл вне слайдера
41+
if(newLeft < 0) {
42+
newLeft = 0;
43+
}
44+
var rightEdge = elem.offsetWidth - thumbElem.offsetWidth;
45+
if(newLeft > rightEdge) {
46+
newLeft = rightEdge;
47+
}
48+
49+
thumbElem.style.left = newLeft + 'px';
50+
51+
elem.dispatchEvent(new CustomEvent('slide', {
52+
bubbles: true,
53+
detail: positionToValue(newLeft)
54+
}));
55+
}
56+
57+
function valueToPosition(value) {
58+
return pixelsPerValue * value;
59+
}
60+
61+
function positionToValue(left) {
62+
return Math.round( left / pixelsPerValue);
63+
}
64+
65+
function onDocumentMouseMove(e) {
66+
moveTo(e.clientX);
67+
}
68+
69+
function onDocumentMouseUp() {
70+
endDrag();
71+
}
72+
73+
function endDrag() {
74+
document.removeEventListener('mousemove', onDocumentMouseMove);
75+
document.removeEventListener('mouseup', onDocumentMouseUp);
76+
77+
elem.dispatchEvent(new CustomEvent('change', {
78+
bubbles: true,
79+
detail: positionToValue(parseInt(thumbElem.style.left))
80+
}));
81+
}
82+
83+
function setValue(value) {
84+
thumbElem.style.left = valueToPosition(value) + 'px';
85+
}
86+
87+
this.setValue = setValue;
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Слайдер с событиями
2+
3+
[importance 5]
4+
5+
На основе слайдера из задачи [](/task/slider-widget) создайте графический компонент, который умеет возвращать/получать значение.
6+
7+
Синтаксис:
8+
9+
```js
10+
var slider = new Slider({
11+
elem: document.getElementById('slider'),
12+
max: 100 // слайдер на самой правой позиции соответствует 100
13+
});
14+
```
15+
16+
Метод `setValue` устанавливает значение:
17+
18+
```js
19+
slider.setValue(50);
20+
```
21+
22+
У слайдера должно быть два события: `slide` при каждом передвижении и `change` при отпускании мыши (установке значения).
23+
24+
Пример использования:
25+
26+
```js
27+
var sliderElem = document.getElementById('slider');
28+
29+
sliderElem.addEventListener('slide', function(event) {
30+
document.getElementById('slide').innerHTML = event.detail;
31+
});
32+
33+
sliderElem.addEventListener('change', function(event) {
34+
document.getElementById('change').innerHTML = event.detail;
35+
});
36+
```
37+
38+
В действии:
39+
[iframe src="solution" height="80"]
40+
41+
<ul>
42+
<li>Ширина/высота слайдера может быть любой, JS-код это должен учитывать.</li>
43+
<li>Центр бегунка должен располагаться в точности над выбранным значением. Например, он должен быть в центре для 50 при `max=100`.</li>
44+
</ul>
45+
46+
Исходный документ -- возьмите решение задачи [](/task/slider-widget).

2-ui/5-widgets/6-what-next/article.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Что изучать дальше
2+
3+
Если вы прочитали весь учебник и сделали задачи, то на текущий момент вы обладаете важнейшими фундаментальными знаниями и навыками JavaScript.
4+
5+
[cut]
6+
7+
В этом разделе мы изучали основы создания компонентов на JavaScript. Если проект большой и сложный, то понадобятся дополнительные инструменты для связывания компонент между собой, для привязки к ним данных и так далее.
8+
9+
Сейчас существует много фреймворков. Всё активно развивается, меняется, кипит и булькает, может быть из этого получится "общепринятая" архитектура, а может и нет. Сейчас явного победителя нет, выбор фреймворка зависит от проекта и личных предпочтений разработчиков.
10+
11+
Примеры удачных фреймворков, которые можно изучить:
12+
13+
<ul>
14+
<li>[Angular.JS](http://angularjs.org)</li>
15+
<li>[React.JS](http://facebook.github.io/react/) + [Flux](http://facebook.github.io/flux/)</li>
16+
<li>[Backbone.JS](http://backbonejs.org/) + [Marionette](http://marionettejs.com/)</li>
17+
</ul>
18+
19+
Также для работы с браузерами понадобятся различные [API](https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9), в частности:
20+
21+
<ul>
22+
<li>Работу с окнами и фреймами.</li>
23+
<li>Регулярные выражения, класс `RegExp`.</li>
24+
<li>Объекты `XMLHttpRequest` и `WebSocket` для работы с сервером.</li>
25+
<li>Другие возможности современных браузеров.</li>
26+
</ul>
27+
28+
В дополнительных разделах учебника мы обязательно разберём что-то из этого.
29+
30+
...И, конечно, понадобится система сборки проектов, например [WebPack](http://webpack.github.io/).
31+
32+
Успехов вам!

0 commit comments

Comments
 (0)