2014_03_11: it’s progress Jim, but not as we know it

So I spent most of yesterday trying to find what causes my work to crash Safari under iOS7: turns out it’s the gizmo that clusters the CC markers. Not going to cure that in a hurry!

Then I tried for several hours to add the info features from leaflet’s chloropleth/geoJSON example to my script. I got the LAs to highlight on mouseover, but not to de-highlight on mouseout. Nor could I get the data control to pick out data from the LA geoJSON file.

So I reasoned ‘if I can’t add their stuff to mine, can I add my stuff to theirs?’ That is, could I swap in my LA and CC data sets and use leaflet’s code to colour them and pick out data to be displayed in their external control? This seemed to go OK until I added in the geocoder (the bit for entering an address to zoom to that area of the map. This code failed, so everything that should have been processed after it wasn’t even reached.

I went back to trying to add leaflet’s functions to my otherwise functional code. Still no joy.

I refactored my code so it was in a more logical order:

  1. preparatory functions,
  2. drawing basic map
  3. adding scale, geocoder, reset and help controls to map
  4. adding LA data layer
  5. adding CC data layer
  6. adding layers on/off control

and made the reset control call a URL from a simple configuration file, so that when the client actually puts this work online, they only need to update the configuration file, not hack around in the reset script.

I still couldn’t get the mouseout bit to work. I knew this code was being called: if I replaced it with document.write(“rude word”); then rude words were written.

So this evening I revisited leaflet’s example, determined to get it to work. This example has all the functionality built into a script in the html file, not a separate ‘external’ script. Not really the way I want but I’m running out of time…

I realised that the geocoder was being called but just failing somewhere. I’m not sure how I worked it out but the fail point was that geocoder calls a function in my main external script to limit its searches to Scotland – the same bounds as are applied to my map. (Without this search-area limiting, searching for EH10 postcodes shows Walthamstow.) But this script is never invoked, so the function isn’t callable. So instead of calling that function, I’ve copied it into the geocoder. Now that works! And so do all the other bits. I can make the reset script call the configuration file, so long as they are in the right order in the html header (i.e. configuration before the reset function that depends on it – so perhaps the issue was that the geocoder was calling the main script before it was available.

There was another wrinkle adding in the CC marker code. Something doesn’t like a variable called location. Changing that to ccLocation worked.

So here is the whole lot working – but with the javascript embedded in the HTML.

My task for tomorrow is to get the javascript into a separate file, so that this works, cos right now it doesn’t. Then write some documentation, then write a talk for the OKFN meet-up tomorrow.

2014_03_10

Added reset button

It’s another hack down of the OSMGeocoder control, mostly because I don’t have time to understand how to create a control from scratch. The main fault with it is that it relies on

inner.innerHTML = “<a href=\”http://localhost:8888/realISV22\”><img src = \”css/images/reset.png\”></a>”;

The bold bit will need to be replaced with the real URL for wherever the site will be used.

2014_02_20 more LA boundary progress

I spent a while today trying to drop a marker at the user’s entered location. It’s easy to do on(zoomed) add marker but removing it at the next zoom is so far beyond me. Back to fighting with LA borders – the theatre of battle being styling them

I knew from leaflet’s example that leaflet does style geoJSON – so the issue must have been with my geoJSON files. When in doubt, copy: I copied leaflets’ code for colouring US state geoJSON data, substituted in the Scottish LA names and a piece to colour them by code rather than population density, and lo and behold it works.

Truth – it took a while to isolate the co-ordinate lines, so I’m only a wee way into substituting in the LA co-ordinates. But here’s the proof:

Screen Shot 2014-02-20 at 22.51.16

2014_02_16: progress

So after ac couple of days of literature reviewing, and spending Saturday being social, I was back at the code-face today.

Task 1: understand – and maybe cure – the failing geocoder

Entering single-initial letter postcodes such as EH3 7PX works – the map zooms to the right place. Entering textual places such as Merchiston, Leith Links, Macmerry and Dalry also works. But EH10 5DT still appears to be in Walthamstow, instead of Merchiston. EH12 6AP appears to be slightly east of Walthamstow, instead of near Murrayfield.

I noticed that EH10 5DT and E10 5DT both give the same place (in east London), as do EH12 6AP and E12 6AP. So Nominatim is omitting the H in some cases. Interestingly, the geocoder works with Macmerry’s postcode (EH33 1PL).

To see whether it was my fault, I created a stripped-down version from scratch: the javascript contains just the map declaration, the code to fill it with tiles and the geocoder. Same result – so it’s the geocoder, not my code. I feel far less guilty but I’ll need to fix this.

Task 2: understand how leaflet.js handles geoJSON files

I worked my way through http://leafletjs.com/examples/geojson.html. I got most of it to work, except for styling the output. I then got a trial LA boundary to work – this trial had 4 co-ordinates. If it will work for four, it will work for many, many more – but will take longer.

Task 3: make geoJSON files of LA boundaries

With thanks to a Leaflet mailing list member for some sage advice, I’ve installed QGIS. This could open the 18-month old UK local authorities file I obtained from https://www.sharegeo.ac.uk/handle/10672/305. (It couldn’t handle the .sld files I obtained from the Ordnance Survey.) The way I worked – there may well be better ways – was to select an LA, then do Layer > Save selection as a vector file with options

  • format = geoJSON
  • CRS =  WGS84/EPSG4326

It took a while to work out the correct CRS option. I was surprised it wasn’t WGS84/PseudoMercator/EPSG3857 because that appears to be Leaflet’s default CRD. Then again, what do I know about converting points on am irregular 3D surface to points on a flat plane?

Anyway, that gave me 32 nice geoJSON files in a little less than 2 hours.

Task 4: display LA boundaries

Using my stripped-down version of the code, I added in 32 routines to display the LA boundaries. They were still in the default blue – remember I’d not cracked styling them. There may be an advantage to separate routines and data files. If an LA ever changes, I’d just need to make new geoJSON files for that LA and its neighbours, and each can be coloured (if this ever works!) separately. Anyway, by adding var = <LA_name> [ to the beginning of each file and ]; to the end of each, then appropriately commenting off all routines except for the LA I was testing, I made sure each displayed OK.

I then tried a few methods to programatically assemble the files into one huge array of the form var laBoundaryData = [ [content of first geojson file], [content of second geojson file], ….[content of last geojson file] ];  Another hour down the pan and no joy, so I did it the hard way, copying and pasting the contents of the geoJSON files into
var laBoundaryData = [
],
[
], 
[
]
];

It almost worked straight off – all the LAs apart from Shetland and Scottish Borders displayed as they should. Shetland and Scottish Borders had some weird horizontal lines, but removing them from the huge file, then replacing their code from their individual geoJSON files got rid of these nasty artefacts. I guess I had pasted the code in slightly the wrong place first time round.

Then the code for displaying the LAs is just a simple traversal of the array of LA boundary data. And all this without going anywhere near the command line.

So with my map displaying all LA boundaries, it was time for…

Task 5: putting it all back together

I’d thought this would be easy – just replace the code lumps for calculating the map centre, its bounds and displaying the CCs. Not a bit of it! Failure points included not calling the data, scripts and even the css in the right order, the functions for calculating centres and bounds not being called properly – aarrgh. Anyway after a couple of hours, it’s all there. It’s slow (I guess need to simplify the LA shapes before writing them to geoJSON format), the geocoder is still a mystery but it works. Yeehah!

The initial result

The initial result

zoomed into the West End of Edinburgh - see the markers for individual CCs

zoomed into the West End of Edinburgh – see the markers for individual CCs

 

My reward for all that – 2 more hours doing stuff to a real CC’s website!

 

2014_02_09

So I’ve given up on the polygons for now. In fact, I’ve received some advice in response to an online plea for LatLong shape files for Scottish LAs but I won’t be able to look into this until Tuesday afternoon.

So today on with the show of drawing a map with markers for all CCs for which I have LatLong data. This should have been easy – I’d had something very like this working for 2 CCs already, with different coloured markers for whether the CC had both website and email address, just an email address, no electronic contact details or no actual functionality.

I started by knocking up some css and a disclaimer/copyright page and some custom markers for functional and non-functional CCs – easy, if not the prettiest thing ever. Then I followed the recipe for displaying a couple of LAs’ CCs (without differentiating between functional and non-functional), with the markers for each LA coalescing when zooming out from the map.

All fine, until I noticed the numbers in the coalescences were not correct – there should have been 19 CCs in Aberdeen and 71 in Aberdeenshire, but while Aberdeen was correct, Aberdeenshire had 90 CCs, so the markers for Aberdeen were presumable adding to the Aberdeenshire set.

I then added in Angus CCs, and got even more confusing numbers. I battled with this for several hours, even stripping the code right down to for each CC in the whole dataset, document.write(“rude word”); No joy.

So this is where my personal life affects my work life – I went to my regular sunday evening spin class. I started again about 8:30 and within 30 minutes, I had it properly working numbers for 3 CCs. 29 fairly tedious additions to a case statement and checks that the right numbers appeared, all 32 LAs’ CCs were appearing correctly.

A quick hack to one LA got me green marked for functional CCs and red marked for non-functional ones, with each LAs’ own CCs coalescing into one lump no matter what colour they were.

Then half an hour’s web-trawling got each LA’s CCs’ markers displaying popups linking to the relevant LA web pages. Job done!

So entry to the page draws a map of Scotland, with all CCs for which we have LatLong data coalesced into lumps that show the number of CCs in each coalescence. Zooming in, or clicking on a coalescence de-coalescesces so that markers for individual CCs display. A marker is green if the CC is functional and red if it isn’t. Each marker has a popup with the name of the CC and a link to the relevant LA’s webpages about its CCs. Entering a postcode or address in the search box zooms to that place, so you can see the CCs around it. (You may need to zoom out a little.) We will draw a discrete veil over the question of how good the LatLong data I’m currently working with is – not my problem!

Still to do

  • display LA boundaries
  • get the search box to drop a marker
  • optionally, calculate the distance to the nearest CC
  • optionally, calculate the distance to the nearest functional CC
  • be able to switch on and off each LA’s markers, using leaflet.js’s layers functionality
  • optionally, to calculate distances to the nearest (functional) CC in an LA if only one is switched one
  • write a hacker-guide
  • style links in <h1>s

Getting there!

2014_02_06 encore

I couldn’t leave it alone this evening – 5 hours after I got home and I’ve done the 6 LAs on Scotland’s mid-east coast. The wee bit that was missing from Aberdeen has been restored. (I processed that dataset again and the missing points magically reappeared. So here it is in glorious technicolour:

Screen Shot 2014-02-07 at 04.46.30

The points are very close to the LA boundaries on OpenStreetMap tiles, which is quite encouraging. The dashed line is OpenStreetMap and the solid line is Leaflet’s rendering of the converted data.

Screen Shot 2014-02-07 at 04.46.12

Fife is a 4-part multipolygon, that is there are four polygons in the bits that represent Fife. I guess these are the Isle of May, Inchkeith and Inchcolm. Each part of a multi polygon requires separate processing via the hero of the hour(s), http://gridreferencefinder.com/batchConvert/batchConvert.php.

So I’m dreading doing Shetland, Orkney and the Western Isles. But perhaps they don’t need to be marked or coloured because they are clearly separate from the mainland.

Less heroic have been Mac TextEdit (no RegEx), TextMate (one successful RegEx, then fell over and won’t stop trying to process a long finished-with Angus file) and Word (it has done most of the heavy kiting but has fallen over at least 10 times). I’ll forgive Eclipse for chugging away with RegExes very slowly but I won’t forgive it for completing the RegEx then hanging so I can’t save the result.

The optimal process seems to be

  1. Open the original data file in Word.
  2. Find any sub-polygons, by replacing  ] ], [ [ with multiple <new line>s.
  3. Save.
  4. Grep ], [ with ,<new line>
  5. Save.
  6. Get rid of the dross at the start and end of the of the file, so that I’m left with just sets of [number,number],<new line>[number,number], …[number,number],<new line>[number,number].
  7. Save.
  8. Manually copy and paste the first set into the heroic web page, and tell it to convert. If it moans, there is more than one set in what I’ve copied, so go back and sort it out. At this point, Word will fall over – hence the multiple saves,
  9. When a clean data set is in the hero, it will convert the data to lines containing some unwanted blurb and the data in LatLong format.
  10. Copy that bit to a new TextEdit file called <LA-name>.js, then leave some spaces.
  11. Convert the next data set, i.e the next polygon in the multipolygon.
  12. Copy and paste that data into the TextEdit file.
  13. Repeat steps 8-12 until all polygons are in the TextEdit file. Save and close it.
  14. Open it in Eclipse. Do the RegEx to remove the unwanted blurb. (To play it safe, do a few hundred lines at a time, saving each time.
  15. Save and close the file – Eclipse is about to fall over.
  16. Open the file in Word again, then replace all multiple new lines with a suitable swearword.
  17. Replace all new lines with ], [
  18. Replace the swearwords with ], [
  19. Top and tail the file so that it has the format var <LAname>  = [ [ [number, number], … [number, number] ],  [ [number, number], … [number, number] ], …  [ [number, number], … [number, number] ] ]; 
  20. Save it in the right place in the website data structure, add the necessary call to index.html’s head and the necessary Leaflet call to drawMap.js.
  21. Open the web page and draw the map.
  22. Fix the colours in drawMap.js
  23. Move on to the next LA!

Progress update

Monday saw a few more baby steps into JavaScript and leaflet, then I met with a CC chair who wants to set up a website for his CC. He now has a functional site he can show his colleagues and understands more about making posts, adding static pages, tags and categories. I need to write him a guide to the menu items in WordPress – this could be the basis of a section for the good practice guide I intend to create.

Continue reading