instantpage.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*! instant.page v0.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license */
  2. let urlBeingPreloaded
  3. const prefetcher = document.createElement('link')
  4. const isSupported = prefetcher.relList && prefetcher.relList.supports && prefetcher.relList.supports('prefetch')
  5. if (isSupported) {
  6. prefetcher.rel = 'prefetch'
  7. document.head.appendChild(prefetcher)
  8. document.addEventListener('mouseover', mouseoverListener, true)
  9. }
  10. function mouseoverListener(event) {
  11. const linkElement = event.target.closest('a')
  12. if (!linkElement) {
  13. return
  14. }
  15. if (!isPreloadable(linkElement)) {
  16. return
  17. }
  18. linkElement.addEventListener('mouseout', mouseoutListener)
  19. preload(linkElement.href)
  20. }
  21. function mouseoutListener(event) {
  22. if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) {
  23. return
  24. }
  25. stopPreloading()
  26. }
  27. function isPreloadable(linkElement) {
  28. if (urlBeingPreloaded == linkElement.href) {
  29. return false
  30. }
  31. const urlObject = new URL(linkElement.href)
  32. if (urlObject.origin != location.origin) {
  33. return false
  34. }
  35. if (urlObject.pathname + urlObject.search == location.pathname + location.search && urlObject.hash) {
  36. return
  37. }
  38. if ('noInstant' in linkElement.dataset) {
  39. return false
  40. }
  41. return true
  42. }
  43. function preload(url) {
  44. urlBeingPreloaded = url
  45. prefetcher.href = url
  46. }
  47. function stopPreloading() {
  48. if (!urlBeingPreloaded) {
  49. return
  50. }
  51. urlBeingPreloaded = undefined
  52. /* The spec says an empty string should abort the prefetching
  53. * but Firefox 64 interprets it as a relative URL to prefetch. */
  54. prefetcher.removeAttribute('href')
  55. }