geoblacklight 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c5270535fbab7516ccc911e63dee5fdaf1b632d7
4
- data.tar.gz: e699996e65fb6c49bb3cc9d15b5298862c57dedc
3
+ metadata.gz: 5e4a028e9501e7fe556242ab6993d8ef4deb6e41
4
+ data.tar.gz: 516f09eb7667c35fd049df03eb7cd06c5f816197
5
5
  SHA512:
6
- metadata.gz: 747b13d2a4fd7217b96f9b746f8af36c51a12be37d6fea198d3eeebcfe35ff479626a1563bcafe93384bfd1340086d65f6696ffcfcddeef95bb70ce8fc7f35bb
7
- data.tar.gz: d7c85ac98ffe88c6a32b54c724522aa8bc5bc12f5ed3b674fe00030cde245ae6ff20088b485d5e74fb15e68a96ea23195f01a420d67bd279a7e939cda824f8f3
6
+ metadata.gz: 59ec664c8312dae3934b7db59546e17dcf520ed5b9fc6a5724bd303d05352a34891326007742562d7326ae5e32c0cd208570d602cb042ae2af359a75eb930ed4
7
+ data.tar.gz: 91bfb680d29a94bedc3b596a533054c6a72b06e5e0cb0b0a8ca09541466cdf32fe2a4203c35c95b03bceffc3d7ee750af6e1206649f11b39bac9701af3e1924b
@@ -1,5 +1,6 @@
1
1
  //= require leaflet
2
2
  //= require native.history
3
+ //= require_tree ./templates
3
4
 
