Skip to content

Commit 1e4e3a8

Browse files
committed
fixes
1 parent ad41cb8 commit 1e4e3a8

8 files changed

Lines changed: 161 additions & 45 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
function removeClass(obj, cls) {
22
var classes = obj.className.split(' ');
33

4-
for (i = 0; i < classes.length; i++) {
4+
for (var i = 0; i < classes.length; i++) {
55
if (classes[i] == cls) {
66
classes.splice(i, 1); // удалить класс
77
i--;
88
}
99
}
1010
obj.className = classes.join(' ');
11-
}
11+
}

1-js/4-data-structures/8-array-methods/3-remove-class/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
function removeClass(obj, cls) {
66
var classes = obj.className.split(' ');
77

8-
for (i = 0; i < classes.length; i++) {
8+
for (var i = 0; i < classes.length; i++) {
99
if (classes[i] == cls) {
1010
classes.splice(i, 1); // удалить класс
1111
*!*

2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/solution.view/hoverIntent.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict';
2+
13
function HoverIntent(options) {
24

35
options = Object.create(options); // not to modify the object
@@ -16,7 +18,11 @@ function HoverIntent(options) {
1618
var isHover;
1719

1820
// A private function for handling mouse 'hovering'
19-
elem.addEventListener("mouseover", function(event) {
21+
elem.addEventListener("mouseover", onMouseOver);
22+
23+
elem.addEventListener("mouseout", onMouseOut);
24+
25+
function onMouseOver(event) {
2026

2127
if (isOverElement) {
2228
// если мы и так над элементом, то это всплывший переход внутри него
@@ -27,41 +33,52 @@ function HoverIntent(options) {
2733
isOverElement = true;
2834

2935
// при каждом движении мыши mousemove мы будем вычислять расстояние между
30-
// предыдущими и текущими координатами курсора
36+
// предыдущими и текущими координатами курсора
3137
// если оно меньше sensivity, то скорость маленькая и это наведение на элемент
3238
// pX, pY - "предыдущие" координаты
3339
pX = event.pageX;
3440
pY = event.pageY;
3541
pTime = Date.now();
3642

3743
elem.addEventListener('mousemove', onMouseMove);
38-
});
39-
40-
elem.addEventListener("mouseout", function(event) {
44+
checkSpeedInterval = setInterval(trackSpeed, options.interval);
45+
}
46+
47+
function onMouseOut(event) {
4148
// если ушли вовне элемента
42-
if (event.relatedTarget && !elem.contains(event.relatedTarget)) {
49+
if (!event.relatedTarget || !elem.contains(event.relatedTarget)) {
4350
isOverElement = false;
4451
elem.removeEventListener('mousemove', onMouseMove);
52+
clearInterval(checkSpeedInterval);
4553
if (isHover) {
4654
// если была остановка над элементом
4755
options.out.call(elem, event);
4856
isHover = false;
4957
}
5058
}
51-
});
59+
}
5260

5361
function onMouseMove(event) {
5462
cX = event.pageX;
5563
cY = event.pageY;
5664
cTime = Date.now();
65+
}
66+
67+
function trackSpeed() {
5768

58-
if (pTime == cTime) return; // когда mousemove вместе с mouseover
59-
60-
var speed = Math.sqrt(Math.pow(pX - cX, 2) + Math.pow(pY - cY, 2)) / (cTime - pTime);
69+
let speed;
70+
71+
if (!cTime || cTime == pTime) {
72+
// нет измерений скорости (событий mousemove)
73+
// значит курсор не двигался
74+
speed = 0;
75+
} else {
76+
speed = Math.sqrt(Math.pow(pX - cX, 2) + Math.pow(pY - cY, 2)) / (cTime - pTime);
77+
}
6178

6279
if (speed < options.sensitivity) {
6380
// если с предыдущей позиции меньше sensivity дистанция, то "остановка на элементе"
64-
elem.removeEventListener("mousemove", onMouseMove);
81+
clearInterval(checkSpeedInterval);
6582
isHover = true;
6683
options.over.call(elem, event);
6784
} else {
@@ -71,5 +88,11 @@ function HoverIntent(options) {
7188
pTime = cTime;
7289
}
7390
}
91+
92+
this.destroy = function() {
93+
elem.removeEventListener('mousemove', onMouseMove);
94+
elem.removeEventListener('mouseover', onMouseOver);
95+
elem.removeEventListener('mouseout', onMouseOut);
96+
};
7497

75-
}
98+
}
Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,39 @@
11
<!doctype html>
2-
<html lang="en">
2+
<html>
33

44
<head>
55
<meta charset="UTF-8">
6-
<title>Document</title>
76
<link rel="stylesheet" href="style.css">
87
<script src="hoverIntent.js"></script>
8+
<script src="https://js.cx/test/libs.js"></script>
9+
<script src="test.js"></script>
910
</head>
1011

1112
<body>
1213

13-
1414
<div id="elem" class="clock">
1515
<span class="hours">12</span> :
1616
<span class="minutes">30</span> :
1717
<span class="seconds">00</span>
1818
</div>
1919

20-
<script>
21-
var tooltip = document.createElement('div');
22-
tooltip.className = "tooltip";
23-
tooltip.innerHTML = "Подсказка";
24-
25-
new HoverIntent({
26-
elem: elem,
27-
over: function() {
28-
tooltip.style.left = this.getBoundingClientRect().left + 'px';
29-
tooltip.style.top = this.getBoundingClientRect().bottom + 5 + 'px';
30-
document.body.appendChild(tooltip);
31-
},
32-
out: function() {
33-
document.body.removeChild(tooltip);
34-
}
35-
});
36-
</script>
37-
38-
20+
<div id="tooltip" hidden>Tooltip</div>
3921

22+
<script>
23+
// for the demo
24+
setTimeout(function() {
25+
new HoverIntent({
26+
elem: elem,
27+
over: function() {
28+
tooltip.hidden = false;
29+
},
30+
out: function() {
31+
tooltip.hidden = true;
32+
}
33+
});
34+
}, 2000);
35+
</script>
4036

4137
</body>
4238

43-
</html>
39+
</html>

2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/solution.view/style.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
border: 1px dashed black;
1515
padding: 5px;
1616
display: inline-block;
17-
margin: 30px;
1817
background: yellow;
18+
position: absolute;
19+
left: 0;
20+
top: 0;
1921
}
2022

2123
.tooltip {
2224
position: absolute;
2325
background: #eee;
2426
border: 1px brown solid;
2527
padding: 3px;
26-
}
28+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
'use strict';
2+
3+
describe("hoverIntent", function() {
4+
5+
function mouse(eventType, x, y, options) {
6+
let eventOptions = Object.assign({
7+
bubbles: true,
8+
clientX: x,
9+
clientY: y,
10+
pageX: x,
11+
pageY: y,
12+
target: elem
13+
}, options || {});
14+
15+
elem.dispatchEvent(new MouseEvent(eventType, eventOptions));
16+
}
17+
18+
19+
let isOver;
20+
let hoverIntent;
21+
22+
23+
before(function() {
24+
this.clock = sinon.useFakeTimers();
25+
});
26+
27+
after(function() {
28+
this.clock.restore();
29+
});
30+
31+
32+
beforeEach(function() {
33+
isOver = false;
34+
35+
hoverIntent = new HoverIntent({
36+
elem: elem,
37+
over: function() {
38+
isOver = true;
39+
},
40+
out: function() {
41+
isOver = false;
42+
}
43+
});
44+
})
45+
46+
afterEach(function() {
47+
if (hoverIntent) {
48+
hoverIntent.destroy();
49+
}
50+
})
51+
52+
it("mouseover -> immediately no tooltip", function() {
53+
mouse('mouseover', 10, 10);
54+
assert.isFalse(isOver);
55+
});
56+
57+
it("mouseover -> pause shows tooltip", function() {
58+
mouse('mouseover', 10, 10);
59+
this.clock.tick(100);
60+
assert.isTrue(isOver);
61+
});
62+
63+
it("mouseover -> fast mouseout no tooltip", function() {
64+
mouse('mouseover', 10, 10);
65+
setTimeout(
66+
() => mouse('mouseout', 300, 300, { relatedTarget: document.body}),
67+
30
68+
);
69+
this.clock.tick(100);
70+
assert.isFalse(isOver);
71+
});
72+
73+
74+
it("mouseover -> slow move -> tooltips", function() {
75+
mouse('mouseover', 10, 10);
76+
for(let i=10; i<200; i+= 10) {
77+
setTimeout(
78+
() => mouse('mousemove', i/5, 10),
79+
i
80+
);
81+
}
82+
this.clock.tick(200);
83+
assert.isTrue(isOver);
84+
});
85+
86+
it("mouseover -> fast move -> no tooltip", function() {
87+
mouse('mouseover', 10, 10);
88+
for(let i=10; i<200; i+= 10) {
89+
setTimeout(
90+
() => mouse('mousemove', i, 10),
91+
i
92+
);
93+
}
94+
this.clock.tick(200);
95+
assert.isFalse(isOver);
96+
});
97+
98+
});

2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/source.view/index.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717
<span class="seconds">00</span>
1818
</div>
1919

20+
<div id="tooltip" hidden>Tooltip</div>
2021
<script>
21-
var tooltip = document.createElement('div');
22-
tooltip.className = "tooltip";
23-
tooltip.innerHTML = "Подсказка";
24-
2522
new HoverIntent({
2623
elem: elem,
2724
over: function() {

4-ajax/5-xhr-crossdomain/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ xhr.send();
8282

8383
Аналогично, злой хакер и ранее мог на своей странице объявить и, при помощи JavaScript, отправить HTML-форму с методом GET/POST и кодировкой `multipart/form-data`. А значит, даже старый сервер наверняка предусматривает возможность таких атак и умеет от них защищаться.
8484

85-
А вот запросы с нестандартными заголовками или с методом `DELETE` таким образом не создать. Поэтому старый сервер может быть к ним не готов. Или, к примеру, он может полагать, что такие запросы веб-страница в принципе не умеет присылать, значит они пришли из привелигированного приложения, и дать им слишком много прав.
85+
А вот запросы с нестандартными заголовками или с методом `DELETE` таким образом не создать. Поэтому старый сервер может быть к ним не готов. Или, к примеру, он может полагать, что такие запросы веб-страница в принципе не умеет присылать, значит они пришли из привилегированного приложения, и дать им слишком много прав.
8686

8787
Поэтому при посылке "непростых" запросов нужно специальным образом спросить у сервера, согласен ли он в принципе на подобные кросс-доменные запросы или нет? И, если сервер не ответит, что согласен -- значит, нет.
8888

0 commit comments

Comments
 (0)