mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-06 19:34:15 -05:00
Handle overlaps in scroll areas on focus events
When focus changes in scroll areas, check the current focused element isn't overlapped by sticky elements in the area. If there are overlaps, mimic what browsers do if focus moves outside the viewport and scroll to move the focused element into view.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
this._els = [el];
|
||||
this.edge = edge;
|
||||
this.node = scrollArea;
|
||||
this.setEvents();
|
||||
};
|
||||
ScrollArea.prototype.addEl = function (el) {
|
||||
this._els.push(el);
|
||||
@@ -26,6 +27,24 @@
|
||||
ScrollArea.prototype.updateEls = function (usedEls) {
|
||||
this._els = usedEls;
|
||||
};
|
||||
ScrollArea.prototype.setEvents = function () {
|
||||
this.node.addEventListener('focus', this.focusHandler.bind(this), true);
|
||||
};
|
||||
ScrollArea.prototype.removeEvents = function () {
|
||||
this.node.removeEventListener('focus', this.focusHandler.bind(this));
|
||||
};
|
||||
ScrollArea.prototype.focusHandler = function (e) {
|
||||
var $focusedElement = $(document.activeElement);
|
||||
var endOfFurthestEl = focusOverlap.endOfFurthestEl(this._els, this.edge);
|
||||
var overlap = focusOverlap.getOverlap($focusedElement, this.edge, endOfFurthestEl);
|
||||
|
||||
if (overlap > 0) {
|
||||
$(window).scrollTop($(window).scrollTop() + overlap);
|
||||
}
|
||||
};
|
||||
ScrollArea.prototype.destroy = function () {
|
||||
this.removeEvents();
|
||||
};
|
||||
|
||||
// Object collecting together methods for interacting with scrollareas
|
||||
var scrollAreas = {
|
||||
@@ -95,6 +114,44 @@
|
||||
}
|
||||
};
|
||||
|
||||
// Object collecting together methods for stopping sticky overlapping focused elements
|
||||
var focusOverlap = {
|
||||
getOverlap: function ($focusedElement, edge, endOfFurthestEl) {
|
||||
var topOfFocusedElement = $focusedElement.offset().top;
|
||||
|
||||
if (!endOfFurthestEl) { return 0; }
|
||||
|
||||
if (edge === 'top') {
|
||||
return endOfFurthestEl - topOfFocusedElement;
|
||||
} else {
|
||||
return (topOfFocusedElement + $focusedElement.outerHeight()) - endOfFurthestEl;
|
||||
}
|
||||
},
|
||||
endOfFurthestEl: function (els, edge) {
|
||||
var stuckEls = $.grep(els, function (el) { return el.isStuck(); });
|
||||
var edgeOfEl;
|
||||
var offsets;
|
||||
|
||||
if (edge === 'bottom') {
|
||||
edgeOfEl = function (el) {
|
||||
return el.$fixedEl.offset().top;
|
||||
};
|
||||
} else {
|
||||
edgeOfEl = function (el) {
|
||||
return el.$fixedEl.offset().top + el.height;
|
||||
};
|
||||
}
|
||||
|
||||
if (!stuckEls.length) { return false; }
|
||||
|
||||
offsets = $.map(stuckEls, function (el) { return edgeOfEl(el); });
|
||||
|
||||
return offsets.reduce(function (accumulator, offset) {
|
||||
return (accumulator < offset) ? offset: accumulator;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Object collecting together methods for dealing with marking the edge of a sticky, or group of
|
||||
// sticky elements (as seen in dialog mode)
|
||||
var oppositeEdge = {
|
||||
|
||||
Reference in New Issue
Block a user