blacklight-maps 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +18 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +13 -0
- data/README.md +81 -0
- data/Rakefile +43 -0
- data/app/assets/javascripts/blacklight-maps.js +8 -0
- data/app/assets/javascripts/blacklight-maps/blacklight-maps-browse.js +141 -0
- data/app/assets/stylesheets/blacklight_maps/blacklight-maps.css.scss +4 -0
- data/app/assets/stylesheets/blacklight_maps/default.css.scss +24 -0
- data/app/helpers/blacklight_maps_helper.rb +36 -0
- data/app/views/catalog/_document_maps.html.erb +6 -0
- data/app/views/catalog/_index_maps.html.erb +9 -0
- data/blacklight-maps.gemspec +34 -0
- data/config/jetty.yml +7 -0
- data/config/locales/blacklight-maps.en.yml +5 -0
- data/config/routes.rb +4 -0
- data/docs/map-sidebar.png +0 -0
- data/docs/map-view.png +0 -0
- data/lib/blacklight/maps.rb +7 -0
- data/lib/blacklight/maps/engine.rb +32 -0
- data/lib/blacklight/maps/version.rb +5 -0
- data/lib/generators/blacklight_maps/install_generator.rb +25 -0
- data/lib/generators/blacklight_maps/templates/blacklight_maps.css.scss +3 -0
- data/lib/railties/blacklight_maps.rake +13 -0
- data/solr_conf/conf/schema.xml +673 -0
- data/solr_conf/conf/solrconfig.xml +523 -0
- data/spec/features/maps_spec.rb +79 -0
- data/spec/fixtures/sample_solr_documents.yml +2742 -0
- data/spec/helpers/blacklight_maps_helper_spec.rb +28 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/test_app_templates/Gemfile.extra +7 -0
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +23 -0
- metadata +268 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e35e471feb601eeeec9355dc1cc7e31d158f03bb
|
4
|
+
data.tar.gz: 8be5024c30a03decfb0e15563f79117606be1fec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b019eae752da2b6cc576a759b09abb1d7799748c82603b0d13f20990f592e0ad51b35785abb6dda9370d5cbbd477c506ee26db9f73ae2cfa8aa7380ea584c707
|
7
|
+
data.tar.gz: a999abc043657b6f52ae34f1ce6d5479491b49812e2fa87b93257a3173de069a4e237d09e4cfb53869849d939803554842a918aec59e78c182d94be3d02f787b
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
notifications:
|
2
|
+
email: false
|
3
|
+
|
4
|
+
rvm:
|
5
|
+
- 2.1.0
|
6
|
+
- 2.0.0
|
7
|
+
- 1.9.3
|
8
|
+
- jruby-19mode
|
9
|
+
|
10
|
+
notifications:
|
11
|
+
irc: "irc.freenode.org#blacklight"
|
12
|
+
email:
|
13
|
+
- blacklight-commits@googlegroups.com
|
14
|
+
|
15
|
+
env:
|
16
|
+
global:
|
17
|
+
- JRUBY_OPTS="-J-Xms512m -J-Xmx1024m"
|
18
|
+
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in blacklight-maps.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'simplecov', require: false
|
7
|
+
gem 'coveralls', require: false
|
8
|
+
|
9
|
+
gem 'engine_cart', git: 'https://github.com/cbeer/engine_cart'
|
10
|
+
|
11
|
+
|
12
|
+
file = File.expand_path("Gemfile", ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path("../spec/internal", __FILE__))
|
13
|
+
if File.exists?(file)
|
14
|
+
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
|
15
|
+
instance_eval File.read(file)
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014 The Board of Trustees of the Leland Stanford Junior University.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Blacklight::Maps
|
2
|
+
|
3
|
+
[](https://travis-ci.org/sul-dlss/blacklight-maps)
|
4
|
+
|
5
|
+
Provides a map view for Blacklight search results.
|
6
|
+
|
7
|
+

|
8
|
+

|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'blacklight-maps'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install blacklight-maps
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
Blacklight-Maps adds a map view capability for a results set that contains geospatial coordinates (latitude/longitude).
|
27
|
+
|
28
|
+
For now, Blacklight-Maps requires that your SOLR index includes a field containing placenames with latitude and longitude coordinates delimited by `|`. This field can be multivalued.
|
29
|
+
|
30
|
+
A document requires the following field:
|
31
|
+
```
|
32
|
+
placename_coords:
|
33
|
+
- China|35.86166|104.195397
|
34
|
+
- Tibet|29.646923|91.117212
|
35
|
+
- India|20.593684|78.96288
|
36
|
+
```
|
37
|
+
|
38
|
+
Note: We are looking at implementing support for additional fields.
|
39
|
+
|
40
|
+
### Configuration
|
41
|
+
|
42
|
+
#### Required
|
43
|
+
Blacklight-Maps expects you to provide:
|
44
|
+
|
45
|
+
- a field to map the placename coordinates (`placename_coords` in the example above)
|
46
|
+
|
47
|
+
#### Optional
|
48
|
+
|
49
|
+
- the maxZoom [property of the map](http://leafletjs.com/reference.html#map-maxzoom)
|
50
|
+
- a [tileLayer url](http://leafletjs.com/reference.html#tilelayer-l.tilelayer) to change the basemap
|
51
|
+
- an [attribution string](http://leafletjs.com/reference.html#tilelayer-attribution) to describe the basemap layer
|
52
|
+
|
53
|
+
|
54
|
+
All of these options can easily be configured in `CatalogController.rb` in the `config` block.
|
55
|
+
|
56
|
+
```
|
57
|
+
...
|
58
|
+
configure_blacklight do |config|
|
59
|
+
## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
|
60
|
+
config.default_solr_params = {
|
61
|
+
:qt => 'search',
|
62
|
+
:rows => 10,
|
63
|
+
:fl => '*'
|
64
|
+
}
|
65
|
+
|
66
|
+
## Default values
|
67
|
+
config.view.maps.placename_coords_field = "placename_coords"
|
68
|
+
config.view.maps.tileurl = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
69
|
+
config.view.maps.attribution = 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
|
70
|
+
...
|
71
|
+
|
72
|
+
```
|
73
|
+
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
1. Fork it ( http://github.com/<my-github-username>/blacklight-maps/fork )
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
80
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
81
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
ZIP_URL = "https://github.com/projectblacklight/blacklight-jetty/archive/v4.6.0.zip"
|
4
|
+
APP_ROOT = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'engine_cart/rake_task'
|
8
|
+
|
9
|
+
require 'jettywrapper'
|
10
|
+
|
11
|
+
task default: :ci
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
14
|
+
|
15
|
+
desc "Load fixtures"
|
16
|
+
task :fixtures => ['engine_cart:generate'] do
|
17
|
+
EngineCart.within_test_app do
|
18
|
+
system "rake blacklight_maps:solr:seed RAILS_ENV=test"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Execute Continuous Integration build"
|
23
|
+
task :ci => ['engine_cart:generate', 'jetty:clean', 'blacklight_maps:configure_jetty'] do
|
24
|
+
|
25
|
+
require 'jettywrapper'
|
26
|
+
jetty_params = Jettywrapper.load_config('test')
|
27
|
+
|
28
|
+
error = Jettywrapper.wrap(jetty_params) do
|
29
|
+
Rake::Task['fixtures'].invoke
|
30
|
+
Rake::Task['spec'].invoke
|
31
|
+
end
|
32
|
+
raise "test failures: #{error}" if error
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
namespace :blacklight_maps do
|
37
|
+
desc "Copies the default SOLR config for the bundled Testing Server"
|
38
|
+
task :configure_jetty do
|
39
|
+
FileList['solr_conf/conf/*'].each do |f|
|
40
|
+
cp("#{f}", 'jetty/solr/blacklight-core/conf/', :verbose => true)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
var map, sidebar;
|
2
|
+
|
3
|
+
Blacklight.onLoad(function() {
|
4
|
+
|
5
|
+
// Stop doing stuff if the map div isn't there
|
6
|
+
if ($("#blacklight-map").length === 0){
|
7
|
+
return;
|
8
|
+
}
|
9
|
+
|
10
|
+
// Get the configuration options from the data-attributes
|
11
|
+
$.extend(Blacklight.mapOptions, $("#blacklight-map").data());
|
12
|
+
|
13
|
+
map = L.map('blacklight-map').setView([0,0], 2);
|
14
|
+
L.tileLayer(Blacklight.mapOptions.tileurl, {
|
15
|
+
attribution: Blacklight.mapOptions.mapattribution,
|
16
|
+
maxZoom: Blacklight.mapOptions.maxzoom
|
17
|
+
}).addTo(map);
|
18
|
+
|
19
|
+
// Sets up leaflet-sidebar
|
20
|
+
sidebar = L.control.sidebar('blacklight-map-sidebar', {
|
21
|
+
position: 'right',
|
22
|
+
autoPan: false
|
23
|
+
});
|
24
|
+
|
25
|
+
// Adds leaflet-sidebar control to map (object)
|
26
|
+
map.addControl(sidebar);
|
27
|
+
|
28
|
+
// Create a marker cluster object and set options
|
29
|
+
markers = new L.MarkerClusterGroup({
|
30
|
+
showCoverageOnHover: false,
|
31
|
+
spiderfyOnMaxZoom: false,
|
32
|
+
singleMarkerMode: true,
|
33
|
+
animateAddingMarkers: true
|
34
|
+
});
|
35
|
+
|
36
|
+
geoJsonLayer = L.geoJson(geojson_docs, {
|
37
|
+
onEachFeature: function(feature, layer){
|
38
|
+
layer.defaultOptions.title = feature.properties.placename;
|
39
|
+
layer.on('click', function(e){
|
40
|
+
if (sidebar.isVisible()){
|
41
|
+
sidebar.hide();
|
42
|
+
}
|
43
|
+
var placenames = {};
|
44
|
+
placenames[feature.properties.placename] = [feature.properties.html];
|
45
|
+
offsetMap(e);
|
46
|
+
$('#blacklight-map-sidebar').html(buildList(placenames));
|
47
|
+
sidebar.show();
|
48
|
+
});
|
49
|
+
}
|
50
|
+
});
|
51
|
+
|
52
|
+
// Add GeoJSON layer to marker cluster object
|
53
|
+
markers.addLayer(geoJsonLayer);
|
54
|
+
|
55
|
+
// Add marker cluster object to map
|
56
|
+
map.addLayer(markers);
|
57
|
+
|
58
|
+
// Listeners for marker cluster clicks
|
59
|
+
markers.on('clusterclick', function(e){
|
60
|
+
|
61
|
+
//hide sidebar if it is visible
|
62
|
+
if (sidebar.isVisible()){
|
63
|
+
sidebar.hide();
|
64
|
+
}
|
65
|
+
|
66
|
+
//if map is at the lowest zoom level
|
67
|
+
if (map.getZoom() === Blacklight.mapOptions.maxzoom){
|
68
|
+
|
69
|
+
var placenames = generatePlacenamesObject(e.layer._markers);
|
70
|
+
|
71
|
+
|
72
|
+
offsetMap(e);
|
73
|
+
|
74
|
+
//Update sidebar div with new html
|
75
|
+
$('#blacklight-map-sidebar').html(buildList(placenames));
|
76
|
+
|
77
|
+
//Show the sidebar!
|
78
|
+
sidebar.show();
|
79
|
+
}
|
80
|
+
});
|
81
|
+
|
82
|
+
//Add click listener to map
|
83
|
+
map.on('click', function(e){
|
84
|
+
|
85
|
+
//hide the sidebar if it is visible
|
86
|
+
if (sidebar.isVisible()){
|
87
|
+
sidebar.hide();
|
88
|
+
}
|
89
|
+
});
|
90
|
+
|
91
|
+
//drag listener on map
|
92
|
+
map.on('drag', function(e){
|
93
|
+
|
94
|
+
//hide the sidebar if it is visible
|
95
|
+
if (sidebar.isVisible()){
|
96
|
+
sidebar.hide();
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
});
|
101
|
+
|
102
|
+
Blacklight.mapOptions = {
|
103
|
+
tileurl : 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
104
|
+
mapattribution : 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
|
105
|
+
};
|
106
|
+
|
107
|
+
function buildList(placenames){
|
108
|
+
var html = "";
|
109
|
+
$.each(placenames, function(i,val){
|
110
|
+
html += "<h2>" + i + "</h2>";
|
111
|
+
html += "<ul class='sidebar-list'>";
|
112
|
+
$.each(val, function(j, val2){
|
113
|
+
html += val2;
|
114
|
+
});
|
115
|
+
html += "</ul>";
|
116
|
+
});
|
117
|
+
return html;
|
118
|
+
}
|
119
|
+
|
120
|
+
// Generates placenames object
|
121
|
+
function generatePlacenamesObject(markers){
|
122
|
+
var placenames = {};
|
123
|
+
$.each(markers, function(i,val){
|
124
|
+
if (!(val.feature.properties.placename in placenames)){
|
125
|
+
placenames[val.feature.properties.placename] = [];
|
126
|
+
}
|
127
|
+
placenames[val.feature.properties.placename].push(val.feature.properties.html);
|
128
|
+
});
|
129
|
+
return placenames;
|
130
|
+
}
|
131
|
+
|
132
|
+
// Move the map so that it centers the clicked cluster TODO account for various size screens
|
133
|
+
function offsetMap(e){
|
134
|
+
mapWidth = $('#blacklight-map').width();
|
135
|
+
mapHeight = $('#blacklight-map').height();
|
136
|
+
if (!e.latlng.equals(map.getCenter())){
|
137
|
+
map.panBy([(e.originalEvent.layerX - (mapWidth/4)), (e.originalEvent.layerY - (mapHeight/2))]);
|
138
|
+
}else{
|
139
|
+
map.panBy([(mapWidth/4), 0]);
|
140
|
+
}
|
141
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
/*
|
2
|
+
*= require leaflet
|
3
|
+
*= require leaflet.markercluster
|
4
|
+
*= require leaflet.markercluster.default
|
5
|
+
*= require L.Control.Sidebar.css
|
6
|
+
*/
|
7
|
+
|
8
|
+
.view-icon-maps {
|
9
|
+
&:before { content: "\e135"; }
|
10
|
+
}
|
11
|
+
|
12
|
+
#blacklight-map{
|
13
|
+
height: 550px;
|
14
|
+
}
|
15
|
+
|
16
|
+
.sidebar-thumb{
|
17
|
+
height: 64px;
|
18
|
+
width: 64px;
|
19
|
+
}
|
20
|
+
|
21
|
+
.sidebar-list{
|
22
|
+
padding-left: 0;
|
23
|
+
list-style: none;
|
24
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BlacklightMapsHelper
|
2
|
+
|
3
|
+
def show_map_div
|
4
|
+
data_attributes = {
|
5
|
+
:maxzoom => blacklight_config.view.maps.maxzoom,
|
6
|
+
:tileurl => blacklight_config.view.maps.tileurl
|
7
|
+
|
8
|
+
}
|
9
|
+
|
10
|
+
content_tag(:div, "", id: "blacklight-map",
|
11
|
+
data: data_attributes
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize_geojson
|
16
|
+
geojson_docs = {type: "FeatureCollection", features: []}
|
17
|
+
@response.docs.each_with_index do |doc, counter|
|
18
|
+
if doc[blacklight_config.view.maps.placename_coord_field]
|
19
|
+
doc[blacklight_config.view.maps.placename_coord_field].each do |loc|
|
20
|
+
values = loc.split('|')
|
21
|
+
feature = {type: "Feature", geometry: {type: "Point",
|
22
|
+
coordinates: [values[2].to_f, values[1].to_f]},
|
23
|
+
properties: {placename: values[0],
|
24
|
+
html: render_leaflet_sidebar_partial(doc)}}
|
25
|
+
geojson_docs[:features].push feature
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return geojson_docs.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_leaflet_sidebar_partial(doc)
|
33
|
+
render partial: 'catalog/index_maps', locals: {document: SolrDocument.new(doc)}
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% # the way each document will be viewed in the sidebar list -%>
|
2
|
+
<li class='media'>
|
3
|
+
<%= render_thumbnail_tag document, {class: 'sidebar-thumb media-object'}, {class: 'pull-left'} %>
|
4
|
+
<div class='media-body'>
|
5
|
+
<h4 class='media-heading'>
|
6
|
+
<%= link_to_document document, :label=>document_show_link_field(document) %>
|
7
|
+
</h4>
|
8
|
+
</div>
|
9
|
+
</li>
|