This commit is contained in:
Ilya Kantor 2020-08-23 19:03:29 +03:00
parent 718d9df37b
commit b24b05d3ca
1436 changed files with 131 additions and 106126 deletions

View file

@ -0,0 +1,52 @@
// Here's a brief sketch of the class
// with things that you'll need anyway
class HoverIntent {
constructor({
sensitivity = 0.1, // speed less than 0.1px/ms means "hovering over an element"
interval = 100, // measure mouse speed once per 100ms: calculate the distance between previous and next points
elem,
over,
out
}) {
this.sensitivity = sensitivity;
this.interval = interval;
this.elem = elem;
this.over = over;
this.out = out;
// make sure "this" is the object in event handlers.
this.onMouseMove = this.onMouseMove.bind(this);
this.onMouseOver = this.onMouseOver.bind(this);
this.onMouseOut = this.onMouseOut.bind(this);
// assign the handlers
elem.addEventListener("mouseover", this.onMouseOver);
elem.addEventListener("mouseout", this.onMouseOut);
// continue from this point
}
onMouseOver(event) {
console.error(console.log);
console.log("OVER", event);
/* ... */
}
onMouseOut(event) {
/* ... */
}
onMouseMove(event) {
/* ... */
}
destroy() {
/* your code to "disable" the functionality, remove all handlers */
/* it's needed for the tests to work */
}
}

View file

@ -0,0 +1,24 @@
<link rel="stylesheet" href="style.css">
<script src="hoverIntent.js"></script>
<div id="elem" class="clock">
<span class="hours">12</span> :
<span class="minutes">30</span> :
<span class="seconds">00</span>
</div>
<div id="tooltip" hidden>Tooltip</div>
<script>
new HoverIntent({
elem,
over() {
tooltip.style.left = elem.getBoundingClientRect().left + 5 + 'px';
tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
tooltip.hidden = false;
},
out() {
tooltip.hidden = true;
}
});
</script>

View file

@ -0,0 +1,38 @@
.hours {
color: red;
}
body {
margin: 0;
}
.minutes {
color: green;
}
.seconds {
color: blue;
}
.clock {
border: 1px dashed black;
padding: 5px;
display: inline-block;
background: yellow;
position: absolute;
left: 0;
top: 0;
}
#tooltip {
position: absolute;
padding: 10px 20px;
border: 1px solid #b3c9ce;
border-radius: 4px;
text-align: center;
font: italic 14px/1.3 sans-serif;
color: #333;
background: #fff;
z-index: 100000;
box-shadow: 3px 3px 3px rgba(0, 0, 0, .3);
}

View file

@ -0,0 +1,96 @@
describe("hoverIntent", function() {
function mouse(eventType, x, y, options) {
let eventOptions = Object.assign({
bubbles: true,
clientX: x,
clientY: y,
pageX: x,
pageY: y,
target: elem
}, options || {});
elem.dispatchEvent(new MouseEvent(eventType, eventOptions));
}
let isOver;
let hoverIntent;
before(function() {
this.clock = sinon.useFakeTimers();
});
after(function() {
this.clock.restore();
});
beforeEach(function() {
isOver = false;
hoverIntent = new HoverIntent({
elem: elem,
over: function() {
isOver = true;
},
out: function() {
isOver = false;
}
});
})
afterEach(function() {
if (hoverIntent) {
hoverIntent.destroy();
}
})
it("mouseover -> when the pointer just arrived, no tooltip", function() {
mouse('mouseover', 10, 10);
assert.isFalse(isOver);
});
it("mouseover -> after a delay, the tooltip shows up", function() {
mouse('mouseover', 10, 10);
this.clock.tick(100);
assert.isTrue(isOver);
});
it("mouseover -> followed by fast mouseout leads doesn't show tooltip", function() {
mouse('mouseover', 10, 10);
setTimeout(
() => mouse('mouseout', 300, 300, { relatedTarget: document.body}),
30
);
this.clock.tick(100);
assert.isFalse(isOver);
});
it("mouseover -> slow move -> tooltips", function() {
mouse('mouseover', 10, 10);
for(let i=10; i<200; i+= 10) {
setTimeout(
() => mouse('mousemove', i/5, 10),
i
);
}
this.clock.tick(200);
assert.isTrue(isOver);
});
it("mouseover -> fast move -> no tooltip", function() {
mouse('mouseover', 10, 10);
for(let i=10; i<200; i+= 10) {
setTimeout(
() => mouse('mousemove', i, 10),
i
);
}
this.clock.tick(200);
assert.isFalse(isOver);
});
});