blacklight-maps 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +120 -42
  4. data/app/assets/javascripts/blacklight-maps.js +1 -2
  5. data/app/assets/javascripts/blacklight-maps/blacklight-maps-browse.js +122 -96
  6. data/app/assets/stylesheets/blacklight_maps/blacklight-maps.css.scss +5 -1
  7. data/app/assets/stylesheets/blacklight_maps/default.css.scss +74 -12
  8. data/app/helpers/blacklight/blacklight_maps_helper_behavior.rb +125 -0
  9. data/app/helpers/blacklight_maps_helper.rb +1 -24
  10. data/app/views/catalog/_document_maps.html.erb +1 -3
  11. data/app/views/catalog/_index_map.html.erb +7 -0
  12. data/app/views/catalog/_map_placename_search.html.erb +8 -0
  13. data/app/views/catalog/_map_spatial_search.html.erb +6 -0
  14. data/app/views/catalog/_show_maplet_default.html.erb +11 -0
  15. data/app/views/catalog/map.html.erb +8 -0
  16. data/blacklight-maps.gemspec +1 -2
  17. data/config/locales/blacklight-maps.en.yml +17 -1
  18. data/config/routes.rb +2 -2
  19. data/docs/blacklight-maps_index-view.png +0 -0
  20. data/docs/blacklight-maps_map-view.png +0 -0
  21. data/docs/blacklight-maps_search-control.png +0 -0
  22. data/docs/blacklight-maps_show-view.png +0 -0
  23. data/lib/blacklight/maps.rb +16 -0
  24. data/lib/blacklight/maps/controller_override.rb +33 -0
  25. data/lib/blacklight/maps/engine.rb +14 -6
  26. data/lib/blacklight/maps/export.rb +102 -61
  27. data/lib/blacklight/maps/render_constraints_override.rb +62 -0
  28. data/lib/blacklight/maps/version.rb +1 -1
  29. data/lib/generators/blacklight_maps/templates/blacklight_maps.css.scss +1 -1
  30. data/solr_conf/conf/schema.xml +4 -1
  31. data/spec/controllers/catalog_controller_spec.rb +22 -0
  32. data/spec/features/maps_spec.rb +194 -61
  33. data/spec/fixtures/sample_solr_documents.yml +73 -72
  34. data/spec/helpers/blacklight_maps_helper_spec.rb +134 -12
  35. data/spec/lib/blacklight/maps/controller_override_spec.rb +34 -0
  36. data/spec/lib/blacklight/maps/export_spec.rb +178 -35
  37. data/spec/lib/blacklight/maps/render_constraints_override_spec.rb +95 -0
  38. data/spec/spec_helper.rb +1 -1
  39. data/spec/test_app_templates/Gemfile.extra +0 -2
  40. metadata +22 -21
  41. data/app/views/catalog/_index_maps.html.erb +0 -9
  42. data/docs/map-sidebar.png +0 -0
  43. data/docs/map-view.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: acbcc33561dd5699830f9737e8b4dcb876f710ab
4
- data.tar.gz: dea0549de23c5ce92351f4b9838db60c8adf6359
3
+ metadata.gz: e7059d890824c42ab380fe30f134bbe80c6aec34
4
+ data.tar.gz: 0ce93e925097ef9a696d19722d60a46210a0130f
5
5
  SHA512:
6
- metadata.gz: 3e88613aede3859941d6789b68739ec39cb81a3962a3248b2527cab1c727312ab1e25eff02abe5da231e4ea2584ed3524646e9cee12a722abdc292c2467310b8
7
- data.tar.gz: 048ce9b3544f60cd889f547b56565561e94919b1a639178a1cc8a41c1d183ca7258b0b3947f54cce6e3b502d80ab75122998d60ed9776e1ab9ca357528cda8ef
6
+ metadata.gz: e38b41d52c15e1194bb858fd74a5f121e859d41e5c2e5c2063a1ea03d4761c64a5688443d527723fb274f13481292fb77008a6a3c987113cc7e3116e03538f19
7
+ data.tar.gz: 0f5bb334cea790bd339f408e00daf1100ecc8678adb011be8a72481a498274271eecb976b4e504f3381d7f7a71db8027ea541ed0e2a4aa59a46144605d212b53
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ tmp
18
18
  spec/internal
