0

Is it possible to update the CSS image pointed by the passed-in url in "backgound-image: \"<some-url>\" in Javascript only when the source image is changed in the server. I.e. cache the image, and then retrieve the image from the server when it's needed to be reload and compare it with the cached image. Then, reload it when it's updated only. I know that in order to refresh an image in CSS through Javascript, the image must have a different string after the "?" in the image source, and one way to do so is by using the current time returned by Date.getTime method after "?". E.g. (I got this method from here https://stackoverflow.com/a/1077051/7000599):

$(".some-css-class").css("backgound-image", "url(" + "\"" + some_source + "?" + new Date().getTime() + "\"" + ")");

However, I would like to call the above logic when I need to update the background-image only when it detect the image has been changed. So is there a way to detect such changes?

falhumai96
  • 97
  • 1
  • 11
  • You would need to create a timer that does an XMLHTTP request to the image every few seconds, and check the last modified date of the image, and then compare that to a cached copy of when the file was last modified. That seems like an awful lot of work, and is rather intensive. Why exactly do you need the image to update? Can't you just ensure that the visitor never caches that image in the first place? – Obsidian Age Jun 26 '17 at 23:16
  • @ObsidianAge No, but for instance, if I have set onInterval event somewhere to update the photo, I want the event handler to update the image only when the cached image != the new image, so, for instance, I won't see image flickering except when it's really updating!! – falhumai96 Jun 26 '17 at 23:21
  • Only way to detect it is to load it.... Or you have a service that tells you it changed. So either you break the cache on every call (querytring or no cache header) or you write something that says the image changed. – epascarello Jun 26 '17 at 23:39

4 Answers4

0

Give each image a unique id and then poll the server every so often to see if there's a new id, and if so, change the underlying image.

Difster
  • 3,240
  • 2
  • 19
  • 32
0

You may add API to server side which returns some hash value for image content. So when you put the image for first time - add hash-value for specific image after '?'.

$(".come-css-class").css("backgound-image", "url(" + "\"" + some_source + "?" + imageHash + "\"" + ")");

Than from time to time call the hash API and replace background-image property. When image will be updated on server - it will return new hash-value - so css will reload the image.

Oleg Imanilov
  • 2,268
  • 1
  • 11
  • 21
  • Lmao, I just thought about a similar answer for it!! thx though!! – falhumai96 Jun 26 '17 at 23:23
  • Can I generate the hash of the loaded image from the Javascript side though?? – falhumai96 Jun 26 '17 at 23:45
  • You can, but it will be wrong, because you will get same image over the network again and again just to ensure that it's content doesn't changed. – Oleg Imanilov Jun 29 '17 at 05:49
  • I decided to rely on using https://en.wikipedia.org/wiki/HTTP_ETag as a way to detect whether the content has changed or not. The ETag will update if the source is updated!! – falhumai96 Jun 29 '17 at 05:59
0

To automatically update the image through JavaScript itself (without relying on any back-end script), you would need to poll the server periodically to check whether the modification date was greater than a cached copy of the image. You would then need to refresh the page if this was the case.

This would be done similar to the following:

var previous = null;
var current = null;
var image_url = 'IMAGE URL';
setInterval(function() {
  var req = new XMLHttpRequest(); // Poll the server
  req.open("HEAD", image_url, false);
  req.send(null);
  if (req.status == 200) {
    current = req.getResponseHeader('Last-Modified'); // Get modification time
  }
  if (previous && current && previous !== current) { // If it's been modified
    location.reload(); // Refresh
  }
  previous = current; // Store the 'new' image information
  $(".come-css-class").css("background-image", "url(" + "\"" + image_url + "\""); // Update the image
}, 2000); // Repeat every two seconds

Also note that you called it backgound-image in your question. You need to ensure that you call it background-image in order to function correctly.

Hope this helps! :)

Obsidian Age
  • 36,816
  • 9
  • 39
  • 58
0

Similar to a reply comment to @Nosyara, I think the better approach to this problem I have found so far is by using the HTTP header ETag to detect whether the source image (or file as well) is changed from the last cached file. I think @ObsidianAge's answer would also work (i.e. using the Last-Modified header), but for some reason it doesn't show any changes when the source image (or file) is changed. I did a simple local Apache server and simple webpage with a Javascript onInterval event to console.log whether the file has changed or not, but it doesn't seem the case. So apparently ETag is a way to do it. Here's the Wikipedia page explaining it's purposes (it has other purposes too): https://en.wikipedia.org/wiki/HTTP_ETag.

falhumai96
  • 97
  • 1
  • 11