For a very long time now I have been planning to update my old list webapp.
I made the original maybe 5 years ago, before I found Wunderlist and other list apps. The original app was a very simple php server/client, no ajax app. And even though I have tried other apps along the years, it has served me well for a long time.
It has been very neglected over the years, and at some point the login stopped working because I updated the shared user database, but forgot to fix the app. This meant it only worked with an autologin url I had saved. I did an ajax version a few years ago, but after I got the initial tech demo working, I lost interest and never got it finished.
I have also been very unmotivated to code anything for maybe 3 years or so. Even though I have planned a lot of different things, I have never quite gotten around to actually doing anything outside work and other "mandatory" projects.
Anyway, when we had a "databases and webprogramming" class in school, and I had to make up my own project on account of being way ahead of everyone else, I decided to finally do my HTML5 version of the list app. I had been planning the app for about a year and a half, so I had a fairly good idea of where to start.
The first requirement of the app was that it had to allow a sync mechanism separate from the frontend. This is because I'm planning to make a native android version with the same sync backend.
The second requirement was that it had to function 100% within the listview without a net connection. This is because often when I shop, I'm speaking to someone on the phone, and for some strange reason there is almost never a 3G connection inside shops. I really can't figure that one out, since just about everywhere else has 3G or 4G connections.
The third requirement was that it had to allow unlimited clients using the same list at the same time, with or without a net connection.
The approach I used to acheive all this was to have the lists stored in a localStorage key as a JSON object. The frontend draws the HTML based on this, and the backend syncs with the JSON object.
I also timecoded 4 user editable parts per item (status, value, category and sort order), so that every time any one part is changed, that part get a new timecode. That way different clients can update different parts of the same list item and have all the changes synced to all clients.
Initially I only had the listview draw client side, and you had to be only to switch to a different list. But I quickly realized that it wouldn't be much harder to have it draw the index and the lists client side, so that you can freely switch between lists without a net connection. This is actually very useful, as the app is designed to work on really bad connections.
I still draw some of the views server side, like the login and settings. These views are not used very often, and still needs to use the server to read or write data, so there would be almost no gain by doing them client side.
As long as you have loaded the index page, and synced the lists once, there is no UI element that depends on a server request, as long as you don't go into settings. This means that the speed of your connection doesn't impact the performance of the UI.
One feature that was also very important was that I wanted an autologin feature. For the old list I used a simple autologin url that hashed the user id and the password hash and passed that along with the user id. This was of course a very insecure way of doing it, but quite convenient.
The autologin, and the fact that I wanted to make a native android client later meant that I decided against using php sessions to track users. The solution I used instead was to write a cookie containing the uuid of the user, the timestamp when the cookie was written, the amount of time in seconds the token is valid and a hash of all these combined with the password hash.
This token is used to authenticate the user on the server, and a new token with the same valid duration is returned to the client and saved as a cookie. I beleive that this is a more secure way of doing long sessions, but I might be wrong. If the tokens are captured they expire after their validity period, but of course anyone who managed to capture a token can always get it refreshed. I considered having the tokens expire after one use, but I haven't yet figured out a way to do that in a smart way.
The project have been quite fun, and I have learned a bit more javascript techniques and practices. I have also gotten quite a bit more inspiration to code during my "free time". I have gotten quite a few hours done on the project in the evenings.
If anyone want to read the code, or follow the project, it can be found at: https://bitbucket.org/schonben/list
At the moment of writing, the beta branch is the best branch to view, as I haven't yet "published" to the master, and the dev branch might not always work, I tend to break that one quite often.
The app itself can be found on http://list.beta.uplink.fi, and later on http://list.uplink.fi, but that still holds the old version.