I mean how bad can it be? Storing images for few future passages shouldn't be critical. All modern PC's must handle that load.
It's not about the computer. It's also not about the images. They'll either be ready or not ready when the user clicks the link and goes to the next passage (I don't think you should actually force them into a 'loading screen' situation) all this code does is give the images a decent head start of however long it takes the user to read the passage. In reality, it should be long enough for most reasonably-sized images. If you're loading up 4k bitmaps, I don't know if anything can help you there.
It's about the browser's JavaScript engine. Stacking a large amount of complicated code like this (it uses all your classic performance killers: regex, DOM lookup, etc) onto SugarCube's rendering system will eventually make it seem laggy and unresponsive. Browsers can only interpret so much code so fast.
I'm not an expert, though; I don't know how big a deal this code will be in the long run. I just recommend keeping an eye on things. If your passage transitions start getting wonky, this might be the culprit. Lots of links and lots of images all being processed, in addition to SugarCube's normal parsing and rendering and State copying, not to mention anything else you have going on in task objects or special passages, it could all start slowing things down.
Anyway, here's the example. We'll use the same CSS as from the forum post:
#imgloader-box{position:fixed;left:0;top:0;width:2px;height:2px;overflow:hidden;z-index:0}
#imgloader-box img{position:absolute;left:0;top:0;width:1px;height:1px}
Then, in the JavaScript:
(function () { // set up the element
var $preloader = $(document.createElement('div'));
$preloader
.attr('id', 'imgloader-box')
.appendTo(document.body);
}());
setup.getMatches = function (string, regex, index) {
// taken from here: https://stackoverflow.com/a/14210948
index || (index = 1);
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
};
setup.preload = function (sources) {
$('#imgloader-box').empty(); // empty the box
if (sources && Array.isArray(sources) && sources.length > 0) {
sources.forEach(function (src) { // append images
var $image = $(document.createElement('img'));
$image
.attr('src', src)
.appendTo('#imgloader-box');
});
}
};
setup.crawlForLinks = function () { // look for links in current passage
if (tags().includes('noCrawl')) { // just in case you want to skip some passages
return;
}
var $links = $('a').toArray(), linked = [];
$links.forEach(function (l) {
if ($(l).attr('data-passage')) {
linked.push($(l).attr('data-passage'));
}
});
return linked;
};
setup.crawlForImages = function (psg) { // look for images in passage source code
if (!Story.has(psg)) {
return; // someone made a mistake...
}
var sources = [];
psg = Story.get(psg).text;
// find html elements
var html = /<img\s.*?src=["'](.*?)['"].*?>/gi;
html = setup.getMatches(psg, html, 1);
sources = (html.length) ? sources.concat(html) : sources;
// find wiki images
var wiki = /\[img\[(.*?)[|\]].*?\]/gi;
wiki = setup.getMatches(psg, wiki, 1);
sources = (wiki.length) ? sources.concat(wiki) : sources;
return sources;
};
postdisplay['preload-images'] = function (t) { // the postdisplay that brings it all together
var linked = setup.crawlForLinks(), sources = [];
if (linked) {
linked.forEach(function (p) {
var temp = setup.crawlForImages(p);
sources = (temp) ? sources.concat(temp) : sources;
});
}
setup.preload(sources);
};
A few caveats:
- There might be bugs. I tested it, but not thoroughly.
- This is a bit messy in a few places, and it doesn't support everything--it won't look at <<goto>>s or <<button>>s, though you could add that functionality pretty easily.
- I'm not great at regex, so there might be a better way to find the image sources.
- There is no error handling.
- Overall, I'd build off of this; I'm not sure you'd want to use it as is.