4
5
  !function(global) {
5
6
  'use strict';
@@ -1,7 +1,15 @@
1
1
  Blacklight.onLoad(function() {
2
- $('#ajax-modal').on('loaded.blacklight.ajax-modal', function() {
2
+ $('#ajax-modal').on('loaded.blacklight.ajax-modal', function(e) {
3
+ $(e.target).find('.metadata-body').each(function(_i, el) {
4
+ $(el).parent().parent().addClass('metadata-modal');
5
+ });
3
6
  $(this).find('.pill-metadata').each(function(i, element) {
4
7
  GeoBlacklight.metadataDownloadButton(element);
5
8
  });
6
9
  });
10
+ $('#ajax-modal').on('hidden.bs.modal', function(e) {
11
+ $(e.target).find('.metadata-body').each(function(_i, el) {
12
+ $(el).parent().parent().removeClass('metadata-modal');
13
+ });
14
+ });
7
15
  });
@@ -5,5 +5,26 @@ GeoBlacklight.Util = {
5
5
  linkify: function(str) {
6
6
  var urlRegEx = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-]*)?\??(?:[\-\+=&;%@\.\w]*)#?(?:[\.\!\/\\\w]*))?)/g;
7
7
  return str.toString().replace(urlRegEx, '<a href=\'$1\'>$1</a>');
8
+ },
9
+ /**
10
+ * Calls the index map template
11
+ * @param {Object} data - GeoJSON feature properties object
12
+ * @param {requestCallback} cb
13
+ */
14
+ indexMapTemplate: function(data, cb) {
15
+ var thumbDeferred = $.Deferred();
16
+ $.when(thumbDeferred).done(function() {
17
+ cb(HandlebarsTemplates["index_map_info"](data));
18
+ });
19
+ if (data.iiifUrl) {
20
+ var manifest = $.getJSON(data.iiifUrl, function(manifestResponse) {
21
+ if (manifestResponse.thumbnail['@id'] !== null) {
22
+ data.thumbnailUrl = manifestResponse.thumbnail['@id'];
23
+ thumbDeferred.resolve();
24
+ }
25
+ });
26
+ } else {
27
+ thumbDeferred.resolve();
28
+ }
8
29
  }
9
30
  };
@@ -0,0 +1,38 @@
1
+ <div class="index-map-info">
2
+ {{#if title}}
3
+ <h3>{{title}}</h3>
4
+ {{/if}}
5
+ <div class="">
6
+ {{#if thumbnailUrl}}
7
+ {{#if websiteUrl}}
8
+ <a href="{{websiteUrl}}">
9
+ <img src="{{thumbnailUrl}}" class="img-responsive">
10
+ </a>
11
+ {{else}}
12
+ <img src="{{thumbnailUrl}}">
13
+ {{/if}}
14
+ {{/if}}
15
+ <dl>
16
+ {{#if websiteUrl}}
17
+ <dt>Website</dt>
18
+ <dd><a href="{{websiteUrl}}">{{websiteUrl}}</a></dd>
19
+ {{/if}}
20
+ {{#if downloadUrl}}
21
+ <dt>Download</dt>
22
+ <dd><a href="{{downloadUrl}}">{{downloadUrl}}</a></dd>
23
+ {{/if}}
24
+ {{#if recordIdentifier}}
25
+ <dt>Record Identifier</dt>
26
+ <dd>{{recordIdentifier}}</dd>
27
+ {{/if}}
28
+ {{#if label}}
29
+ <dt>Label</dt>
30
+ <dd>{{label}}</dd>
31
+ {{/if}}
32
+ {{#if note}}
33
+ <dt>Note</dt>
34
+ <dd>{{note}}</dd>
35
+ {{/if}}
36
+ </dl>
37
+ </div>
38
+ </div>
@@ -0,0 +1,53 @@
1
+ //= require geoblacklight/viewers/map
2
+
3
+ GeoBlacklight.Viewer.IndexMap = GeoBlacklight.Viewer.Map.extend({
4
+ load: function() {
5
+ this.map = L.map(this.element).fitBounds(this.options.bbox);
6
+ this.map.addLayer(this.selectBasemap());
7
+
8
+ if (this.data.available) {
9
+ this.addPreviewLayer();
10
+ } else {
11
+ this.addBoundsOverlay(this.options.bbox);
12
+ }
13
+ },
14
+
15
+ addPreviewLayer: function() {
16
+ var _this = this;
17
+ var geoJSONLayer;
18
+ $.getJSON(this.data.url, function(data) {
19
+ geoJSONLayer = L.geoJson(data,
20
+ {
21
+ style: function(feature) {
22
+ var style = {
23
+ weight: 1
24
+ }
25
+ // Style the colors based on availability
26
+ if (feature.properties.available) {
27
+ style.color = '#1eb300';
28
+ } else {
29
+ style.color = '#b3001e';
30
+ }
31
+ return style;
32
+ },
33
+ onEachFeature: function(feature, layer) {
34
+ // Add a hover label for the label property
35
+ if (feature.properties.label !== null) {
36
+ layer.bindLabel(feature.properties.label, {
37
+ direction: 'auto', permanent: true
38
+ });
39
+ }
40
+ // If it is available add clickable info
41
+ if (feature.properties.available !== null) {
42
+ layer.on('click', function(e) {
43
+ GeoBlacklight.Util.indexMapTemplate(feature.properties, function(html) {
44
+ $('.viewer-information').html(html);
45
+ });
46
+ });
47
+ }
48
+ }
49
+ }).addTo(_this.map);
50
+ _this.map.fitBounds(geoJSONLayer.getBounds());
51
+ });
52
+ }
53
+ });
@@ -1,18 +1,11 @@
1
1
  /**
2
2
  * Rules for the geospatial metadata Bootstrap Modal dialog
3
3
  */
4
- .modal-dialog {
5
- width: 1148px;
4
+ .modal-dialog.metadata-modal {
5
+ width: 90%;
6
6
  }
7
7
 
8
- .modal-header {
9
- .modal-title {
10
- font-weight: 400;
11
- font-size: 20px;
12
- }
13
- }
14
-
15
- .modal-body {
8
+ .metadata-body.modal-body {
16
9
  overflow-y: scroll;
17
10
  height: calc(100vh - 190px);
18
11
 
@@ -5,4 +5,5 @@
5
5
  <div class='row'>
6
6
  <%= render 'show_default_viewer_container' %>
7
7
  <%= render 'show_default_attribute_table' %>
8
+ <%= render 'show_default_viewer_information' %>
8
9
  </div>
@@ -0,0 +1,2 @@
1
+ <div class='viewer-information col-md-4'>
2
+ </div>
@@ -2,7 +2,7 @@
2
2
  <button type="button" class="ajax-modal-close close" data-dismiss="modal" aria-hidden="true">×</button>
3
3
  <h3 class="modal-title">View Metadata</h3>
4
4
  </div>
5
- <div class="modal-body">
5
+ <div class="modal-body metadata-body">
6
6
  <%= render partial: 'metadata' %>
7
7
  </div>
8
8
  <div class="modal-footer">
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency 'deprecation'
32
32
  spec.add_dependency 'geo_combine', '>= 0.3'
33
33
  spec.add_dependency 'mime-types'
34
+ spec.add_dependency 'handlebars_assets'
34
35
 
35
36
  spec.add_development_dependency 'solr_wrapper'
36
37
  spec.add_development_dependency 'rails-controller-testing'
@@ -1,3 +1,4 @@
1
+ //= require handlebars.runtime
1
2
  //= require geoblacklight/geoblacklight
2
3
  //= require geoblacklight/basemaps
3
4
  //= require geoblacklight/controls
@@ -7,3 +8,4 @@
7
8
  //= require leaflet-iiif
8
9
  //= require esri-leaflet
9
10
  //= require readmore.min
11
+ //= require leaflet-label-src
@@ -1,3 +1,4 @@
1
1
  /*
2
2
  *= require geoblacklight/application
3
+ *= require leaflet-label
3
4
  */
@@ -20,7 +20,8 @@ module Geoblacklight
20
20
  tiled_map_layer: 'urn:x-esri:serviceType:ArcGIS#TiledMapLayer',
21
21
  dynamic_map_layer: 'urn:x-esri:serviceType:ArcGIS#DynamicMapLayer',
22
22
  image_map_layer: 'urn:x-esri:serviceType:ArcGIS#ImageMapLayer',
23
- data_dictionary: 'http://lccn.loc.gov/sh85035852'
23
+ data_dictionary: 'http://lccn.loc.gov/sh85035852',
24
+ index_map: 'https://openindexmaps.org'
24
25
  }.freeze
25
26
  end
26
27
  end
@@ -8,6 +8,7 @@ require 'faraday_middleware'
8
8
  require 'nokogiri'
9
9
  require 'geoblacklight-icons'
10
10
  require 'mime/types'
11
+ require 'handlebars_assets'
11
12
 
12
13
  module Geoblacklight
13
14
  class Engine < ::Rails::Engine
@@ -38,8 +38,12 @@ module Geoblacklight
38
38
  @references.image_map_layer
39
39
  end
40
40
 
41
+ def index_map
42
+ @references.index_map
43
+ end
44
+
41
45
  def viewer_preference
42
- [wms, iiif, tiled_map_layer, dynamic_map_layer,
46
+ [index_map, wms, iiif, tiled_map_layer, dynamic_map_layer,
43
47
  image_map_layer, feature_layer].compact.map(&:to_hash).first
44
48
  end
45
49
  end
@@ -1,3 +1,3 @@
1
1
  module Geoblacklight
2
- VERSION = '1.7.1'.freeze
2
+ VERSION = '1.8.0'.freeze
3
3
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Index map' do
4
+ scenario 'displays index map viewer', js: true do
5
+ visit solr_document_path('stanford-fb897vt9938')
6
+ # Wait until SVG elements are added
7
+ expect(page).to have_css '.leaflet-overlay-pane svg'
8
+ page.first('svg g path').click
9
+ within '.index-map-info' do
10
+ expect(page).to have_css 'h3', text: 'Dabao Kinbōzu -- ダバオ近傍圖'
11
+ expect(page).to have_css 'a img[src="https://stacks.stanford.edu/image/iiif/zh828kt2136%2Fzh828kt2136_00_0001/full/!400,400/0/default.jpg"]'
12
+ within 'dl' do
13
+ expect(page).to have_css 'dt', text: 'Website'
14
+ expect(page).to have_css 'dd a', text: 'http://purl.stanford.edu/zh828kt2136'
15
+ expect(page).to have_css 'dt', text: 'Download'
16
+ expect(page).to have_css 'dd a', text: 'https://embed.stanford.edu/iframe?url=https://purl.stanford.edu/zh828kt2136&hide_title=true#'
17
+ expect(page).to have_css 'dt', text: 'Record Identifier'
18
+ expect(page).to have_css 'dd', text: '10532136'
19
+ expect(page).to have_css 'dt', text: 'Label'
20
+ expect(page).to have_css 'dd', text: 'SHEET 8'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -9,7 +9,7 @@ feature 'Index view', js: true do
9
9
  scenario 'should have documents and map on page' do
10
10
  visit search_catalog_path(f: { Settings.FIELDS.PROVENANCE => ['Stanford'] })
11
11
  expect(page).to have_css('#documents')
12
- expect(page).to have_css('.document', count: 3)
12
+ expect(page).to have_css('.document', count: 4)
13
13
  expect(page).to have_css('#map')
14
14
  end
15
15
 
@@ -0,0 +1,40 @@
1
+ {
2
+ "uuid": "http://purl.stanford.edu/fb897vt9938",
3
+ "dc_identifier_s": "http://purl.stanford.edu/fb897vt9938",
4
+ "dc_title_s": "Dabao Kinbōzu, Maps Index",
5
+ "dc_description_s": "This polygon GeoJSON file is an index to 1:50000 scale maps of Davao (Philippines), titled 'Dabao Kinbōzu -- ダバオ近傍圖/Dabao Kinbōzu.’ This map series was originally produced by the Japanese Land Survey Department of the General Staff Headquarters in 1944. Stanford University Libraries holds a large collection of Japanese military and imperial maps, referred to as gaihōzu, or \"maps of outer lands.\" These maps were produced starting in the early Meiji (1868-1912) era and the end of World War II by the Land Survey Department of the General Staff Headquarters, the former Japanese Army. The Library is in the process of scanning and making available all of the maps in the collection. To create this index, footprints were generated using the fishnet tool, and metadata were supplied for the digitized paper maps by Stanford University Libraries. After the footprints were created, the GeoJSON was trimmed and labeled according to the sources.This layer provides an index map that can be used to locate individual scanned map sheets.",
6
+ "dc_rights_s": "Public",
7
+ "dct_provenance_s": "Stanford",
8
+ "dct_references_s": "{\"http://schema.org/url\":\"http://purl.stanford.edu/fb897vt9938\",\"http://schema.org/downloadUrl\":\"https://gist.githubusercontent.com/mejackreed/4a44f1f7cc4fbb926068738e903a9e96/raw/fedfb0e599d647920f084627b7dca8f88a358757/stanford-fb897vt9938.geojson\",\"http://www.loc.gov/mods/v3\":\"http://purl.stanford.edu/fb897vt9938.mods\",\"http://www.isotc211.org/schemas/2005/gmd/\":\"http://opengeometadata.stanford.edu/metadata/edu.stanford.purl/druid:fb897vt9938/iso19139.xml\",\"http://www.w3.org/1999/xhtml\":\"http://opengeometadata.stanford.edu/metadata/edu.stanford.purl/druid:fb897vt9938/default.html\",\"https://openindexmaps.org\": \"https://gist.githubusercontent.com/mejackreed/4a44f1f7cc4fbb926068738e903a9e96/raw/fedfb0e599d647920f084627b7dca8f88a358757/stanford-fb897vt9938.geojson\"}",
9
+ "layer_id_s": "druid:fb897vt9938",
10
+ "layer_slug_s": "stanford-fb897vt9938",
11
+ "layer_geom_type_s": "Polygon",
12
+ "layer_modified_dt": "2016-10-20T21:07:24Z",
13
+ "dc_format_s": "GeoJSON",
14
+ "dc_language_s": "English",
15
+ "dc_type_s": "Dataset",
16
+ "dc_publisher_s": "Stanford Digital Repository",
17
+ "dc_creator_sm": [
18
+ "Stanford Geospatial Center"
19
+ ],
20
+ "dc_subject_sm": [
21
+ "Military maps",
22
+ "Topographic maps",
23
+ "Index maps",
24
+ "Grids (Cartography)",
25
+ "Boundaries",
26
+ "Military"
27
+ ],
28
+ "dct_issued_s": "2016",
29
+ "dct_temporal_sm": [
30
+ "1944"
31
+ ],
32
+ "dct_spatial_sm": [
33
+ "Davao (Philippines)"
34
+ ],
35
+ "georss_box_s": "6.6666 125 7.3333 126",
36
+ "georss_polygon_s": "6.6666 125 7.3333 125 7.3333 126 6.6666 126 6.6666 125",
37
+ "solr_geom": "ENVELOPE(125, 126, 7.3333, 6.6666)",
38
+ "solr_year_i": 1944,
39
+ "stanford_rights_metadata_s": "<?xml version=\"1.0\"?>\n<rightsMetadata>\n <access type=\"discover\">\n <machine>\n <world/>\n </machine>\n </access>\n <access type=\"read\">\n <machine>\n <world/>\n </machine>\n </access>\n <use>\n <human type=\"useAndReproduction\">This item is in the public domain. There are no restrictions on use.</human>\n <human type=\"creativeCommons\"/>\n <machine type=\"creativeCommons\"/>\n </use>\n <copyright>\n <human>This work is in the Public Domain, meaning that it is not subject to copyright.</human>\n </copyright>\n</rightsMetadata>\n"
40
+ }
@@ -49,5 +49,15 @@ describe Geoblacklight::ItemViewer do
49
49
  expect(item_viewer.viewer_preference).to eq tiled_map_layer: 'http://www.example.com/MapServer'
50
50
  end
51
51
  end
52
+ context 'index map' do
53
+ let(:document_attributes) do
54
+ {
55
+ references_field => {
56
+ 'https://openindexmaps.org' => 'http://www.example.com/index_map'
57
+ }.to_json
58
+ }
59
+ end
60
+ it { expect(item_viewer.viewer_preference).to eq index_map: 'http://www.example.com/index_map' }
61
+ end
52
62
  end
53
63
  end
@@ -0,0 +1,564 @@
1
+ /*
2
+ Leaflet.label, a plugin that adds labels to markers and vectors for Leaflet powered maps.
3
+ (c) 2012-2013, Jacob Toye, Smartrak
4
+
5
+ https://github.com/Leaflet/Leaflet.label
6
+ http://leafletjs.com
7
+ https://github.com/jacobtoye
8
+ */
9
+ (function (factory, window) {
10
+
11
+ // define an AMD module that relies on 'leaflet'
12
+ if (typeof define === 'function' && define.amd) {
13
+ define(['leaflet'], factory);
14
+
15
+ // define a Common JS module that relies on 'leaflet'
16
+ } else if (typeof exports === 'object') {
17
+ module.exports = factory(require('leaflet'));
18
+ }
19
+
20
+ // attach your plugin to the global 'L' variable
21
+ if (typeof window !== 'undefined' && window.L) {
22
+ window.LeafletLabel = factory(L);
23
+ }
24
+ }(function (L) {
25
+ L.labelVersion = '0.2.4';
26
+
27
+
28
+ var LeafletLabel = L.Class.extend({
29
+
30
+ includes: L.Mixin.Events,
31
+
32
+ options: {
33
+ className: '',
34
+ clickable: false,
35
+ direction: 'right',
36
+ noHide: false,
37
+ offset: [12, -15], // 6 (width of the label triangle) + 6 (padding)
38
+ opacity: 1,
39
+ zoomAnimation: true
40
+ },
41
+
42
+ initialize: function (options, source) {
43
+ L.setOptions(this, options);
44
+
45
+ this._source = source;
46
+ this._animated = L.Browser.any3d && this.options.zoomAnimation;
47
+ this._isOpen = false;
48
+ },
49
+
50
+ onAdd: function (map) {
51
+ this._map = map;
52
+
53
+ this._pane = this.options.pane ? map._panes[this.options.pane] :
54
+ this._source instanceof L.Marker ? map._panes.markerPane : map._panes.popupPane;
55
+
56
+ if (!this._container) {
57
+ this._initLayout();
58
+ }
59
+
60
+ this._pane.appendChild(this._container);
61
+
62
+ this._initInteraction();
63
+
64
+ this._update();
65
+
66
+ this.setOpacity(this.options.opacity);
67
+
68
+ map
69
+ .on('moveend', this._onMoveEnd, this)
70
+ .on('viewreset', this._onViewReset, this);
71
+
72
+ if (this._animated) {
73
+ map.on('zoomanim', this._zoomAnimation, this);
74
+ }
75
+
76
+ if (L.Browser.touch && !this.options.noHide) {
77
+ L.DomEvent.on(this._container, 'click', this.close, this);
78
+ map.on('click', this.close, this);
79
+ }
80
+ },
81
+
82
+ onRemove: function (map) {
83
+ this._pane.removeChild(this._container);
84
+
85
+ map.off({
86
+ zoomanim: this._zoomAnimation,
87
+ moveend: this._onMoveEnd,
88
+ viewreset: this._onViewReset
89
+ }, this);
90
+
91
+ this._removeInteraction();
92
+
93
+ this._map = null;
94
+ },
95
+
96
+ setLatLng: function (latlng) {
97
+ this._latlng = L.latLng(latlng);
98
+ if (this._map) {
99
+ this._updatePosition();
100
+ }
101
+ return this;
102
+ },
103
+
104
+ setContent: function (content) {
105
+ // Backup previous content and store new content
106
+ this._previousContent = this._content;
107
+ this._content = content;
108
+
109
+ this._updateContent();
110
+
111
+ return this;
112
+ },
113
+
114
+ close: function () {
115
+ var map = this._map;
116
+
117
+ if (map) {
118
+ if (L.Browser.touch && !this.options.noHide) {
119
+ L.DomEvent.off(this._container, 'click', this.close);
120
+ map.off('click', this.close, this);
121
+ }
122
+
123
+ map.removeLayer(this);
124
+ }
125
+ },
126
+
127
+ updateZIndex: function (zIndex) {
128
+ this._zIndex = zIndex;
129
+
130
+ if (this._container && this._zIndex) {
131
+ this._container.style.zIndex = zIndex;
132
+ }
133
+ },
134
+
135
+ setOpacity: function (opacity) {
136
+ this.options.opacity = opacity;
137
+
138
+ if (this._container) {
139
+ L.DomUtil.setOpacity(this._container, opacity);
140
+ }
141
+ },
142
+
143
+ _initLayout: function () {
144
+ this._container = L.DomUtil.create('div', 'leaflet-label ' + this.options.className + ' leaflet-zoom-animated');
145
+ this.updateZIndex(this._zIndex);
146
+ },
147
+
148
+ _update: function () {
149
+ if (!this._map) { return; }
150
+
151
+ this._container.style.visibility = 'hidden';
152
+
153
+ this._updateContent();
154
+ this._updatePosition();
155
+
156
+ this._container.style.visibility = '';
157
+ },
158
+
159
+ _updateContent: function () {
160
+ if (!this._content || !this._map || this._prevContent === this._content) {
161
+ return;
162
+ }
163
+
164
+ if (typeof this._content === 'string') {
165
+ this._container.innerHTML = this._content;
166
+
167
+ this._prevContent = this._content;
168
+
169
+ this._labelWidth = this._container.offsetWidth;
170
+ }
171
+ },
172
+
173
+ _updatePosition: function () {
174
+ var pos = this._map.latLngToLayerPoint(this._latlng);
175
+
176
+ this._setPosition(pos);
177
+ },
178
+
179
+ _setPosition: function (pos) {
180
+ var map = this._map,
181
+ container = this._container,
182
+ centerPoint = map.latLngToContainerPoint(map.getCenter()),
183
+ labelPoint = map.layerPointToContainerPoint(pos),
184
+ direction = this.options.direction,
185
+ labelWidth = this._labelWidth,
186
+ offset = L.point(this.options.offset);
187
+
188
+ // position to the right (right or auto & needs to)
189
+ if (direction === 'right' || direction === 'auto' && labelPoint.x < centerPoint.x) {
190
+ L.DomUtil.addClass(container, 'leaflet-label-right');
191
+ L.DomUtil.removeClass(container, 'leaflet-label-left');
192
+
193
+ pos = pos.add(offset);
194
+ } else { // position to the left
195
+ L.DomUtil.addClass(container, 'leaflet-label-left');
196
+ L.DomUtil.removeClass(container, 'leaflet-label-right');
197
+
198
+ pos = pos.add(L.point(-offset.x - labelWidth, offset.y));
199
+ }
200
+
201
+ L.DomUtil.setPosition(container, pos);
202
+ },
203
+
204
+ _zoomAnimation: function (opt) {
205
+ var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
206
+
207
+ this._setPosition(pos);
208
+ },
209
+
210
+ _onMoveEnd: function () {
211
+ if (!this._animated || this.options.direction === 'auto') {
212
+ this._updatePosition();
213
+ }
214
+ },
215
+
216
+ _onViewReset: function (e) {
217
+ /* if map resets hard, we must update the label */
218
+ if (e && e.hard) {
219
+ this._update();
220
+ }
221
+ },
222
+
223
+ _initInteraction: function () {
224
+ if (!this.options.clickable) { return; }
225
+
226
+ var container = this._container,
227
+ events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu'];
228
+
229
+ L.DomUtil.addClass(container, 'leaflet-clickable');
230
+ L.DomEvent.on(container, 'click', this._onMouseClick, this);
231
+
232
+ for (var i = 0; i < events.length; i++) {
233
+ L.DomEvent.on(container, events[i], this._fireMouseEvent, this);
234
+ }
235
+ },
236
+
237
+ _removeInteraction: function () {
238
+ if (!this.options.clickable) { return; }
239
+
240
+ var container = this._container,
241
+ events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu'];
242
+
243
+ L.DomUtil.removeClass(container, 'leaflet-clickable');
244
+ L.DomEvent.off(container, 'click', this._onMouseClick, this);
245
+
246
+ for (var i = 0; i < events.length; i++) {
247
+ L.DomEvent.off(container, events[i], this._fireMouseEvent, this);
248
+ }
249
+ },
250
+
251
+ _onMouseClick: function (e) {
252
+ if (this.hasEventListeners(e.type)) {
253
+ L.DomEvent.stopPropagation(e);
254
+ }
255
+
256
+ this.fire(e.type, {
257
+ originalEvent: e
258
+ });
259
+ },
260
+
261
+ _fireMouseEvent: function (e) {
262
+ this.fire(e.type, {
263
+ originalEvent: e
264
+ });
265
+
266
+ // TODO proper custom event propagation
267
+ // this line will always be called if marker is in a FeatureGroup
268
+ if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) {
269
+ L.DomEvent.preventDefault(e);
270
+ }
271
+ if (e.type !== 'mousedown') {
272
+ L.DomEvent.stopPropagation(e);
273
+ } else {
274
+ L.DomEvent.preventDefault(e);
275
+ }
276
+ }
277
+ });
278
+
279
+
280
+ /*global LeafletLabel */
281
+
282
+ // This object is a mixin for L.Marker and L.CircleMarker. We declare it here as both need to include the contents.
283
+ L.BaseMarkerMethods = {
284
+ showLabel: function () {
285
+ if (this.label && this._map) {
286
+ this.label.setLatLng(this._latlng);
287
+ this._map.showLabel(this.label);
288
+ }
289
+
290
+ return this;
291
+ },
292
+
293
+ hideLabel: function () {
294
+ if (this.label) {
295
+ this.label.close();
296
+ }
297
+ return this;
298
+ },
299
+
300
+ setLabelNoHide: function (noHide) {
301
+ if (this._labelNoHide === noHide) {
302
+ return;
303
+ }
304
+
305
+ this._labelNoHide = noHide;
306
+
307
+ if (noHide) {
308
+ this._removeLabelRevealHandlers();
309
+ this.showLabel();
310
+ } else {
311
+ this._addLabelRevealHandlers();
312
+ this.hideLabel();
313
+ }
314
+ },
315
+
316
+ bindLabel: function (content, options) {
317
+ var labelAnchor = this.options.icon ? this.options.icon.options.labelAnchor : this.options.labelAnchor,
318
+ anchor = L.point(labelAnchor) || L.point(0, 0);
319
+
320
+ anchor = anchor.add(LeafletLabel.prototype.options.offset);
321
+
322
+ if (options && options.offset) {
323
+ anchor = anchor.add(options.offset);
324
+ }
325
+
326
+ options = L.Util.extend({offset: anchor}, options);
327
+
328
+ this._labelNoHide = options.noHide;
329
+
330
+ if (!this.label) {
331
+ if (!this._labelNoHide) {
332
+ this._addLabelRevealHandlers();
333
+ }
334
+
335
+ this
336
+ .on('remove', this.hideLabel, this)
337
+ .on('move', this._moveLabel, this)
338
+ .on('add', this._onMarkerAdd, this);
339
+
340
+ this._hasLabelHandlers = true;
341
+ }
342
+
343
+ this.label = new LeafletLabel(options, this)
344
+ .setContent(content);
345
+
346
+ return this;
347
+ },
348
+
349
+ unbindLabel: function () {
350
+ if (this.label) {
351
+ this.hideLabel();
352
+
353
+ this.label = null;
354
+
355
+ if (this._hasLabelHandlers) {
356
+ if (!this._labelNoHide) {
357
+ this._removeLabelRevealHandlers();
358
+ }
359
+
360
+ this
361
+ .off('remove', this.hideLabel, this)
362
+ .off('move', this._moveLabel, this)
363
+ .off('add', this._onMarkerAdd, this);
364
+ }
365
+
366
+ this._hasLabelHandlers = false;
367
+ }
368
+ return this;
369
+ },
370
+
371
+ updateLabelContent: function (content) {
372
+ if (this.label) {
373
+ this.label.setContent(content);
374
+ }
375
+ },
376
+
377
+ getLabel: function () {
378
+ return this.label;
379
+ },
380
+
381
+ _onMarkerAdd: function () {
382
+ if (this._labelNoHide) {
383
+ this.showLabel();
384
+ }
385
+ },
386
+
387
+ _addLabelRevealHandlers: function () {
388
+ this
389
+ .on('mouseover', this.showLabel, this)
390
+ .on('mouseout', this.hideLabel, this);
391
+
392
+ if (L.Browser.touch) {
393
+ this.on('click', this.showLabel, this);
394
+ }
395
+ },
396
+
397
+ _removeLabelRevealHandlers: function () {
398
+ this
399
+ .off('mouseover', this.showLabel, this)
400
+ .off('mouseout', this.hideLabel, this);
401
+
402
+ if (L.Browser.touch) {
403
+ this.off('click', this.showLabel, this);
404
+ }
405
+ },
406
+
407
+ _moveLabel: function (e) {
408
+ this.label.setLatLng(e.latlng);
409
+ }
410
+ };
411
+
412
+
413
+ // Add in an option to icon that is used to set where the label anchor is
414
+ L.Icon.Default.mergeOptions({
415
+ labelAnchor: new L.Point(9, -20)
416
+ });
417
+
418
+ // Have to do this since Leaflet is loaded before this plugin and initializes
419
+ // L.Marker.options.icon therefore missing our mixin above.
420
+ L.Marker.mergeOptions({
421
+ icon: new L.Icon.Default()
422
+ });
423
+
424
+ L.Marker.include(L.BaseMarkerMethods);
425
+ L.Marker.include({
426
+ _originalUpdateZIndex: L.Marker.prototype._updateZIndex,
427
+
428
+ _updateZIndex: function (offset) {
429
+ var zIndex = this._zIndex + offset;
430
+
431
+ this._originalUpdateZIndex(offset);
432
+
433
+ if (this.label) {
434
+ this.label.updateZIndex(zIndex);
435
+ }
436
+ },
437
+
438
+ _originalSetOpacity: L.Marker.prototype.setOpacity,
439
+
440
+ setOpacity: function (opacity, labelHasSemiTransparency) {
441
+ this.options.labelHasSemiTransparency = labelHasSemiTransparency;
442
+
443
+ this._originalSetOpacity(opacity);
444
+ },
445
+
446
+ _originalUpdateOpacity: L.Marker.prototype._updateOpacity,
447
+
448
+ _updateOpacity: function () {
449
+ var absoluteOpacity = this.options.opacity === 0 ? 0 : 1;
450
+
451
+ this._originalUpdateOpacity();
452
+
453
+ if (this.label) {
454
+ this.label.setOpacity(this.options.labelHasSemiTransparency ? this.options.opacity : absoluteOpacity);
455
+ }
456
+ },
457
+
458
+ _originalSetLatLng: L.Marker.prototype.setLatLng,
459
+
460
+ setLatLng: function (latlng) {
461
+ if (this.label && !this._labelNoHide) {
462
+ this.hideLabel();
463
+ }
464
+
465
+ return this._originalSetLatLng(latlng);
466
+ }
467
+ });
468
+
469
+ // Add in an option to icon that is used to set where the label anchor is
470
+ L.CircleMarker.mergeOptions({
471
+ labelAnchor: new L.Point(0, 0)
472
+ });
473
+
474
+
475
+ L.CircleMarker.include(L.BaseMarkerMethods);
476
+
477
+ /*global LeafletLabel */
478
+
479
+ L.Path.include({
480
+ bindLabel: function (content, options) {
481
+ if (!this.label || this.label.options !== options) {
482
+ this.label = new LeafletLabel(options, this);
483
+ }
484
+
485
+ this.label.setContent(content);
486
+
487
+ if (!this._showLabelAdded) {
488
+ this
489
+ .on('mouseover', this._showLabel, this)
490
+ .on('mousemove', this._moveLabel, this)
491
+ .on('mouseout remove', this._hideLabel, this);
492
+
493
+ if (L.Browser.touch) {
494
+ this.on('click', this._showLabel, this);
495
+ }
496
+ this._showLabelAdded = true;
497
+ }
498
+
499
+ return this;
500
+ },
501
+
502
+ unbindLabel: function () {
503
+ if (this.label) {
504
+ this._hideLabel();
505
+ this.label = null;
506
+ this._showLabelAdded = false;
507
+ this
508
+ .off('mouseover', this._showLabel, this)
509
+ .off('mousemove', this._moveLabel, this)
510
+ .off('mouseout remove', this._hideLabel, this);
511
+ }
512
+ return this;
513
+ },
514
+
515
+ updateLabelContent: function (content) {
516
+ if (this.label) {
517
+ this.label.setContent(content);
518
+ }
519
+ },
520
+
521
+ _showLabel: function (e) {
522
+ this.label.setLatLng(e.latlng);
523
+ this._map.showLabel(this.label);
524
+ },
525
+
526
+ _moveLabel: function (e) {
527
+ this.label.setLatLng(e.latlng);
528
+ },
529
+
530
+ _hideLabel: function () {
531
+ this.label.close();
532
+ }
533
+ });
534
+
535
+
536
+ L.Map.include({
537
+ showLabel: function (label) {
538
+ return this.addLayer(label);
539
+ }
540
+ });
541
+
542
+ L.FeatureGroup.include({
543
+ // TODO: remove this when AOP is supported in Leaflet, need this as we cannot put code in removeLayer()
544
+ clearLayers: function () {
545
+ this.unbindLabel();
546
+ this.eachLayer(this.removeLayer, this);
547
+ return this;
548
+ },
549
+
550
+ bindLabel: function (content, options) {
551
+ return this.invoke('bindLabel', content, options);
552
+ },
553
+
554
+ unbindLabel: function () {
555
+ return this.invoke('unbindLabel');
556
+ },
557
+
558
+ updateLabelContent: function (content) {
559
+ this.invoke('updateLabelContent', content);
560
+ }
561
+ });
562
+
563
+ return LeafletLabel;
564
+ }, window));
@@ -0,0 +1,54 @@
1
+ .leaflet-label {
2
+ background: rgb(235, 235, 235);
3
+ background: rgba(235, 235, 235, 0.81);
4
+ background-clip: padding-box;
5
+ border-color: #777;
6
+ border-color: rgba(0,0,0,0.25);
7
+ border-radius: 4px;
8
+ border-style: solid;
9
+ border-width: 4px;
10
+ color: #111;
11
+ display: block;
12
+ font: 12px/20px "Helvetica Neue", Arial, Helvetica, sans-serif;
13
+ font-weight: bold;
14
+ padding: 1px 6px;
15
+ position: absolute;
16
+ -webkit-user-select: none;
17
+ -moz-user-select: none;
18
+ -ms-user-select: none;
19
+ user-select: none;
20
+ pointer-events: none;
21
+ white-space: nowrap;
22
+ z-index: 6;
23
+ }
24
+
25
+ .leaflet-label.leaflet-clickable {
26
+ cursor: pointer;
27
+ pointer-events: auto;
28
+ }
29
+
30
+ .leaflet-label:before,
31
+ .leaflet-label:after {
32
+ border-top: 6px solid transparent;
33
+ border-bottom: 6px solid transparent;
34
+ content: none;
35
+ position: absolute;
36
+ top: 5px;
37
+ }
38
+
39
+ .leaflet-label:before {
40
+ border-right: 6px solid black;
41
+ border-right-color: inherit;
42
+ left: -10px;
43
+ }
44
+
45
+ .leaflet-label:after {
46
+ border-left: 6px solid black;
47
+ border-left-color: inherit;
48
+ right: -10px;
49
+ }
50
+
51
+ .leaflet-label-right:before,
52
+ .leaflet-label-left:after {
53
+ content: "";
54
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoblacklight
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Graves
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-01-22 00:00:00.000000000 Z
14
+ date: 2018-01-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -181,6 +181,20 @@ dependencies:
181
181
  - - ">="
182
182
  - !ruby/object:Gem::Version
183
183
  version: '0'
184
+ - !ruby/object:Gem::Dependency
185
+ name: handlebars_assets
186
+ requirement: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ type: :runtime
192
+ prerelease: false
193
+ version_requirements: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
184
198
  - !ruby/object:Gem::Dependency
185
199
  name: solr_wrapper
186
200
  requirement: !ruby/object:Gem::Requirement
@@ -355,6 +369,7 @@ files:
355
369
  - app/assets/javascripts/geoblacklight/modules/relations.js
356
370
  - app/assets/javascripts/geoblacklight/modules/results.js
357
371
  - app/assets/javascripts/geoblacklight/modules/util.js
372
+ - app/assets/javascripts/geoblacklight/templates/index_map_info.hbs
358
373
  - app/assets/javascripts/geoblacklight/viewers.js
359
374
  - app/assets/javascripts/geoblacklight/viewers/esri.js
360
375
  - app/assets/javascripts/geoblacklight/viewers/esri/dynamic_map_layer.js
@@ -362,6 +377,7 @@ files:
362
377
  - app/assets/javascripts/geoblacklight/viewers/esri/image_map_layer.js
363
378
  - app/assets/javascripts/geoblacklight/viewers/esri/tiled_map_layer.js
364
379
  - app/assets/javascripts/geoblacklight/viewers/iiif.js
380
+ - app/assets/javascripts/geoblacklight/viewers/index_map.js
365
381
  - app/assets/javascripts/geoblacklight/viewers/map.js
366
382
  - app/assets/javascripts/geoblacklight/viewers/viewer.js
367
383
  - app/assets/javascripts/geoblacklight/viewers/wms.js
@@ -416,6 +432,7 @@ files:
416
432
  - app/views/catalog/_show_default.html.erb
417
433
  - app/views/catalog/_show_default_attribute_table.html.erb
418
434
  - app/views/catalog/_show_default_viewer_container.html.erb
435
+ - app/views/catalog/_show_default_viewer_information.html.erb
419
436
  - app/views/catalog/_show_header_default.html.erb
420
437
  - app/views/catalog/_upper_metadata.html.erb
421
438
  - app/views/catalog/_web_services.html.erb
@@ -511,6 +528,7 @@ files:
511
528
  - spec/features/exports_spec.rb
512
529
  - spec/features/home_page_spec.rb
513
530
  - spec/features/iiif_viewer_spec.rb
531
+ - spec/features/index_map_spec.rb
514
532
  - spec/features/layer_inspection_spec.rb
515
533
  - spec/features/layer_opacity_spec.rb
516
534
  - spec/features/layer_preview_spec.rb
@@ -539,6 +557,7 @@ files:
539
557
  - spec/fixtures/solr_documents/esri-tiled_map_layer.json
540
558
  - spec/fixtures/solr_documents/esri-wms-layer.json
541
559
  - spec/fixtures/solr_documents/harvard_raster.json
560
+ - spec/fixtures/solr_documents/index-map-stanford.json
542
561
  - spec/fixtures/solr_documents/no_spatial.json
543
562
  - spec/fixtures/solr_documents/public_direct_download.json
544
563
  - spec/fixtures/solr_documents/public_iiif_princeton.json
@@ -602,8 +621,10 @@ files:
602
621
  - template.rb
603
622
  - vendor/assets/javascripts/esri-leaflet.js
604
623
  - vendor/assets/javascripts/leaflet-iiif.js
624
+ - vendor/assets/javascripts/leaflet-label-src.js
605
625
  - vendor/assets/javascripts/native.history.js
606
626
  - vendor/assets/javascripts/readmore.min.js
627
+ - vendor/assets/stylesheets/leaflet-label.css
607
628
  homepage: http://github.com/geoblacklight/geoblacklight
608
629
  licenses:
609
630
  - Apache 2.0
@@ -643,6 +664,7 @@ test_files:
643
664
  - spec/features/exports_spec.rb
644
665
  - spec/features/home_page_spec.rb
645
666
  - spec/features/iiif_viewer_spec.rb
667
+ - spec/features/index_map_spec.rb
646
668
  - spec/features/layer_inspection_spec.rb
647
669
  - spec/features/layer_opacity_spec.rb
648
670
  - spec/features/layer_preview_spec.rb
@@ -671,6 +693,7 @@ test_files:
671
693
  - spec/fixtures/solr_documents/esri-tiled_map_layer.json
672
694
  - spec/fixtures/solr_documents/esri-wms-layer.json
673
695
  - spec/fixtures/solr_documents/harvard_raster.json
696
+ - spec/fixtures/solr_documents/index-map-stanford.json
674
697
  - spec/fixtures/solr_documents/no_spatial.json
675
698
  - spec/fixtures/solr_documents/public_direct_download.json
676
699
  - spec/fixtures/solr_documents/public_iiif_princeton.json