Local markers in cookies with leaflet
Last night I got an idea: start implementing some stuff on top of Elevation. The first thing I thought of was the ability to save markers in cookies, and to recover them every time the map was accessed. This would allow anybody to safely add personal markers on top of it without having to trust me (except for the map service). This might lead to something else entirely later, but for now that was the goal.
So the first step was to find out how to access cookies in js. It seems that
there is no native way to do it, and you have to parse them for yourself from
the document.cookie
attribute. Luckily someone already wrote some code for
it. There was no license, but I
think it's ok. Then I added another function to have a list of all the cookies
whose name starts with some prefix, based on the readCookie()
function:
function readCookies(prefix) { var nameEQ = prefix + '_'; var ca = document.cookie.split(';'); var ans = []; j= 0; for (var i = 0; i < ca.length; i++) { var index = 0; var c = ca[i]; while (c.charAt(index) == ' ') { index = index + 1; } if (c.indexOf(nameEQ) == index) { // keep reading, find the = while (c.charAt(index) != '=') { index = index + 1; } ans[j] = c.substring(index + 1, c.length); j= j+1; } } return ans; }
The next step was to encode and decode markers into strings. The format I
decided is simple: CSV, lat,lon,text,URL
. So, here's the function that
converts cookies to markers:
function markersFromCookies () { var cookies= readCookies ("marker"); for (var i= 0; i<cookies.length; i++) { var cookie= cookies[i]; var data= cookie.split (','); // it's lat,lon,text,url var marker= L.marker([data[0], data[1]]).addTo (map); // TODO: reconstruct the url in case it got split if (data[3].length>0) { marker.bindPopup ('<a href="'+data[3]+'">'+data[2]+'</a>').openPopup (); } else { marker.bindPopup (data[2]).openPopup (); } } }
20 lines of code and there already is a TODO comment :) That's because URLs can have commas in them, but for the moment I'm thinking in short URLs from sites like bitly.
All this was working perfectly in Firefox' scratchpad. Then I decided to put it in "production". For that I took all the js from the original page and put it in a file, along with all these functions, I removed the permanent marker from my map, converting it into a cookie, pushed the code, reloaded and... it broke.
This is not the first time I see js fall apart. Last year I helped PyCon.ar's organization with the site, specifically the map showing the city with markers for the venue and the bus station. I even had to map the venue because it was not in OSM's data :) If you follow that link, you'll see that the popups are completely broken. These things were working perfectly in vacuum, but when I integrated it into the page it just fell apart. I never found out why.
In my current situation, if I try to run markersFromCookies()
in scratchpad,
this is what I get:
Exception: t.addLayer is not a function o.Marker<.addTo@http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js:7 markersFromCookies@http://grulicueva.homenet.org/~mdione/Elevation/local.js:59 @Scratchpad/1:1
Basically, that's the call to L.marker().addTo()
. Maybe the constructor is not
working anymore, maybe something else entirely. At least this time a dim light
in the back of my head told me maybe the map
variable is not global as it
seems to be from scratchpad, so I simply passed the map from setup_map()
to
markersFromCookies()
and now it works. Notice that the error message never
mentioned this fact but something else entirely. I'm just glad I didn't have to
follow the hint and debug Leaflet's to find out this. All I hope now is that
I don't go insane with this small project.
Next steps: adding new markers and sharing!