68

How do I bind a function to the HTML5 localStorage change event using jQuery?

$(function () {

  $(window).bind('storage', function (e) {
    alert('storage changed');
  });

  localStorage.setItem('a', 'test');

});

I've tried the above but the alert is not showing.

Update: It works in Firefox 3.6 but it doesn't work in Chrome 8 or IE 8 so the question should be more 'How to bind to localStorage change event using jQuery for all browsers?'

David Glenn
  • 24,412
  • 19
  • 74
  • 94
  • works fine for me. You should maybe add a little feature detection.. `if(!localStorage in window) alert('foobar');` http://typeofnan.blogspot.com/2010/09/localstorage-inter-window-communication.html – jAndy Jan 12 '11 at 17:38
  • @jAndy are you using safari, and i have also tested his solution but same result, i think it may not be supported – RobertPitt Jan 12 '11 at 17:41
  • 1
    This works for me in Firefox, but not in Chrome. Indeed, I can't get Chrome to work with `addEventListener` either. – lonesomeday Jan 12 '11 at 17:41
  • yea you may have to create a wrapper – RobertPitt Jan 12 '11 at 17:44
  • pretty strange. Chrome doesn't work anywore ? I know it did in the past. – jAndy Jan 12 '11 at 17:50

5 Answers5

94

It turns out that this is actually working correctly and I have misinterpreted the specification

When the setItem(), removeItem(), and clear() methods are called on a Storage object x that is associated with a local storage area, if the methods did something, then in every Document object whose Window object's localStorage attribute's Storage object is associated with the same storage area, other than x, a storage event must be fired

In other words, a storage event is fired on every window/tab except for the one that updated the localStorage object and caused the event.

So the event was not fired because I only had one window/tab open. If I place the above code in a page and open the page in two tabs I would see the event fired in the second tab.

This answer on the problem contains more details.

Community
  • 1
  • 1
David Glenn
  • 24,412
  • 19
  • 74
  • 94
  • 2
    Firefox's implementation of the specification (in 3.6) is incorrect as it fires the event in the window that updated the localStorage – David Glenn Jan 14 '11 at 08:05
  • 6
    Firefox seems to have corrected the problem, however IE9 and IE10 still do not follow the spec. They fire the event in ALL windows/tabs, including the one that originated the change. I've raised this bug with Microsoft here (requires login unfortunately): https://connect.microsoft.com/IE/feedback/details/774798/localstorage-event-fired-in-source-window – Dave Lockhart Dec 19 '12 at 22:53
  • Thanks for that! I've been going crazy for two days wondering why my localstorage was updating twice in front of my eyes when I wasn't doing anything... I had another window opened with another user logged in that was storing different data. But of course with local storage shared between domains that was why! Thanks again – Got The Fever Media Dec 02 '14 at 14:03
13

Here's how to do it in JQuery:

 $(window).bind('storage', function (e) {
     console.log(e.originalEvent.key, e.originalEvent.newValue);
 });

Accessing e.key directly does not work. You need to use e.originalEvent.key.

Some browsers will only send storage notifications to other tabs, and some won't. (Firefox will send storage events to its own tab, but with key set to null, it seems like).

SFin
  • 149
  • 13
Flimm
  • 136,138
  • 45
  • 251
  • 267
  • Firefox repaired that bug, it's working same way as in Chrome, but IE 11 still works buggy so it fires an event in its own tab... – JayDee Aug 07 '20 at 06:18
8

One thing to mention is that the event handler is only called on .setItem if the item actually changes. I was ripping my hair out trying to get this to work until I realized you can't keep running setItem with the same value.

I am on Chrome Version 54.0.2840.71 m

Here is a test (open this in two browser tabs).

if (window.addEventListener)
            addEventListener('storage', storage_event, false);
        else if (window.attachEvent)
            attachEvent('onstorage', storage_event, false);
        function storage_event(e) {
            console.log("Time is now "+ e.newValue);
        }

        setInterval(function () {
            var time=new Date().getTime();
            localStorage.setItem("time", time);
            console.log("Setting time to "+time);
        }, 1000)
kmoney12
  • 4,413
  • 5
  • 37
  • 59
3

You could always use a utility like localDataStorage to fire the events for you, in the same window/tab, whenever a key value changes, such as those made by the set or remove methods. You can also use it to transparently set/get any of the following "types": Array, Boolean, Date, Float, Integer, Null, Object or String.

[DISCLAIMER] I am the author of the utility [/DISCLAIMER]

Once you instantiate the utility, the following snippet will allow you to monitor the events (in vanilla JS, since jQuery examples have already been given):

function localStorageChangeEvents( e ) {
    console.log(
        "timestamp: "     + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
        "key: "           + e.detail.key     + "\n" +
        "old value: "     + e.detail.oldval  + "\n" +
        "new value: "     + e.detail.newval  + "\n"
    );
};
document.addEventListener(
    "localDataStorage"
    , localStorageChangeEvents
    , false
);
Mac
  • 1,432
  • 21
  • 27
0

An update to @Flimm's answer; .bind() method is deprecated after jQuery 3.0 so using .on() method is recommended.

$(window).on('storage', function (e) {
  console.log(e.originalEvent.key, e.originalEvent.newValue);
});
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
MrAlbino
  • 308
  • 2
  • 10