19
19
  jetty
20
20
  .DS_Store
21
+ .idea/
data/README.md CHANGED
@@ -2,10 +2,16 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/sul-dlss/blacklight-maps.png?branch=master)](https://travis-ci.org/sul-dlss/blacklight-maps)
4
4
 
5
- Provides a map view for Blacklight search results.
5
+ Provides map views for Blacklight for items with geospatial coordinate (latitude/longitude) metadata.
6
6
 
7
- ![Screen shot](docs/map-view.png)
8
- ![Screen shot](docs/map-sidebar.png)
7
+ Browse all records by 'Map' view:
8
+ ![Screen shot](docs/blacklight-maps_map-view.png)
9
+
10
+ Map results view for search results (coordinate data as facet):
11
+ ![Screen shot](docs/blacklight-maps_index-view.png)
12
+
13
+ Maplet widget in item detail view:
14
+ ![Screen shot](docs/blacklight-maps_show-view.png)
9
15
 
10
16
  ## Installation
11
17
 
@@ -27,69 +33,141 @@ Run Blacklight-Maps generator:
27
33
 
28
34
  ## Usage
29
35
 
30
- Blacklight-Maps adds a map view capability for a results set that contains geospatial coordinates (latitude/longitude).
36
+ Blacklight-Maps integrates [Leaflet](http://leafletjs.com/) to add map view capabilities for items with geospatial data in their corresponding Solr record.
31
37
 
32
- For now, Blacklight-Maps requires that your Solr index include one of the following two types of fields:
38
+ In the map views, locations are represented as markers (or marker clusters, depending on the zoom level). Clicking on a marker opens a popup which (depending on config settings) displays the location name or coordinates, and provides a link to search for other items with the same location name/coordinates.
33
39
 
34
- 1. A `location_rpt` field that contains a bounding box for the document. For more on `location_rpt` see [Solr help](https://cwiki.apache.org/confluence/display/solr/Spatial+Search). This field can be multivalued.
35
- ```
36
- place_bbox: 44.0318907 25.0594286 63.3333366 39.7816755
37
- # minX minY maxX maxY
38
- ```
40
+ Users can also run a search using the map bounds as coordinate parameters by clicking the ![search control](docs/blacklight-maps_search-control.png) search control in the map view. Any items with coordinates or bounding boxes that are contained within the current map window will be returned.
41
+
42
+ In the catalog#map and catalog#index views, the geospatial data to populate the map comes from the facet component of the Solr response. Bounding boxes are represented as points corresponding to the center of the box.
43
+
44
+ In the catalog#show view, the data simply comes from the main document. Points are represented as markers and bounding boxes are represented as polygons. Clicking on a polygon opens a popup that allows the user to search for any items intersecting the bounding box.
45
+
46
+ ### Solr Requirements
47
+
48
+ Blacklight-Maps requires that your Solr index include at least one (but preferably BOTH) of the following two types of fields:
49
+
50
+ 1. A `location_rpt` field that contains coordinates or a bounding box. For more on `location_rpt` see [Solr help](https://cwiki.apache.org/confluence/display/solr/Spatial+Search). This field can be multivalued.
51
+
52
+ ```
53
+ # coordinates: lon lat or lat,lon
54
+ # bounding box: minX minY maxX maxY
55
+ coordinates_field:
56
+ - 78.96288 20.593684
57
+ - 20.593684,78.96288
58
+ - 68.162386 6.7535159 97.395555 35.5044752
59
+ ```
60
+
61
+ 2. An indexed, stored string field containing a properly-formatted [GeoJSON](http://geojson.org) feature object for a point or bounding box that includes the coordinates and (preferably) location name. This field can be multivalued.
62
+
63
+ ```
64
+ # first example below is for coordinate point, second is for bounding box
65
+ geojson_ssim:
66
+ - {"type":"Feature","geometry":{"type":"Point","coordinates":[78.96288,20.593684]},"properties":{"placename":"India"}}
67
+ - {"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[68.162386, 6.7535159], [97.395555, 6.7535159], [97.395555, 35.5044752], [68.162386, 35.5044752], [68.162386, 6.7535159]]]},"bbox":[68.162386, 6.7535159, 97.395555, 35.5044752]}
68
+ ```
69
+
70
+ If you have #2 above and you want the popup search links to use the location name as a search parameter, you also need:
71
+
72
+ 3. An indexed, stored text or string field containing location names. This field can be multivalued.
73
+
74
+ ```
75
+ placename_field: India
76
+ ```
77
+
78
+ ##### Why so complicated?
79
+ Blacklight-Maps can be used with either field type (#1 or #2), however to take advantage of the full feature set, it is preferred that both field types exist for each item with geospatial metadata.
80
+
81
+ * The GeoJSON field (#2 above) provides reliable association of place names with coordinates, so the map marker popups can display the location name
82
+ * The Location name field (#3 above) allows users to run meaningful searches for locations found on the map
83
+ * The Coordinate field (#1 above) provides for the "Search" function on the map in the catalog#map and catalog#index views
84
+
85
+
86
+ **Important:** If you are NOT using the geojson field (#2), you should create a `copyField` in your Solr schema.xml to copy the coordinates from the `location_rpt` field to a string field that is stored, indexed, and multivalued to allow for proper faceting of the coordinate values in the catalog#map and catalog#index views.
39
87
 
40
- 2. A field containing placenames with latitude and longitude coordinates delimited by `-|-`. The delimiter can be configured in `app/controllers/catalog_controller.rb`. This field can be multivalued.
41
- ```
42
- placename_coords:
43
- - China-|-35.86166-|-104.195397
44
- - Tibet-|-29.646923-|-91.117212
45
- - India-|-20.593684-|-78.96288
88
+ ```
89
+ <!-- Solr4 location_rpt field for coordinates, shapes, etc. -->
90
+ <dynamicField name="geospatial" type="location_rpt" indexed="true" stored="true" multiValued="true" />
91
+ <!-- copy geospatial to string field for faceting -->
92
+ <copyField source="geospatial" dest="geospatial_facet" />
46
93
  ```
47
94
 
48
- Note: We are looking at implementing support for additional fields.
95
+ Support for additional field types may be added in the future.
49
96
 
50
97
  ### Configuration
51
98
 
52
99
  #### Required
53
- Blacklight-Maps expects you to provide:
54
-
55
- - the type of location field you are using, `placename_coord` or `bbox` (`bbox` is default)
56
- - a field to map the placename coordinates or bbox field
100
+ Blacklight-Maps expects you to provide these configuration options:
101
+
102
+ + `facet_mode` = the type of field containing the data to use to display locations on the map (values: `'geojson'` or `'coordinates'`)
103
+ - if `'geojson'`:
104
+ + `geojson_field` = the name of the Solr field containing the GeoJSON data
105
+ + `placename_property` = the key in the GeoJSON properties hash representing the location name
106
+ - if `'coordinates'`
107
+ + `coordinates_facet_field` = the name of the Solr field containing coordinate data in string format (`<copyField>` of `coordinates_field`)
108
+ + `search_mode` = the type of search to run when clicking a link in the map popups (values: `'placename'` or `'coordinates'`)
109
+ - if `'placename'`:
110
+ + `placename_field` = the name of the Solr field containing the location names
111
+ + `coordinates_field` = the name of the Solr `location_rpt` type field containing geospatial coordinate data
57
112
 
58
113
  #### Optional
59
114
 
60
- - the maxZoom [property of the map](http://leafletjs.com/reference.html#map-maxzoom)
61
- - a [tileLayer url](http://leafletjs.com/reference.html#tilelayer-l.tilelayer) to change the basemap
62
- - an [attribution string](http://leafletjs.com/reference.html#tilelayer-attribution) to describe the basemap layer
63
- - a custom delimiter field (used to delimit placename_coord values)
115
+ - `show_initial_zoom` = the zoom level to be used in the catalog#show view map (zoom levels for catalog#map and catalog#index map views are computed automatically)
116
+ - `maxzoom` = the maxZoom [property of the map](http://leafletjs.com/reference.html#map-maxzoom)
117
+ - `tileurl` = a [tileLayer url](http://leafletjs.com/reference.html#tilelayer-l.tilelayer) to change the basemap
118
+ - `mapattribution` = an [attribution string](http://leafletjs.com/reference.html#tilelayer-attribution) to describe the basemap layer
119
+ - `spatial_query_dist` = the radial distance, in kilometers, to search from a supplied coordinate point in a spatial search. This corresponds to the `d` [Spatial Filter](https://cwiki.apache.org/confluence/display/solr/Spatial+Search) parameter in Solr.
120
+
64
121
 
65
122
  All of these options can easily be configured in `CatalogController.rb` in the `config` block.
66
123
 
67
- ```
124
+ ```ruby
68
125
  ...
69
126
  configure_blacklight do |config|
70
- ## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
71
- config.default_solr_params = {
72
- :qt => 'search',
73
- :rows => 10,
74
- :fl => '*'
75
- }
76
-
77
- ## Default values
78
- config.view.maps.type = "bbox" # also accepts 'placename_coord' to use the placename coordinate type
79
- config.view.maps.bbox_field = "place_bbox"
80
- config.view.maps.placename_coord_field = "placename_coords"
127
+ ## blacklight-maps configuration default values
128
+ config.view.maps.geojson_field = "geojson"
129
+ config.view.maps.placename_property = "placename"
130
+ config.view.maps.coordinates_field = "coordinates"
131
+ config.view.maps.search_mode = "placename" # or "coordinates"
132
+ config.view.maps.spatial_query_dist = 0.5
133
+ config.view.maps.placename_field = "placename_field"
134
+ config.view.maps.coordinates_facet_field = "coordinates_facet_field"
135
+ config.view.maps.facet_mode = "geojson" # or "coordinates"
81
136
  config.view.maps.tileurl = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
82
- config.view.maps.attribution = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
83
- config.view.maps.placename_coord_delimiter = '-|-'
137
+ config.view.maps.mapattribution = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
138
+ config.view.maps.maxzoom = 18
139
+ config.view.maps.show_initial_zoom = 5
84
140
  ...
85
141
 
86
142
  ```
87
143
 
144
+ ### Implementation
145
+
146
+ The catalog#map and catalog#index map views are available by default. The "browse everything" Map view will be available in your app at `/map`, and in your app using routing helper `map_path`.
147
+
148
+ However, the catalog#show maplet widget must be included manually, via one of two ways:
149
+
150
+ 1. Include the catalog/show_maplet_default partial explicitly. This option gives you the most flexibility, as you can choose where the partial gets rendered.
151
+
152
+ ```ruby
153
+ <%= render partial: 'catalog/show_maplet_default' %>
154
+ ```
155
+
156
+ 2. Add `:show_maplet` to the list of partials to be rendered automatically by Blacklight in `CatalogController.rb` in the `config` block. This option is less work up front, but it may be more difficult to customize how the maplet is integrated into the page layout.
157
+
158
+ ```
159
+ ...
160
+ configure_blacklight do |config|
161
+ # add :show_maplet to the show partials array
162
+ config.show.partials << :show_maplet
163
+ ...
164
+ ```
88
165
 
89
166
  ## Contributing
90
167
 
91
168
  1. Fork it ( http://github.com/<my-github-username>/blacklight-maps/fork )
92
169
  2. Create your feature branch (`git checkout -b my-new-feature`)
93
- 3. Commit your changes (`git commit -am 'Add some feature'`)
94
- 4. Push to the branch (`git push origin my-new-feature`)
95
- 5. Create new Pull Request
170
+ 3. Make some changes (with [tests](https://github.com/projectblacklight/blacklight/wiki/testing), please)
171
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
172
+ 5. Push to the branch (`git push origin my-new-feature`)
173
+ 6. Create new Pull Request
@@ -3,6 +3,5 @@
3
3
 
4
4
  //= require leaflet
5
5
  //= require leaflet.markercluster
6
- //= require L.Control.Sidebar
7
6
 
8
- //= require_tree './blacklight-maps'
7
+ //= require_tree .
@@ -3,14 +3,53 @@
3
3
  $.fn.blacklight_leaflet_map = function(geojson_docs, arg_opts) {
4
4
  var map, sidebar, markers, geoJsonLayer, currentLayer;
5
5
 
6
- // Update page links with number of mapped items
7
- $('.page_links').append('<span class="badge mapped-count">' + geojson_docs.features.length + '</span> mapped');
6
+ var mapped_items = '<span class="mapped-count"><span class="badge">' + geojson_docs.features.length + '</span> location' + (geojson_docs.features.length !== 1 ? 's' : '') + ' mapped</span>';
7
+
8
+ var mapped_caveat = '<span class="mapped-caveat">Only items with location data are shown below</span>';
9
+
10
+ var sortAndPerPage = $('#sortAndPerPage');
11
+
12
+ // Update page links with number of mapped items, disable sort, per_page, pagination
13
+ if (sortAndPerPage.length) { // catalog#index and #map view
14
+ var page_links = sortAndPerPage.find('.page_links');
15
+ var result_count = page_links.find('.page_entries').find('strong').last().html();
16
+ page_links.html('<span class="page_entries"><strong>' + result_count + '</strong> items found</span>' + mapped_items + mapped_caveat);
17
+ sortAndPerPage.find('.dropdown-toggle').hide();
18
+
19
+ // clusters should show item result count in #index and #map views
20
+ var clusterIconFunction = function (cluster) {
21
+ var markers = cluster.getAllChildMarkers();
22
+ var childCount = 0;
23
+ for (var i = 0; i < markers.length; i++) {
24
+ childCount += markers[i].feature.properties.hits;
25
+ }
26
+ var c = ' marker-cluster-';
27
+ if (childCount < 10) {
28
+ c += 'small';
29
+ } else if (childCount < 100) {
30
+ c += 'medium';
31
+ } else {
32
+ c += 'large';
33
+ }
34
+ return new L.divIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });
35
+ };
36
+ } else { // catalog#show view
37
+ $(this.selector).before(mapped_items);
38
+ var clusterIconFunction = this._defaultIconCreateFunction;
39
+ }
8
40
 
9
41
  // Configure default options and those passed via the constructor options
10
42
  var options = $.extend({
11
43
  tileurl : 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
12
44
  mapattribution : 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
13
- sidebar: 'blacklight-map-sidebar'
45
+ viewpoint: [0,0],
46
+ initialzoom: 2,
47
+ singlemarkermode: true,
48
+ searchcontrol: false,
49
+ catalogpath: 'catalog',
50
+ searchctrlcue: 'Search for all items within the current map window',
51
+ placenamefield: 'placename_field',
52
+ nodata: 'Sorry, there is no data for this location.'
14
53
  }, arg_opts );
15
54
 
16
55
  // Extend options from data-attributes
@@ -21,135 +60,122 @@
21
60
  options.id = this.id;
22
61
 
23
62
  // Setup Leaflet map
24
- map = L.map(this.id).setView([0,0], 2);
63
+ map = L.map(this.id);
64
+
65
+ // set the viewpoint and zoom
66
+ if (options.viewpoint[0].constructor === Array) {
67
+ map.fitBounds(options.viewpoint,
68
+ {
69
+ padding:[10,10],
70
+ maxZoom:options.maxzoom
71
+ });
72
+ } else {
73
+ map.setView(options.viewpoint, options.initialzoom);
74
+ }
75
+
25
76
  L.tileLayer(options.tileurl, {
26
77
  attribution: options.mapattribution,
27
78
  maxZoom: options.maxzoom
28
79
  }).addTo(map);
29
80
 
30
- // Initialize sidebar
31
- sidebar = L.control.sidebar(options.sidebar, {
32
- position: 'right',
33
- autoPan: false
34
- });
35
-
36
- // Adds leaflet-sidebar control to map
37
- map.addControl(sidebar);
38
-
39
81
  // Create a marker cluster object and set options
40
82
  markers = new L.MarkerClusterGroup({
41
- showCoverageOnHover: false,
42
- spiderfyOnMaxZoom: false,
43
- singleMarkerMode: true,
44
- animateAddingMarkers: true
83
+ singleMarkerMode: options.singlemarkermode,
84
+ iconCreateFunction: clusterIconFunction
45
85
  });
46
86
 
47
87
  geoJsonLayer = L.geoJson(geojson_docs, {
48
88
  onEachFeature: function(feature, layer){
49
- layer.defaultOptions.title = getMapTitle(options.type, feature.properties.name);
50
- layer.on('click', function(e){
51
- var placenames = {};
52
- placenames[layer.defaultOptions.title] = [feature.properties.html];
53
- setupSidebarDisplay(e,placenames);
54
- });
89
+ if (feature.properties.popup) {
90
+ layer.bindPopup(feature.properties.popup);
91
+ } else {
92
+ layer.bindPopup(options.nodata);
93
+ }
55
94
  }
56
95
  });
57
96
 
58
97
  // Add GeoJSON layer to marker cluster object
59
98
  markers.addLayer(geoJsonLayer);
60
99
 
61
- // Add marker cluster object to map
100
+ // Add markers to map
62
101
  map.addLayer(markers);
63
102
 
64
- // Listeners for marker cluster clicks
65
- markers.on('clusterclick', function(e){
66
- hideSidebar();
103
+ // create overlay for search control hover
104
+ var searchHoverLayer = L.rectangle([[0,0], [0,0]], {
105
+ color: "#0033ff",
106
+ weight: 5,
107
+ opacity: 0.5,
108
+ fill: true,
109
+ fillColor: "#0033ff",
110
+ fillOpacity: 0.2
111
+ });
67
112
 
68
- //if map is at the lowest zoom level
69
- if (map.getZoom() === options.maxzoom){
113
+ // create search control
114
+ var searchControl = L.Control.extend({
70
115
 
71
- var placenames = generatePlacenamesObject(e.layer.getAllChildMarkers());
72
- setupSidebarDisplay(e,placenames);
73
- }
74
- });
116
+ options: { position: 'topleft' },
75
117
 
76
- //Add click listener to map
77
- map.on('click drag', hideSidebar);
118
+ onAdd: function (map) {
119
+ var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
120
+ this.link = L.DomUtil.create('a', 'leaflet-bar-part search-control', container);
121
+ this.link.title = options.searchctrlcue;
122
+ this.icon = L.DomUtil.create('i', 'glyphicon glyphicon-search', this.link);
78
123
 
79
- });
124
+ L.DomEvent.addListener(this.link, 'click', _search);
80
125
 
81
- function setupSidebarDisplay(e, placenames){
82
- hideSidebar();
83
- offsetMap(e);
84
- if (currentLayer !== e.layer || !("layer" in e)){
85
- // Update sidebar div with new html
86
- $('#' + options.sidebar).html(buildList(placenames));
126
+ L.DomEvent.addListener(this.link, 'mouseover', function () {
127
+ searchHoverLayer.setBounds(map.getBounds());
128
+ map.addLayer(searchHoverLayer);
129
+ });
87
130
 
88
- // Scroll sidebar div to top
89
- $('#' + options.sidebar).scrollTop(0);
90
- currentLayer = e.layer;
91
- }
131
+ L.DomEvent.addListener(this.link, 'mouseout', function () {
132
+ map.removeLayer(searchHoverLayer);
133
+ });
92
134
 
93
- // Show the sidebar
94
- sidebar.show();
135
+ return container;
136
+ }
95
137
 
96
- }
138
+ });
97
139
 
98
- // Hides sidebar if it is visible
99
- function hideSidebar(){
100
- if (sidebar.isVisible()){
101
- sidebar.hide();
140
+ // add search control to map
141
+ if (options.searchcontrol === true) {
142
+ map.addControl(new searchControl());
102
143
  }
103
- }
104
144
 
105
- // Build the list
106
- function buildList(placenames){
107
- var html = "";
108
- $.each(placenames, function(i,val){
109
- html += "<h2>" + i + "</h2>";
110
- html += "<ul class='sidebar-list'>";
111
- $.each(val, function(j, val2){
112
- html += val2;
113
- });
114
- html += "</ul>";
115
- });
116
- return html;
117
- }
145
+ });
118
146
 
119
- // Generates placenames object
120
- function generatePlacenamesObject(markers){
121
- var placenames = {};
122
- $.each(markers, function(i,val){
123
- if (!(val.defaultOptions.title in placenames)){
124
- placenames[val.defaultOptions.title] = [];
125
- }
126
- placenames[val.defaultOptions.title].push(val.feature.properties.html);
127
- });
128
- return placenames;
147
+ // remove stale params, add new params, and run a new search
148
+ function _search() {
149
+ var params = filterParams(['view', 'spatial_search_type', 'coordinates', 'f%5B' + options.placenamefield + '%5D%5B%5D']),
150
+ bounds = map.getBounds().toBBoxString().split(',').map(function(coord) {
151
+ if (parseFloat(coord) > 180) {
152
+ coord = '180'
153
+ } else if (parseFloat(coord) < -180) {
154
+ coord = '-180'
155
+ }
156
+ return Math.round(parseFloat(coord) * 1000000) / 1000000;
157
+ }),
158
+ coordinate_params = '[' + bounds[1] + ',' + bounds[0] + ' TO ' + bounds[3] + ',' + bounds[2] + ']';
159
+ params.push('coordinates=' + encodeURIComponent(coordinate_params), 'spatial_search_type=bbox');
160
+ $(location).attr('href', options.catalogpath + '?' + params.join('&'));
129
161
  }
130
162
 
131
- // Move the map so that it centers the clicked cluster TODO account for various size screens
132
- function offsetMap(e){
133
- var mapWidth = $('#' + options.id).width();
134
- var mapHeight = $('#' + options.id).height();
135
- if (!e.latlng.equals(map.getCenter())){
136
- map.panBy([(e.originalEvent.layerX - (mapWidth/4)), (e.originalEvent.layerY - (mapHeight/2))]);
137
- }else{
138
- map.panBy([(mapWidth/4), 0]);
163
+ // remove unwanted params
164
+ function filterParams(filterList) {
165
+ var querystring = window.location.search.substr(1),
166
+ params = [];
167
+ if (querystring !== "") {
168
+ params = $.map(querystring.split('&'), function(value) {
169
+ if ($.inArray(value.split('=')[0], filterList) > -1) {
170
+ return null;
171
+ } else {
172
+ return value;
173
+ }
174
+ });
139
175
  }
176
+ return params;
140
177
  }
141
178
 
142
179
  };
143
180
 
144
- function getMapTitle(type, featureName){
145
- switch(type){
146
- case 'bbox':
147
- return 'Results';
148
- case 'placename_coord':
149
- return featureName;
150
- default:
151
- return 'Results';
152
- }
153
- }
154
-
155
181
  }( jQuery ));