Include layers in hash
authorJohn Firebaugh <john.firebaugh@gmail.com>
Wed, 24 Jul 2013 22:23:19 +0000 (15:23 -0700)
committerJohn Firebaugh <john.firebaugh@gmail.com>
Tue, 30 Jul 2013 22:41:41 +0000 (15:41 -0700)
app/assets/javascripts/application.js
app/assets/javascripts/index.js
app/assets/javascripts/index/browse.js
app/assets/javascripts/index/notes.js.erb
app/assets/javascripts/leaflet.extend.js.erb
app/assets/javascripts/osm.js.erb
app/controllers/site_controller.rb
test/functional/site_controller_test.rb

index c8577f7c3f7e6529683ac3bd296da1affa071f1e..cbea58cc17628bc6f4daf90c432c635f8546df67 100644 (file)
@@ -4,6 +4,7 @@
 //= require jquery.cookie
 //= require jquery.throttle-debounce
 //= require augment
+//= require osm
 //= require leaflet
 //= require leaflet.osm
 //= require leaflet.hash
@@ -12,7 +13,6 @@
 //= require leaflet.locationfilter
 //= require i18n/translations
 //= require oauth
-//= require osm
 //= require piwik
 //= require map
 //= require menu
@@ -61,17 +61,27 @@ function remoteEditHandler(bbox, select) {
  */
 function updatelinks(loc, zoom, layers, bounds, object) {
   $(".geolink").each(function(index, link) {
-    var base = link.href.split('?')[0],
+    var href = link.href.split(/[?#]/)[0],
         args = querystring.parse(link.search.substring(1));
 
     if (bounds && $(link).hasClass("bbox")) args.bbox = normalBounds(bounds).toBBoxString();
-    if (layers && $(link).hasClass("layers")) args.layers = layers;
     if (object && $(link).hasClass("object")) args[object.type] = object.id;
 
-    var href = base + '?' + querystring.stringify(args);
+    var query = querystring.stringify(args);
+    if (query) href += '?' + query;
 
     if ($(link).hasClass("llz")) {
-      href += OSM.formatHash({lat: loc.lat, lon: loc.lon || loc.lng, zoom: zoom});
+      args = {
+        lat: loc.lat,
+        lon: loc.lon || loc.lng,
+        zoom: zoom
+      };
+
+      if (layers && $(link).hasClass("layers")) {
+        args.layers = layers;
+      }
+
+      href += OSM.formatHash(args);
     }
 
     link.href = href;
index 452cc0bca821d1ba5d64374f3aa9875fd4d6735c..19e1f16de8ebd3b3a596fd5bbc95a7eb4b92c24a 100644 (file)
@@ -19,7 +19,7 @@ $(document).ready(function () {
 
   map.attributionControl.setPrefix('');
 
-  new L.Hash(map);
+  map.hash = L.hash(map);
 
   var layers = [
     new L.OSM.Mapnik({
@@ -50,8 +50,11 @@ $(document).ready(function () {
 
   layers[0].addTo(map);
 
-  map.noteLayer = new L.LayerGroup({code: 'N'});
+  map.noteLayer = new L.LayerGroup();
+  map.noteLayer.options = {code: 'N'};
+
   map.dataLayer = new L.OSM.DataLayer(null);
+  map.dataLayer.options.code = 'D';
 
   $("#sidebar").on("opened closed", function () {
     map.invalidateSize();
@@ -161,8 +164,8 @@ $(document).ready(function () {
   }
 
   initializeExport(map);
-  initializeBrowse(map);
-  initializeNotes(map);
+  initializeBrowse(map, params);
+  initializeNotes(map, params);
 });
 
 function updateLocation() {
@@ -174,6 +177,9 @@ function updateLocation() {
   var expiry = new Date();
   expiry.setYear(expiry.getFullYear() + 10);
   $.cookie("_osm_location", cookieContent(this), { expires: expiry });
+
+  // Trigger hash update on layer changes.
+  this.hash.onMapMove();
 }
 
 function setPositionLink(map) {
index 49090f69cfe1a3a0b3742867d2bdb4d224e3cdca..a9bdbf2b7fac290dd561b9ac1e31b8396d8763ee 100644 (file)
@@ -2,7 +2,7 @@
 //= require templates/browse/feature_list
 //= require templates/browse/feature_history
 
-function initializeBrowse(map) {
+function initializeBrowse(map, params) {
   var browseBounds;
   var layersById;
   var selectedLayer;
@@ -49,6 +49,12 @@ function initializeBrowse(map) {
     }
   });
 
+  if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
+    if (params.layers.indexOf(dataLayer.options.code) >= 0) {
+      map.addLayer(dataLayer);
+    }
+  }
+
   function startBrowse(sidebarHtml) {
     locationFilter = new L.LocationFilter({
       enableButton: false,
index 012538e1d2a4bf98b887773837450b6b2ed343b6..93b60c3e7a09f6c1e907a36e5f71afb7579bba45 100644 (file)
@@ -1,9 +1,8 @@
 //= require templates/notes/show
 //= require templates/notes/new
 
-function initializeNotes(map) {
-  var params = OSM.mapParams(),
-      noteLayer = map.noteLayer,
+function initializeNotes(map, params) {
+  var noteLayer = map.noteLayer,
       notes = {},
       newNote;
 
@@ -50,7 +49,7 @@ function initializeNotes(map) {
   });
 
   if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
-    if (params.notes || (params.layers && params.layers.indexOf('N')) >= 0) {
+    if (params.layers.indexOf(noteLayer.options.code) >= 0) {
       map.addLayer(noteLayer);
     }
 
index 84ad92920e41c959d40d98dcf5be62060777b9c0..a50df013e51799871b0f845744a3044c15c9e605 100644 (file)
@@ -30,15 +30,21 @@ L.extend(L.Map.prototype, {
 
   getUrl: function(marker) {
     var precision = zoomPrecision(this.getZoom()),
-        params = { layers: this.getLayersCode() };
+        params = {};
 
     if (marker && this.hasLayer(marker)) {
       params.mlat = marker.getLatLng().lat.toFixed(precision);
       params.mlon = marker.getLatLng().lng.toFixed(precision);
     }
 
-    return 'http://' + OSM.SERVER_URL + '/?' + querystring.stringify(params) +
-      OSM.formatHash({lat: this.getCenter().lat, lon: this.getCenter().lng, zoom: this.getZoom()});
+    var url = 'http://' + OSM.SERVER_URL + '/',
+      query = querystring.stringify(params),
+      hash = OSM.formatHash(this);
+
+    if (query) url += '?' + query;
+    if (hash) url += hash;
+
+    return url;
   },
 
   getShortUrl: function(marker) {
@@ -87,3 +93,6 @@ L.extend(L.Map.prototype, {
 });
 
 L.Icon.Default.imagePath = <%= "#{asset_prefix}/images".to_json %>;
+
+L.Hash.prototype.parseHash = OSM.parseHash;
+L.Hash.prototype.formatHash = OSM.formatHash;
index 5343b039cc8d6e82f3e4875a8e4cc1a3b06b398b..409cda8d84fd51426c0a0e93feda73a297e38d80 100644 (file)
@@ -41,10 +41,6 @@ OSM = {
       mapParams.mlat = parseFloat(params.mlat);
     }
 
-    if (params.layers) {
-      mapParams.layers = params.layers;
-    }
-
     if (params.node || params.way || params.relation) {
       mapParams.object_zoom = true;
 
@@ -76,9 +72,10 @@ OSM = {
       mapParams.box = bounds;
     }
 
+    var hash = OSM.parseHash(location.hash);
+
     // Decide on a map starting position. Various ways of doing this.
-    var hash = L.Hash.parseHash(location.hash);
-    if (hash) {
+    if (hash.lat && hash.lon) {
       mapParams.lon = hash.center.lng;
       mapParams.lat = hash.center.lat;
       mapParams.zoom = hash.zoom;
@@ -101,7 +98,6 @@ OSM = {
       mapParams.lon = parseFloat(loc[0]);
       mapParams.lat = parseFloat(loc[1]);
       mapParams.zoom = parseInt(loc[2]);
-      mapParams.layers = loc[3];
     } else if (OSM.home) {
       mapParams.lon = OSM.home.lon;
       mapParams.lat = OSM.home.lat;
@@ -118,7 +114,7 @@ OSM = {
       mapParams.zoom = parseInt(params.zoom || 5);
     }
 
-    mapParams.notes = params.notes == "yes";
+    mapParams.layers = hash.layers || (loc && loc[3]) || '';
 
     if (params.note) {
       mapParams.note = parseInt(params.note);
@@ -132,10 +128,39 @@ OSM = {
     return mapParams;
   },
 
+  parseHash: function(hash) {
+    if (hash.indexOf('#') === 0) {
+      hash = hash.substr(1);
+    }
+    hash = querystring.parse(hash);
+    var args = L.Hash.parseHash(hash.map || '') || {};
+    if (hash.layers) args.layers = hash.layers;
+    return args;
+  },
+
   formatHash: function(args) {
-    var precision = zoomPrecision(args.zoom);
-    return '#' + args.zoom +
-           '/' + args.lat.toFixed(precision) +
-           '/' + args.lon.toFixed(precision);
+    if (args instanceof L.Map) {
+      args = {
+        lat: args.getCenter().lat,
+        lon: args.getCenter().lng,
+        zoom: args.getZoom(),
+        layers: args.getLayersCode()
+      };
+    }
+
+    var precision = zoomPrecision(args.zoom),
+      hash = '#map=' + args.zoom +
+        '/' + args.lat.toFixed(precision) +
+        '/' + args.lon.toFixed(precision);
+
+    if (args.layers) {
+      args.layers = args.layers.replace('M', '');
+    }
+
+    if (args.layers) {
+      hash += '&layers=' + args.layers;
+    }
+
+    return hash;
   }
 };
index c16daf37facb7ff7e2ac64ebe267d988be6cf874..b1239d0daa5f16e493e46a2568144d3fbd4dbf07 100644 (file)
@@ -8,9 +8,20 @@ class SiteController < ApplicationController
   before_filter :require_oauth, :only => [:index]
 
   def index
+    anchor = []
+
     if params[:lat] && params[:lon]
-      params[:anchor] = "#{params.delete(:zoom) || 5}/#{params.delete(:lat)}/#{params.delete(:lon)}"
-      redirect_to params
+      anchor << "map=#{params.delete(:zoom) || 5}/#{params.delete(:lat)}/#{params.delete(:lon)}"
+    end
+
+    if params[:layers]
+      anchor << "layers=#{params.delete(:layers)}"
+    elsif params.delete(:notes) == 'yes'
+      anchor << "layers=N"
+    end
+
+    if anchor.present?
+      redirect_to params.merge(:anchor => anchor.join('&'))
       return
     end
 
index 145805c01f273ae92f42dbbe08bc117bd7af1a93..23e6c27a375383bd57069b0d155e4aea5729b671 100644 (file)
@@ -75,10 +75,19 @@ class SiteControllerTest < ActionController::TestCase
 
   def test_index_redirect
     get :index, :lat => 4, :lon => 5
-    assert_redirected_to :controller => :site, :action => 'index', :anchor => '5/4/5'
+    assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=5/4/5'
 
     get :index, :lat => 4, :lon => 5, :zoom => 3
-    assert_redirected_to :controller => :site, :action => 'index', :anchor => '3/4/5'
+    assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=3/4/5'
+
+    get :index, :layers => 'T'
+    assert_redirected_to :controller => :site, :action => 'index', :anchor => 'layers=T'
+
+    get :index, :notes => 'yes'
+    assert_redirected_to :controller => :site, :action => 'index', :anchor => 'layers=N'
+
+    get :index, :lat => 4, :lon => 5, :zoom => 3, :layers => 'T'
+    assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=3/4/5&layers=T'
   end
 
   def test_permalink