* Enable the author to trigger spatial navigation programmatically, as if the user had done so manually. * @see https://drafts.csswg.org/css-nav-1/#dom-window-navigate * @function navigate * @param dir {SpatialNavigationDirection} - The directional information for the spatial naviga
(dir)
| 149 | * @param dir {SpatialNavigationDirection} - The directional information for the spatial navigation (e.g. LRUD) |
| 150 | */ |
| 151 | function navigate(dir) { |
| 152 | // spatial navigation steps |
| 153 | |
| 154 | // 1 |
| 155 | const searchOrigin = findSearchOrigin(); |
| 156 | let eventTarget = searchOrigin; |
| 157 | |
| 158 | let elementFromPosition = null; |
| 159 | |
| 160 | // 2 Optional step, UA defined starting point |
| 161 | if (startingPoint) { |
| 162 | // if there is a starting point, set eventTarget as the element from position for getting the spatnav container |
| 163 | elementFromPosition = document.elementFromPoint(startingPoint.x, startingPoint.y); |
| 164 | |
| 165 | // Use starting point if the starting point isn't inside the focusable element (but not container) |
| 166 | // * Starting point is meaningfull when: |
| 167 | // 1) starting point is inside the spatnav container |
| 168 | // 2) starting point is inside the non-focusable element |
| 169 | if (elementFromPosition === null) { |
| 170 | elementFromPosition = document.body; |
| 171 | } |
| 172 | if (isFocusable(elementFromPosition) && !isContainer(elementFromPosition)) { |
| 173 | startingPoint = null; |
| 174 | } else if (isContainer(elementFromPosition)) { |
| 175 | eventTarget = elementFromPosition; |
| 176 | } else { |
| 177 | eventTarget = elementFromPosition.getSpatialNavigationContainer(); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | // 4 |
| 182 | if (eventTarget === document || eventTarget === document.documentElement) { |
| 183 | eventTarget = document.body || document.documentElement; |
| 184 | } |
| 185 | |
| 186 | // 5 |
| 187 | // At this point, spatialNavigationSearch can be applied. |
| 188 | // If startingPoint is either a scroll container or the document, |
| 189 | // find the best candidate within startingPoint |
| 190 | let container = null; |
| 191 | if ((isContainer(eventTarget) || eventTarget.nodeName === 'BODY') && !(eventTarget.nodeName === 'INPUT')) { |
| 192 | if (eventTarget.nodeName === 'IFRAME') { |
| 193 | eventTarget = eventTarget.contentDocument.documentElement; |
| 194 | } |
| 195 | container = eventTarget; |
| 196 | let bestInsideCandidate = null; |
| 197 | |
| 198 | // 5-2 |
| 199 | if ((document.activeElement === searchOrigin) || |
| 200 | (document.activeElement === document.body) && (searchOrigin === document.documentElement)) { |
| 201 | if (getCSSSpatNavAction(eventTarget) === 'scroll') { |
| 202 | if (scrollingController(eventTarget, dir)) return; |
| 203 | } else if (getCSSSpatNavAction(eventTarget) === 'focus') { |
| 204 | bestInsideCandidate = eventTarget.spatialNavigationSearch(dir, {container: eventTarget, candidates: getSpatialNavigationCandidates(eventTarget, {mode: 'all'})}); |
| 205 | if (focusingController(bestInsideCandidate, dir)) return; |
| 206 | } else if (getCSSSpatNavAction(eventTarget) === 'auto') { |
| 207 | bestInsideCandidate = eventTarget.spatialNavigationSearch(dir, {container: eventTarget}); |
| 208 | if (focusingController(bestInsideCandidate, dir) || scrollingController(eventTarget, dir)) return; |
no test coverage detected