Skip to content

Instantly share code, notes, and snippets.

@Ch4s3
Last active February 9, 2022 17:26
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Ch4s3/49a018d32e93bbf7d52064ad9b314d78 to your computer and use it in GitHub Desktop.
Save Ch4s3/49a018d32e93bbf7d52064ad9b314d78 to your computer and use it in GitHub Desktop.
decaffeinated version of https://gist.github.com/Enalmada/6e11191c1ea81a75a4f266e147569096 with a flag for turning it on or off
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const OldHttpRequest = Turbolinks.HttpRequest;
Turbolinks.CachedHttpRequest = class CachedHttpRequest extends Turbolinks.HttpRequest {
constructor(_, location, referrer) {
super();
super(this, location, referrer);
}
requestCompletedWithResponse(response, redirectedToLocation) {
this.response = response;
return(this.redirect = redirectedToLocation);
}
requestFailedWithStatusCode(code) {
return(this.failCode = code);
}
oldSend() {
if (this.xhr && !this.sent) {
this.notifyApplicationBeforeRequestStart();
this.setProgress(0);
this.xhr.send();
this.sent = true;
return(this.delegate, 'requestStarted', o => o.requestStarted());
}
}
send() {
if (this.failCode) {
return(this.delegate.requestFailedWithStatusCode(this.failCode, this.failText));
} else if (this.response) {
return(this.delegate.requestCompletedWithResponse(this.response, this.redirect));
} else {
return(this.oldSend());
}
}
};
Turbolinks.HttpRequest = class HttpRequest {
constructor(delegate, location, referrer) {
const cache = Turbolinks.controller.cache.get(`prefetch${location}`);
if (cache) {
//Turbolinks.controller.cache = new Turbolinks.SnapshotCache 10
Turbolinks.controller.cache.delete(`prefetch${location}`);
console.log(JSON.stringify(Turbolinks.controller.cache.keys));
cache.delegate = delegate;
return cache;
} else {
return(new OldHttpRequest(delegate, location, referrer));
}
}
};
Turbolinks.SnapshotCache.prototype.delete = function(location) {
const key = Turbolinks.Location.wrap(location).toCacheKey();
return(delete this.snapshots[key]);
};
const preloadAttribute = function(link) {
const linkAttr = link.attributes['data-turbolinks-preload']
if (!linkAttr || linkAttr.value === 'false') {
return false;
} else {
return true;
}
}
const isNotGetMethod = function(link) {
link.attributes['data-method'] && (link.attributes['data-method'].value !== 'get')
}
//This function returns true if the link or location shouldn't be
const notPreloadable = function(link, location){
if (preloadAttribute(link) === false) {
return true;
} else if (isNotGetMethod(link)) {
return true;
} else if (location.anchor || location.absoluteURL.endsWith("#")) {
return true;
} else if (location.absoluteURL === window.location.href) {
return true;
} else {
return false;
}
}
const preload = function(event) {
let link = Turbolinks.controller.getVisitableLinkForNode(event.target);
if (link) {
let location = Turbolinks.controller.getVisitableLocationForLink(link);
if (location) {
if (Turbolinks.controller.applicationAllowsFollowingLinkToLocation(link, location)) {
if (notPreloadable(link, location)) {
return;
}
// If Turbolinks has already cached this location internally, use that default behavior
// otherwise we can try and prefetch it here
let cache = Turbolinks.controller.cache.get(location);
if (!cache) {
cache = Turbolinks.controller.cache.get(`prefetch${location}`);
}
if (!cache) {
const request = new Turbolinks.CachedHttpRequest(null, location, window.location);
Turbolinks.controller.cache.put(`prefetch${location}`, request);
return(request.send());
}
}
}
}
};
document.addEventListener("touchstart", preload);
document.addEventListener("mouseover", preload);
@Ch4s3
Copy link
Author

Ch4s3 commented Oct 24, 2017

This gist is the result of running this gist by Enalmada through decaffeinate, adding the preloadAttribute() function, and a little refactoring.

to use this throw it in you bundle/index/applicatio.js as follows:

import Turbolinks from 'turbolinks';
Turbolinks.start();
require('./turboLinksPreFetch.js');

then create a link like this: <a data-turbolinks-preload="true" href="/cat_pic/9000">Super Great Cat Pics</a>.

If data-turbolinks-preload="true" is missing or set to false the link will not be preloaded. This allows you to manually or programmatically apply it.

@grosser
Copy link

grosser commented Sep 29, 2018

FYI change oldSend to this to get back progesssbar for slow requests

oldSend() {
      if(!this.xhr) return;

      if (!this.sent) {
        this.notifyApplicationBeforeRequestStart();
        this.setProgress(0);
        this.xhr.send();
        this.sent = true;
        return(this.delegate, 'requestStarted', o => o.requestStarted());
      } else {
        // request is prefetched but is in flight: show progress
        // can reproduce this by making replies super slow
        Turbolinks.controller.adapter.showProgressBar();
        this.setProgress(0);
      }
    }

@dfang
Copy link

dfang commented Jul 28, 2020

hi, currently i'm not using rails, prefetching only works on first page, when i clicked and redirected to another page, prefetching not works. what am i doing wrong ?

in html head tag,

<script defer src="https://cdn.jsdelivr.net/npm/turbolinks@5.2.0/dist/turbolinks.min.js"></script> <script src="custom.js"></script>

i translated this coffeescript to javascript by http://js2.coffee/, then add it to turbolinks:load

document.addEventListener("turbolinks:load", () => {
// add code here
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment