3

I want to create plugin mechanizm. It is, you can load js file on my website and run your js "plugin" (function) when this plugin is set to run (toggled as running).

All this I want to do without any server.

I mean, I want to keep in localstorage js files or path to this files.

It looks to be hard to do because js can't easy access files path.

I handle file by <input type="file"/>

And I react on onchange event. I get event where I can find selected file by event.srcElement.files[0]

With that I can create URL of that object by : URL.createObjectURL(event.srcElement.files[0])

And I tried to store that URL in localstorage but this URL is temporary. Also I tried to store whole event or just file (event.srcElement.files[0]).

But I need to create string from that if I want to put it to the function .setItem :

localStorage.setItem("functionURL", JSON.stringify(this.functionURL));

.toString() creates [Object Event/File]

JSON.stringify() creates {} from [Object Event/File]

So, maybe is there a way to somehow remember file which we can use as a function without any server ?

  • 1
    I kind of like this idea and may well steal it. :-) I mean, sure, people could use GreaseMonkey or TamperMonkey instead, but... – T.J. Crowder Sep 27 '17 at 17:37
  • @T.J.Crowder been working on this for a while, I finally have a [Web Component](https://jsfiddle.net/patrob10114/rekyegxk/show/) that acts as a file selector that remembers the chosen file using `localStorage` or `sessionStorage`. Another cool thing about this is I pack the binary data of the File objects into `Storage` using UTF-16 code points for the strings, so that every two bytes of the file corresponds to one character of the UTF-16 encoded string in order to efficiently use the 5MB limited memory allocated to the Storage API. – Patrick Roberts Oct 04 '17 at 21:18

1 Answers1

2

So, maybe is there a way to somehow remember file which we can use as a function without any server ?

Basically, no. :-) Web storage only stores strings. You can't use a string to access a file on the user's local filesystem from your web page, for obvious security reasons.

You could, instead:

  1. Make it possible for them to "upload" the file into your page (without a server) by having them identify the file in an input[type=file], reading its text (via the File API), and then storing that text in local storage
  2. On page load, if local storage has code to run, run it
  3. Offer the user a way to delete or update the code they've uploaded to the page

Since all of that happens in the browser, you don't need a server.

Web storage does have size limits, though they're pretty generous, (around 2.5-5MB) and per-origin, so you have that largely to yourself. But if you run into those limits, you could take it further by caching those files via a service worker, but the complexity goes up markedly. I'd start with web storage and only move on if you really need to support massive files.

#1 (reading the script file the user identifies via an input[type=file]) is really simple on modern browsers:

var file = input.files[0];
var fr = new FileReader();
fr.onload = function() {
    // Use `fr.result` here, it's a string containing the text
};
fr.readAsText(file);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • If it's conceivable to stay below the limit, like for a text file or a moderately-sized CSV file or word-doc or something of the sort, you can consider using [`FileReader#readAsDataURL()`](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL) to obtain the data from the file as text and then use [this](https://stackoverflow.com/a/12300351/1541563) to reconstruct a `Blob` from the resulting data-url. – Patrick Roberts Sep 27 '17 at 17:24
  • @PatrickRoberts: True, but the URL is going to be bigger than the file's contents, may as well save them directly. – T.J. Crowder Sep 27 '17 at 17:28
  • I know that... there is also the option of `readAsBinaryString()` but I haven't tested if there's any complications with consistently reproducing the original binary in the reconstruction step when you come across non-ASCII code points in the string. That would allow the string to remain the same size as the file instead of 4/3 its size, but it'll need more care being reconstructed. You'll also need to store the MIME-type separately for that approach. – Patrick Roberts Sep 27 '17 at 17:31
  • @PatrickRoberts: I think I'm missing the point. Why would binary come into this? Just read it as text. – T.J. Crowder Sep 27 '17 at 17:32
  • Oh, word docs would require binary since they have non-ASCII code points in them, for example. The default for `readAsText()` is utf8 encoding, which would garble those code points when reading. – Patrick Roberts Sep 27 '17 at 17:32
  • @PatrickRoberts: The OP's question is about running JavaScript code on his page. It would be weird to write JavaScript code in a Word doc. :-) Same for CSS if he/she wants to support that. But yes, if binary resources were to be supported, they'd need to be read and stored differently from the text resources. – T.J. Crowder Sep 27 '17 at 17:36
  • 1
    Oh, I totally missed that! `readAsText()` with utf-8 encoding would be perfect in most cases then, carry on :) I had skimmed and assumed it was some sort of generic small-scale client-side file storage plugin or something. – Patrick Roberts Sep 27 '17 at 17:37