mirror of https://github.com/freeCodeCamp/devdocs
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.1 KiB
111 lines
2.1 KiB
app.views.SidebarHover = class SidebarHover extends app.View {
|
|
static itemClass = "_list-hover";
|
|
|
|
static events = {
|
|
focus: "onFocus",
|
|
blur: "onBlur",
|
|
mouseover: "onMouseover",
|
|
mouseout: "onMouseout",
|
|
scroll: "onScroll",
|
|
click: "onClick",
|
|
};
|
|
|
|
static routes = { after: "onRoute" };
|
|
|
|
show(el) {
|
|
if (el !== this.cursor) {
|
|
this.hide();
|
|
if (this.isTarget(el) && this.isTruncated(el.lastElementChild || el)) {
|
|
this.cursor = el;
|
|
this.clone = this.makeClone(this.cursor);
|
|
$.append(document.body, this.clone);
|
|
if (this.offsetTop == null) {
|
|
this.offsetTop = this.el.offsetTop;
|
|
}
|
|
this.position();
|
|
}
|
|
}
|
|
}
|
|
|
|
hide() {
|
|
if (this.cursor) {
|
|
$.remove(this.clone);
|
|
this.cursor = this.clone = null;
|
|
}
|
|
}
|
|
|
|
position() {
|
|
if (this.cursor) {
|
|
const rect = $.rect(this.cursor);
|
|
if (rect.top >= this.offsetTop) {
|
|
this.clone.style.top = rect.top + "px";
|
|
this.clone.style.left = rect.left + "px";
|
|
} else {
|
|
this.hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
makeClone(el) {
|
|
const clone = el.cloneNode(true);
|
|
clone.classList.add("clone");
|
|
return clone;
|
|
}
|
|
|
|
isTarget(el) {
|
|
return el.classList?.contains(this.constructor.itemClass);
|
|
}
|
|
|
|
isSelected(el) {
|
|
return el.classList.contains("active");
|
|
}
|
|
|
|
isTruncated(el) {
|
|
return el.scrollWidth > el.offsetWidth;
|
|
}
|
|
|
|
onFocus(event) {
|
|
this.focusTime = Date.now();
|
|
this.show(event.target);
|
|
}
|
|
|
|
onBlur() {
|
|
this.hide();
|
|
}
|
|
|
|
onMouseover(event) {
|
|
if (
|
|
this.isTarget(event.target) &&
|
|
!this.isSelected(event.target) &&
|
|
this.mouseActivated()
|
|
) {
|
|
this.show(event.target);
|
|
}
|
|
}
|
|
|
|
onMouseout(event) {
|
|
if (this.isTarget(event.target) && this.mouseActivated()) {
|
|
this.hide();
|
|
}
|
|
}
|
|
|
|
mouseActivated() {
|
|
// Skip mouse events caused by focus events scrolling the sidebar.
|
|
return !this.focusTime || Date.now() - this.focusTime > 500;
|
|
}
|
|
|
|
onScroll() {
|
|
this.position();
|
|
}
|
|
|
|
onClick(event) {
|
|
if (event.target === this.clone) {
|
|
$.click(this.cursor);
|
|
}
|
|
}
|
|
|
|
onRoute() {
|
|
this.hide();
|
|
}
|
|
};
|