Skip to content

Commit

Permalink
Tweak x-navigate
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Jun 26, 2023
1 parent ae68667 commit 96b477a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 77 deletions.
2 changes: 2 additions & 0 deletions packages/alpinejs/src/alpine.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getBinding as bound } from './utils/bind'
import { debounce } from './utils/debounce'
import { throttle } from './utils/throttle'
import { setStyles } from './utils/styles'
import { entangle } from './entangle'
import { nextTick } from './nextTick'
import { walk } from './utils/walk'
import { plugin } from './plugin'
Expand Down Expand Up @@ -52,6 +53,7 @@ let Alpine = {
setStyles, // INTERNAL
mutateDom,
directive,
entangle,
throttle,
debounce,
evaluate,
Expand Down
68 changes: 33 additions & 35 deletions packages/navigate/src/index.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
import { transition } from "alpinejs/src/directives/x-transition"
import { finishAndHideProgressBar, showAndStartProgressBar } from "./bar"
import { fetchHtml } from "./fetch"
import { updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks, updateUrlAndStoreLatestHtmlForFutureBackButtons, whenTheBackOrForwardButtonIsClicked } from "./history"
import { extractDestinationFromLink, hijackNewLinksOnThePage, whenALinkIsClicked, whenALinkIsHovered } from "./links"
import { swapCurrentPageWithNewHtml } from "./page"
import { putPersistantElementsBack, storePersistantElementsForLater } from "./persist"
import { getPretchedHtmlOr, prefetchHtml, storeThePrefetchedHtmlForWhenALinkIsClicked } from "./prefetch"
import { extractDestinationFromLink, whenThisLinkIsClicked, whenThisLinkIsHovered } from "./links"
import { restoreScrollPosition, storeScrollInformationInHtmlBeforeNavigatingAway } from "./scroll"
import { putPersistantElementsBack, storePersistantElementsForLater } from "./persist"
import { finishAndHideProgressBar, showAndStartProgressBar } from "./bar"
import { transition } from "alpinejs/src/directives/x-transition"
import { swapCurrentPageWithNewHtml } from "./page"
import { fetchHtml } from "./fetch"

let enablePrefetch = true
let enablePersist = true
let showProgressBar = true
let restoreScroll = true
let autofocus = false

export default function (Alpine) {
updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks()
Alpine.directive('navigate', (el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
let shouldPrefetch = modifiers.includes('prefetch')

enablePrefetch && whenALinkIsHovered((el) => {
let forDestination = extractDestinationFromLink(el)
shouldPrefetch && whenThisLinkIsHovered(el, () => {
let forDestination = extractDestinationFromLink(el)

prefetchHtml(forDestination, html => {
storeThePrefetchedHtmlForWhenALinkIsClicked(html, forDestination)
prefetchHtml(forDestination, html => {
storeThePrefetchedHtmlForWhenALinkIsClicked(html, forDestination)
})
})
})

whenALinkIsClicked((el) => {
showProgressBar && showAndStartProgressBar()
whenThisLinkIsClicked(el, () => {
showProgressBar && showAndStartProgressBar()

let fromDestination = extractDestinationFromLink(el)
let fromDestination = extractDestinationFromLink(el)

fetchHtmlOrUsePrefetchedHtml(fromDestination, html => {
restoreScroll && storeScrollInformationInHtmlBeforeNavigatingAway()
fetchHtmlOrUsePrefetchedHtml(fromDestination, html => {
restoreScroll && storeScrollInformationInHtmlBeforeNavigatingAway()

showProgressBar && finishAndHideProgressBar()
showProgressBar && finishAndHideProgressBar()

updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks()
updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks()

preventAlpineFromPickingUpDomChanges(Alpine, andAfterAllThis => {
enablePersist && storePersistantElementsForLater()
preventAlpineFromPickingUpDomChanges(Alpine, andAfterAllThis => {
enablePersist && storePersistantElementsForLater()

swapCurrentPageWithNewHtml(html, () => {
enablePersist && putPersistantElementsBack()
swapCurrentPageWithNewHtml(html, () => {
enablePersist && putPersistantElementsBack()

// Added setTimeout here to detect a currently hovered prefetch link...
// (hack for laracon)
setTimeout(() => hijackNewLinksOnThePage())
restoreScroll && restoreScrollPosition()

restoreScroll && restoreScrollPosition()
fireEventForOtherLibariesToHookInto()

fireEventForOtherLibariesToHookInto()
updateUrlAndStoreLatestHtmlForFutureBackButtons(html, fromDestination)

updateUrlAndStoreLatestHtmlForFutureBackButtons(html, fromDestination)
andAfterAllThis(() => {
autofocus && autofocusElementsWithTheAutofocusAttribute()

andAfterAllThis(() => {
autofocus && autofocusElementsWithTheAutofocusAttribute()

nowInitializeAlpineOnTheNewPage(Alpine)
nowInitializeAlpineOnTheNewPage(Alpine)
})
})
})

})
})
})

updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks()

whenTheBackOrForwardButtonIsClicked((html) => {
// @todo: see if there's a way to update the current HTML BEFORE
// the back button is hit, and not AFTER:
Expand Down
51 changes: 9 additions & 42 deletions packages/navigate/src/links.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,18 @@

let handleLinkClick = () => {}
let handleLinkHover = () => {}
export function whenThisLinkIsClicked(el, callback) {
el.addEventListener('click', e => {
e.preventDefault()

export function whenALinkIsClicked(callback) {
handleLinkClick = callback

initializeLinksForClicking()
callback(el)
})
}

export function whenALinkIsHovered(callback) {
handleLinkHover = callback

initializeLinksForHovering()
export function whenThisLinkIsHovered(el, callback) {
el.addEventListener('mouseenter', e => {
callback(e)
})
}

export function extractDestinationFromLink(linkEl) {
return new URL(linkEl.getAttribute('href'), document.baseURI)
}

export function hijackNewLinksOnThePage() {
initializeLinksForClicking()
initializeLinksForHovering()
}

function initializeLinksForClicking() {
getLinks().forEach(el => {
el.addEventListener('click', e => {
e.preventDefault()

handleLinkClick(el)
})
})
}

function initializeLinksForHovering() {
getLinks()
.filter(i => i.hasAttribute('wire:navigate.prefetch'))
.forEach(el => {
el.addEventListener('mouseenter', e => {
handleLinkHover(el)
})
})
}

function getLinks() {
return Array.from(document.links)
.filter(i => i.hasAttribute('wire:navigate')
|| i.hasAttribute('wire:navigate.prefetch'))
}

0 comments on commit 96b477a

Please sign in to comment.