2

Is there a way to check if the page has changed when the page is on the local filesystem (file:/// not http:// or https://)?

There are answers here that use AJAX to check the headers for a "Last-Modified" header but this is not returned when using the file protocol.

Here's the headers returned in Firefox when testing locally:

// headers
Content-Type: text/xml
Content-Length: 20941

Update:
It looks like the response is set to the file and that has a lastModified property on response. I've added an answer.

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • You can try [`document.lastModified`](https://developer.mozilla.org/en-US/docs/Web/API/Document/lastModified). If that doesn't work, would it be possible to monitor and cache the page's contents, depending on your application? – robere2 Dec 09 '18 at 02:03
  • I can get `document.lastModified` on the current document once the page is loaded into the browser. But I would have to reload the document to check that value. So I'm looking at ways to find if the document has changed on the file system and reloading it only when it has changed. – 1.21 gigawatts Dec 09 '18 at 02:12

4 Answers4

1

What you could do is change the request header from HEAD to GET/POST, which'll return a responseText value. From there, it's very easy to check - have a value before the GET/POST call named original or something similar, compare it to the response, and change stuff if necessary.

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • 1
    This could miss a lot of changes. What if a file contains `aaaaaa` but then changes to `bbbbbb`? – robere2 Dec 09 '18 at 02:05
  • Well, there weren't any other headers given to us by the OP @1.21gigawatts so I don't really have any other things to check. They also did not post their code, or an example file. – Jack Bashford Dec 09 '18 at 02:06
  • Thanks. If I can't get the last modified date I'll fall back on the content length and check if it's changed with the caveat that it could miss changes when the content size is exactly the same. – 1.21 gigawatts Dec 09 '18 at 02:09
  • 1
    Is there a way you can get the *contents* of the file as well? That way would be much easier. – Jack Bashford Dec 09 '18 at 02:10
  • Yeah. If I change the request from HEAD to GET or POST it will return the value in a `responseText` value. – 1.21 gigawatts Dec 09 '18 at 02:13
  • 1
    And then you can just check them from there - very easy! – Jack Bashford Dec 09 '18 at 02:13
1

Based off of your replies in the comments, I would use some form of caching the page.

Check this answer to get the page's current contents as a string and cache it/a hash of it. From there, perform an AJAX request to the current page and compare the contents/hashes. If they do not match, then you can reload the page.

let contents = document.documentElement.outerHTML;
let frequency = 5000; // How often to check for changes (ms)

setInterval(() => {
    let xmlhttp = new XMLHttpRequest();

    xmlhttp.addEventListener("load", (res) => { 
        if(res.responseText != contents)
            window.location.reload(true);
    });

    xmlhttp.open("GET", window.location.href);
    xmlhttp.send();
}, frequency);
robere2
  • 1,689
  • 2
  • 16
  • 26
1

After some debugging I noticed that the response is set to the file in the response property and that has a lastModified property on it!

Modifiying the code in @bugfroggy's answer this seems to work:

function checkForChanges() {
    var contentDate = null;
    var frequency = 5000;

    setInterval(() => {
        let xmlhttp = new XMLHttpRequest();

        xmlhttp.addEventListener("load", (progressEvent) => {
            console.log("Content loaded()");
            if (contentDate==null) {
                contentDate = xmlhttp.response.lastModified;
                return;
            }

            if(xmlhttp.response.lastModified != contentDate) {
                window.location.reload(true);
            }
        });

        //xmlhttp.open("GET", window.location.href);
        xmlhttp.open("HEAD", window.location.href);
        //xmlhttp.responseType = "blob";
        xmlhttp.send();
    }, frequency);

}

checkForChanges();

Note: I think the code above uses ES5 or ES6 features and I don't know if this will work on a server (http:// or https://).

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
0

Use a dev webserver that auto reloads on changes, better to test with a web server over serving from the file system anyway.

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60