This is an archived post. You won't be able to vote or comment.

all 58 comments

[–][deleted]  (1 child)

sorry, this has been archived and can no longer be voted on

[deleted]

    [–]pabs[S] 2 points3 points  (0 children)

    sorry, this has been archived and can no longer be voted on

    Thanks!

    [–]ItsAConspiracy 4 points5 points  (1 child)

    sorry, this has been archived and can no longer be voted on

    No plugin, no flash, just an interface to whatever storage the browser implements. This looks great.

    [–]pabs[S] 1 point2 points * (0 children)

    sorry, this has been archived and can no longer be voted on

    There are backends for two plugins: Flash and Gears. Neither is required in order for PersistJS to work its magic .

    The one notable exception is Opera, which have any sort of native client-side storage.

    So to support Opera users you need to rely on either Flash or cookies.

    [–]vsuontam 2 points3 points  (1 child)

    sorry, this has been archived and can no longer be voted on

    Can I see the full API somewhere, in addition to the example code?

    Just curios to see how to "publich" .js APIs.

    Examples look great!

    [–]pabs[S] 0 points1 point * (0 children)

    sorry, this has been archived and can no longer be voted on

    There isn't a full-blown API reference just yet, although the README file walks through the API in more detail and explains how to embed it in a page. The tarball also includes a functional test directory.

    [–]wetelectric 1 point2 points  (6 children)

    sorry, this has been archived and can no longer be voted on

    Nice. Need that IE6 testing though :)

    [–]pabs[S] 1 point2 points  (4 children)

    sorry, this has been archived and can no longer be voted on

    Yeah, I know. As soon as I have a chance I'm going to dig up an IE6 machine to do some testing.

    [–]mrak 0 points1 point  (3 children)

    sorry, this has been archived and can no longer be voted on

    if you're using pc running xp you can use multiple IE:http://tredosoft.com/Multiple_IE

    I tried to use the persistjs but there isn't a clear description of what to do in IE case. I tried using defer in constructor and save() after setting the string and load()before getting a string, but I get an errror in IE7

    [–]pabs[S] 0 points1 point  (2 children)

    sorry, this has been archived and can no longer be voted on

    I'm using multiple IE, but there are some intermittent problems with persistent data with older versions of IE.

    [–]bdiang 0 points1 point * (0 children)

    sorry, this has been archived and can no longer be voted on

    try this http://www.my-debugbar.com/wiki/IETester/HomePage

    About persistJS

    IE6 have bugs with using 'ie' method. It doesnt see 'save' and 'load' methods.

    FF2 has bug 'security error 1000' on localhost

    [–]ollicle 1 point2 points  (0 children)

    sorry, this has been archived and can no longer be voted on

    The test included in the download works in IE6 here. At least with short random words I have saved and loaded between sessions.

    [–][deleted]  (4 children)

    sorry, this has been archived and can no longer be voted on

    [deleted]

      [–]leonh -1 points0 points  (3 children)

      sorry, this has been archived and can no longer be voted on

      Please enlighten me, in what kind of use case do you find this 'exciting' ?

      I see the following reasons why i would not want to put that much effort (or in this case make use of an extra .js lib) in using client-side 'persistant' storage:

      • The persistant storage is specific to only one browser
      • It would be much more persistant if it is stored in some reliable storage space at the server

      [–]pabs[S] 1 point2 points * (1 child)

      sorry, this has been archived and can no longer be voted on

      I agree that it is generally far easier to save persistent data on the server. However, there are certain cases where that is impractical.

      For example, one of the tools I created at work has some strict privacy and security requirements which prohibit saving any information about the user or what they are doing on the server.

      The tool allows the user to save their work and load it again later. Because of the limit on cookie size, I have to compress the user's session state on the server side, then save that information as a cookie on the client side.

      This effectively limits the session size to approximately 10k (before compression, obviously), which means I have to keep a fairly low limit on the amount of state that is saved.

      With a reliable, cross-browser way of saving persistent data, I can include far more data on the client side.

      Another tool that I am working on has an offline mode. It allows the user to load up the page, then take their computer into an area without network access (for example, a secure facility without external network access). The tool saves any information the user enters in the client-side persistent storage. Once the user has network access again, they can upload their changes back to the server.

      [–]leonh 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Ah, yes the offline mode! It could really be useful there, I agree.

      Thanks.

      [–][deleted] 1 point2 points  (0 children)

      sorry, this has been archived and can no longer be voted on

      You could use this to eliminate the risk of session hijacking (e.g. you're on an insecure network like open wifi and someone sniffs your session cookie).

      When the user logs in (onsubmit), keep their plaintext password in client-side storage, but otherwise do everything as normal (submit the form, server sends back a Set-Cookie header with a session key). Thereafter, every time you hit the server, the server does a hash of the session key combined with your password (HMAC, ideally) to produce a new session key, but doesn't send a Set-Cookie header with the new value. Instead, javascript in the page (onload or manually after ajax requests) reads the stored password and current session cookie, does the same hashing operation and resets the session cookie client-side so it's ready for the next request.

      So the session key changes every request, and each key is only good once.

      Of course, you'd also want to make sure the password doesn't get sent in plaintext on the initial login and isn't stored in plaintext on the server. You usually do that on the server side by generating and saving some random salt for each user and then storing a hash of the password combined with that salt instead of the password itself. Then for your login form, onsubmit you first send just the username to the server in an ajax request to get the user-specific salt (which need not be secret) and a nonce. Then you create the same hash of password+salt in javascript to get the value that's stored on the server, and then you generate a hash of that value combined with the nonce and send that back to the server with the nonce itself. The server makes sure the nonce is valid, then does its own hash of the user's salted password hash it has combined with the nonce and compares that to the value your javascript came up with. If it matches, the password was good and the server sends the initial session cookie.

      (In the ajax request to get the user-specific salt, if the username is invalid you have the server just return a random value that looks like salt. That way an attacker can't tell if they've got a correct username.)

      In this case, you'd store the salted password hash (which the server also knows) client-side and use that to rehash the session key each request.

      For best results, fall back to a traditional session cookie scheme for people without javascript (e.g. if you get a vanilla login form submission at the server instead of the expected ajax hits, flag that session as non-javascript and don't change the session key with each request).

      Won't quite work with OpenID, though. The browser and the server need a shared secret. I guess you could do a Diffie-Hellman key exchange via ajax right after the login. Or just send a random shared secret in a cookie alongside the initial session key and hope no one notices.

      Or use SSL.

      Just thought I'd share that.

      [–]focusfriend 1 point2 points  (1 child)

      sorry, this has been archived and can no longer be voted on

      How about iPhone support?

      [–]HenkPoley 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      It uses the whatwg_db backend there.

      [–]Diastatic 0 points1 point * (1 child)

      sorry, this has been archived and can no longer be voted on

      Excellent script!

      I have got it working via a jquery $.post callback on safari 3.1.2 and firefox 3.0.4. I have a problem with opera 9.26. The only way I can get the store to initialize is if I do an alert() or confirm() right after instantiation. This is a huge kludge. Any ideas on where I might start looking to fix this odd behaviour?

      [–]Diastatic 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Ok, so I've narrowed this down to opera needing to have an event fired off before it will load the stored data. This is very frustrating, because the only solution to this is to apply some hacks.

      [–]alexter 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Perfect! Been looking for exactly this today and PersistJS looks far better than everything else I've found.

      [–]flogic 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      Neat, whats the security on the store though? Similar to cookies?

      [–]pabs[S] 0 points1 point * (0 children)

      sorry, this has been archived and can no longer be voted on

      It depends on the backend; it's same origin for all of them, but the native IE backend is also constrained to the same path (although you can work around this with an iframe shim). The cookie and globalstore backends can be further constrained with the domain parameter, and the cookie backend can be constrained with the path parameter.

      There's a full list of the optional parameters in the README

      The one thing that's really lacking right now is more comprehensive documentation.

      [–]osirisx11 0 points1 point  (3 children)

      sorry, this has been archived and can no longer be voted on

      This is pretty cool.. pabs you should also add window.name support, see http://ajaxian.com/archives/whats-in-a-windowname http://www.thomasfrank.se/sessionvars.html

      [–]pabs[S] 1 point2 points  (2 children)

      sorry, this has been archived and can no longer be voted on

      I don't really think the window.name storage stuff is appropriate for a persistent store, since it goes away when the window is closed.

      [–]osirisx11 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      yeah, good point.. these are both different and powerful new tools. good job on this pabs.

      I'd really like it if there was an easy way to extend and implement new custom storages, say if I wanted to write an interface that uses disk storage, such as used in TiddlyWiki?

      And be able to expand it on another level.. disk storage.. ok what format of disk storage? CSV? XLS? even SQL statements potentially.. Different outputs could be implemented with custom code and possibly XSLT.

      Cheers

      [–]pabs[S] 1 point2 points * (0 children)

      sorry, this has been archived and can no longer be voted on

      Actually there is an undocumented Persist.add() function which allows you to dynamically add custom backends. I didn't include it in the documentation because I wasn't sure if I was going to change it around a bit or not. Here's what the syntax currently looks like:

      Persist.add('my_backend', {
        test: function() {
          // code to test if given backend is available
          return is_available;
        }, 
      
        methods: {
          get: function(key, fn, scope) {
            // code to get value
      
            // call result callback
            if (fn)
              fn.call(scope || this, true, key, val);
          },
      
          set: function(key, val, fn, scope) {
            // code to set value
      
            // call result callback
            if (fn)
              fn.call(scope || this, true, key, val);
          },
      
          remove: function(key, fn, scope) {
            // code to remove value
      
            // call result callback
            if (fn)
              fn.call(scope || this, true, key);
          }
        }
      });
      

      There are also a couple other optional methods: init(), load(), and save(). init() is called whenever a new Persist.Store object is created, and load() and save() are called when the user calls load() and save() on the store object. Any methods you don't define for a backend are set to a default handler which does nothing.

      The one gotcha about Persist.add() is that it affects all stores, regardless of the order in which they were created. In other words, if you create a couple of stores, then add a new backend that the browser supports somewhere later in the code, then the the existing stores will be pointing at the new backend.

      I think this behavior is better than the alternative, which is basically store instances randomly pointing at different backends, but it might catch some people off guard. The safest thing is probably to use Persist.add() and Persist.remove() before creating any Persist.Store instances.

      Anyway, the main reason I didn't document Persist.add() for the initial release is because there isn't a good way to adjust the backend search order yet. When you add a new backend it just blindly places it at the front of the list before all the other backends.

      [–]emullet 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      This looks very cool. Nice project :)

      [–]cstuart 0 points1 point  (5 children)

      sorry, this has been archived and can no longer be voted on

      It fails for me in FF 2.0.0.14 on Leopard. On page load firebug give the following error: Security error" code: "1000

      Disabling firebug doesn't help. It does work on Safari 3.1.1

      Great job though, really exciting stuff.

      [–]pabs[S] 0 points1 point  (4 children)

      sorry, this has been archived and can no longer be voted on

      That's odd, I've been using 2.0.0.14 for testing. Were you using the test page locally or on an external site?

      [–]ehaagwlke 0 points1 point * (0 children)

      sorry, this has been archived and can no longer be voted on

      Hi, I got the same problem too. It works very well in ie6, but a 'Security error" code: "1000'error in firefox.

      I use the test page locally. The code:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <script type='text/javascript' src='persist.js'></script> <script> function sd(){ var store = new Persist.Store('My Data Store'); var data = "pretend this is really long data that won't fit in a cookie"; store.set('saved_data', data); store.get('saved_data', function(ok,val) { if(ok) document.body.innerHTML = val; });

          }
      
          window.onload=function(){
              sd();
          }
      

      </script> </HEAD>

      <BODY> test string <br /> </BODY> </HTML>

      [–]tidal -1 points0 points * (1 child)

      sorry, this has been archived and can no longer be voted on

      Same issues with FF 2.0.0.14 on test-pages >> Security error" code: "1000.

      Problems only occurs locally when pages are loaded directly or with localhost/computer_name as hostname. Does not occur when using 127.0.0.1 or local IP.

      [–]ohashmi 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      I'm also getting this error - it occurs on localhost but not on 127.0.0.1 - unfortunately the page stops processing when this error is received so I cant have the page ignore it in certain cases... would appreciate a prompt set of hints on how to avoid it (maybe the domain restriction settings within the library can fix this?)

      [–]justjeff1 0 points1 point  (2 children)

      sorry, this has been archived and can no longer be voted on

      This is great, perfect timing too for my project. One question -- it appears the script chooses the first successful storage type it can and only stores the info that way. I'm considering altering the script to write to every storage system it can to essentially create "backups" on the user's browser if cookies are cleared, etc. Any reason I shouldn't try that?

      [–]pabs[S] 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      That's an interesting idea. The biggest thing to be aware of is that cookies have far less storage space than the other backends. The other issue is that the IE backend has a same page policy, although the next version will have a way of dealing with that.

      [–]preetipatel 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Which storgae method works for both IE and Firefox and will persist even after you delete regular javascript cookies through the browser?

      [–]sderrick 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      If two or more users are online how do I know who is making the request to determine if that particular user has already cached the data in the local store?

      thanks, Scott

      [–]scottsimpson 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      Offline App Design - I'm working on designing a survey I can have someone access online, then work offline, close and reopen their browser, finish it and post the results online.

      For IE, it seems that as the offline storage is only for one domain, I would need to have the end user do a "save as" and save the online page as a static html file. Then they could open and close the static html file, which could retrieve the data via persistjs calls back into the form and allow saving of updates. Then I could post the page to my web server, authenticate and save the data.

      Anyone got any ideas on alternative design patterns for this. The biggest inconvenience is getting the user to save the page locally, knowing where they saved it and opening it again. I don't see any way round this. Any ideas on making the user experience fairly seamless. Seen any online/offline apps out on the web that do this?

      [–]mikeymckay 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      You wrote this 7 months ago so you have probably moved on - but I am in the same boat. Google Gears allows you to create a manifest file that gets the browser to automatically save required html, css, and js for files that don't change. It all happens transparently and gets associated with a normal URL. I think PersistJS is missing this feature. Does anybody know of a workaround, or should we just use gears?

      [–]ohashmi 0 points1 point  (2 children)

      sorry, this has been archived and can no longer be voted on

      The library is throwing an exception in Google's chrome browser "no suitable storage found" (line 812). This is odd because Chrome is supposed to have gears already.

      I can attempt to fix it myself but would appreciate some tips on how the library's trying to discover gears and what part of the code to try to find a fix in.

      [–]bedney 0 points1 point * (1 child)

      sorry, this has been archived and can no longer be voted on

      ohashmi -

      Even though Chrome has Gears built-in, that only means that you don't have to download the plugin. The invocation machinery should be the same as using Gears from Safari (which the latest version of Gears finally supports).

      In addition I noticed that PersistJS doesn't help you if you don't have a GearsFactory available.

      The only platform differences in Gears are all about creating the 'GearsFactory' differently. Here are the different ways to create the Gears factory (I didn't do browser detection here - you'll have to do that yourself ;-) ):

      if (!google || !google.gears || !google.gears.factory) { google = {}; google.gears = {};

      • Mozilla:

      try { google.gears.factory = new GearsFactory(); } catch (e) { alert("Couldn't create Gears Factory on Mozilla"); }

      • IE:

      try { google.gears.factory = new ActiveXObject('GearsFactory'); } catch (e) { alert("Couldn't create Gears Factory on IE"); }

      • Safari / Chrome:

      try { google.gears.factory = document.createElement('object'); google.gears.factory.style.display = 'none'; google.gears.factory.width = 0; google.gears.factory.height = 0; google.gears.factory.type = 'application/x-googlegears'; document.documentElement.appendChild(google.gears.factory); } catch (e) { alert("Couldn't create Gears Factory on Safari/Chrome"); };

      };

      Cheers,

      • Bill

      [–]bedney 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Sorry for the crappy formatting of that code. My first Reddit post. I'm really not impressed at all :-(.

      Cheers,

      • Bill

      [–]pooh98 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Pabs, I must say persistJS is a great tool. I have successfully implemented it on windows vista with IE 7.0.6 with the data persisting between browser(IE only) session. I am also trying to get it to work on windows vista with firefox version 3.0.1, it stores the data in the browser, but the data does not persist between browser session. Though it works fine on win xp with firefox3. Do you have any idea of how this can be handled? Thanking you in advance.

      [–]pooh98 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      I have successfully used persistJS in IE 7 and firefox 3.0.3. But When I delete the cookies, all the data in the persistent storage gets deleted. Is this a valid behaviour? I need to use persistJS for an application I am developing and I am concerned that the data gets erased when cookies are deleted. Does anybody have any idea how to overcome this problem? Also could anybody please let me know where (on the disk) can you find the data written in the persisent store? can we take backups of this data? Any help will be deeply appreicated. Thank you.

      [–]elklaaso 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Hi,

      FOUND A BUG!:

      I am using PersistJs, but i found a bug in the cookie backend. The get method looks like this:

      get: function(key, val, fn, scope)

      Even the example thats coming with PersistJs does not work with cookie. Because the val parameter needs to be removed, the mothod needs to look like this:

      get: function(key, fn, scope)

      greets

      [–]elklaaso 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      The remove method persist.js does not work for IE, add the following as the first lines in the method remove:

      if(!Array.indexOf){ Array.prototype.indexOf = function(obj){ for(var i=0; i<this.length; i++){ if(this[i]==obj){ return i; } } return -1; } }

      This will add a indexOf method to the javascript Array object, as IE 7 did not implement this.

      [–]pooh98 0 points1 point  (3 children)

      sorry, this has been archived and can no longer be voted on

      Hello there, Are you by any chance addressing the problem which I mentioned below or just reporting errors? In my case firefox is using globalstorage and internet explorer is using "ie" as backend.Then why is the data in the storage destroyed when cookies are deleted? Also where on my hard disk, can I find the data saved on each of this browser. Any help will be deeply appreciated. Thank you guys in advance.

      [–]zarski 0 points1 point  (1 child)

      sorry, this has been archived and can no longer be voted on

      I can confirm this also. However, only in IE 7 does this happen for me. I have tested IE 6, latest Firefox 3.0.x, Safari for Windows ( latest) and they all retain data after cookies are deleted. IE 7 loses its data after cookies are deleted.

      [–]zarski 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      More information here on the IE Blog. Read down where it talks about what happens when "Delete Cookies" is hit. http://blogs.msdn.com/ie/archive/2006/01/12/512232.aspx

      [–]marinalan 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      I would like to have additional method, some way to enumerate all keys of data saved in the store. or load() for all backends, that returns json object with all key/value pairs saved earlier in the store

      [–]3peps 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Goog lib.

      localStorage implemented in FF version 3.5+.

      You can also add support for "Silverlight Isolated Storage" - also a good option when there is no support localStorage.

      [–]aaronhans 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      Beautiful library, thanks pablotron! I found a typo in the localstorage remove method line 479 in version 0.1.0: val = this.getItem(key); should be val = this.store.getItem(key);

      [–]nathanlabenz 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      I would love to use this. Unfortunately, it doesn't seem to work in IE. I loaded up the page and immediately this line threw an error: "Object doesn't support this property or method"


      set:function(key,val,fn,scope){var old_val;key=esc(key);old_val=this.el.set(this.name,key,val)

      [–]anotherJoe90 0 points1 point  (0 children)

      sorry, this has been archived and can no longer be voted on

      The localstorage error/typo is still there in ver 0.2.0, line 42 in the persist-min.js.

      Just replace * val = this.getItem(key); with * val = this.store.getItem(key);

      If you don't you will get the * "Object doesn't support this property or method" error!! Other than that, all OK so far, although a bit more documentation would be nice!!

      [–]soushare -1 points0 points  (0 children)

      sorry, this has been archived and can no longer be voted on

      Just tried this for FF3.6, IE8, and Safari 4. It doesn't work as expected. I created a store = new Persist.Store('test'); and set some key values in it. It worked within one browser. But key values are not shared across browsers. Do you have any specific instructions on how to use the lib?

      Thanks

      [–]3peps -1 points0 points  (0 children)

      sorry, this has been archived and can no longer be voted on

      Good lib!

      localStorage implemented in FF version 3.5+.

      You can also use the options: -Silverlight Isolated Storage -Adobe AIR (datastore)