administrate-field-lat_lng 1.1.0 → 1.2.0
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 +4 -4
- data/README.md +2 -1
- data/administrate-field-lat_lng.gemspec +1 -1
- data/app/views/fields/lat_lng/_map.html.erb +41 -14
- data/lib/administrate/field/lat_lng.rb +22 -7
- data/vendor/assets/javascripts/leaflet-gplaces-autocomplete-0.0.8.js +144 -0
- data/vendor/assets/stylesheets/leaflet-gplaces-autocomplete-0.0.8.css +43 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d18138c50948b551f8f508f321fa2ab1b7176ff4
|
4
|
+
data.tar.gz: e0b5d83b6e52555ce882889e2cf3a461d2cfa78c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a052e9ad5f71668c3c3fb0fa2586843d08dbc5ec686347e3867c8c1daddfd4e2a0bb007b1c101e33204bcb5d124e82f78f1475a944731170e1dd0ca21e05677
|
7
|
+
data.tar.gz: 2f4c2a81600c7608b402348165c5959ace14b19adca170877cb67a568d56990bea03d9bbbd21d0f5f3ec89ac30f3e73de245113747d1d488a77dd7e25e0761f2
|
data/README.md
CHANGED
@@ -45,6 +45,8 @@ Additional options that are available:
|
|
45
45
|
|
46
46
|
* `initial`: Set to an array like `[53.8003,-1.5519]`. Will cause the center of the map to be this point if the lat/lng have not yet been set (e.g. for new records). Defaults to Leeds, UK (because that's where the author is from).
|
47
47
|
* `zoom`: Set the default zoom level for maps drawn (defaults to 11).
|
48
|
+
* `search`: `true` (default) or `false`. Enable location search. Requires `google_api_key` option too.
|
49
|
+
* `google_api_key`: A [key for the Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript/get-api-key). Required for location search to work.
|
48
50
|
|
49
51
|
## Usage notes
|
50
52
|
|
@@ -59,4 +61,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/fishpe
|
|
59
61
|
## License
|
60
62
|
|
61
63
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
62
|
-
|
@@ -2,6 +2,7 @@
|
|
2
2
|
<div id="latlngmap"></div>
|
3
3
|
</div>
|
4
4
|
<% content_for :javascript do %>
|
5
|
+
<%= content_tag(:script, '', src: "https://maps.googleapis.com/maps/api/js?key=#{field.google_api_key}&libraries=places") if field.search? %>
|
5
6
|
<script type="text/javascript">
|
6
7
|
// Attach a leaflet.js map to the div above
|
7
8
|
var map = L.map('latlngmap');
|
@@ -9,7 +10,24 @@
|
|
9
10
|
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
|
10
11
|
});
|
11
12
|
map.addLayer(osm);
|
12
|
-
|
13
|
+
|
14
|
+
var createMarker = function(latlng) {
|
15
|
+
var icon = new L.Icon.Default();
|
16
|
+
var options = { icon: icon };
|
17
|
+
marker = L.marker(latlng, options);
|
18
|
+
marker.addTo(map);
|
19
|
+
};
|
20
|
+
|
21
|
+
var setMarker = function (latlng) {
|
22
|
+
if (marker === undefined) {
|
23
|
+
createMarker(latlng);
|
24
|
+
} else {
|
25
|
+
marker.setLatLng(latlng);
|
26
|
+
}
|
27
|
+
$('.latlng-lat').val(latlng.lat);
|
28
|
+
$('.latlng-lng').val(latlng.lng);
|
29
|
+
};
|
30
|
+
|
13
31
|
// Get the centre lat/lng from the field or the initial default if the field
|
14
32
|
// hasn't been set yet
|
15
33
|
var latlng = [];
|
@@ -19,28 +37,37 @@
|
|
19
37
|
latlng = [lat, lng];
|
20
38
|
}
|
21
39
|
map.setView(latlng, <%= field.zoom %>);
|
22
|
-
|
40
|
+
|
23
41
|
// Add a marker if the field has been set already
|
24
42
|
var marker;
|
25
43
|
if (lng !== undefined) {
|
26
|
-
|
27
|
-
var options = { icon: icon };
|
28
|
-
marker = L.marker(latlng, options);
|
29
|
-
marker.addTo(map);
|
44
|
+
createMarker(latlng);
|
30
45
|
}
|
31
46
|
<% if edit %>
|
32
47
|
// In edit mode, move the marker and update the fields when a user clicks
|
33
48
|
// inside the map
|
34
49
|
map.on('click', function (e) {
|
35
|
-
|
36
|
-
marker = L.marker(e.latlng);
|
37
|
-
marker.addTo(map);
|
38
|
-
} else {
|
39
|
-
marker.setLatLng(e.latlng);
|
40
|
-
}
|
41
|
-
$('.latlng-lat').val(e.latlng.lat);
|
42
|
-
$('.latlng-lng').val(e.latlng.lng);
|
50
|
+
setMarker(e.latlng);
|
43
51
|
});
|
44
52
|
<% end %>
|
53
|
+
|
54
|
+
<% if field.search? %>
|
55
|
+
new L.Control.GPlaceAutocomplete({
|
56
|
+
callback: function (place) {
|
57
|
+
map.panTo([
|
58
|
+
place.geometry.location.lat(),
|
59
|
+
place.geometry.location.lng()
|
60
|
+
]);
|
61
|
+
|
62
|
+
<% if edit %>
|
63
|
+
setMarker({
|
64
|
+
lat: place.geometry.location.lat(),
|
65
|
+
lng: place.geometry.location.lng(),
|
66
|
+
});
|
67
|
+
<% end %>
|
68
|
+
},
|
69
|
+
})
|
70
|
+
.addTo(map);
|
71
|
+
<% end %>
|
45
72
|
</script>
|
46
73
|
<% end %>
|
@@ -6,10 +6,16 @@ module Administrate
|
|
6
6
|
module Field
|
7
7
|
class LatLng < Base
|
8
8
|
class Engine < ::Rails::Engine
|
9
|
-
|
9
|
+
if config.respond_to? :assets
|
10
|
+
config.assets.precompile << %w(lat_lng.js lat_lng.css)
|
11
|
+
config.assets.precompile << %w(leaflet-gplaces-autocomplete-0.0.8.css leaflet-gplaces-autocomplete-0.0.8.js)
|
12
|
+
end
|
13
|
+
|
10
14
|
if defined?(Administrate::Engine)
|
11
15
|
Administrate::Engine.add_javascript 'lat_lng.js'
|
12
16
|
Administrate::Engine.add_stylesheet 'lat_lng.css'
|
17
|
+
Administrate::Engine.add_javascript 'leaflet-gplaces-autocomplete-0.0.8.js'
|
18
|
+
Administrate::Engine.add_stylesheet 'leaflet-gplaces-autocomplete-0.0.8.css'
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
@@ -17,31 +23,40 @@ module Administrate
|
|
17
23
|
def lat?
|
18
24
|
options.fetch(:lat, attribute == :lat)
|
19
25
|
end
|
20
|
-
|
26
|
+
|
21
27
|
# True if the :lng option has been provided, or field is called :lng
|
22
28
|
def lng?
|
23
29
|
options.fetch(:lng, attribute == :lng)
|
24
30
|
end
|
25
|
-
|
31
|
+
|
32
|
+
# Return wether or not search should be enabled (defaults to true)
|
33
|
+
def search?
|
34
|
+
options.fetch(:search, true) && google_api_key.present?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get Google API Key. How to obtain one: https://developers.google.com/maps/documentation/javascript/get-api-key
|
38
|
+
def google_api_key
|
39
|
+
options.fetch(:google_api_key, nil)
|
40
|
+
end
|
41
|
+
|
26
42
|
# Returns :lat or :lng depending on which type this is
|
27
43
|
def which
|
28
44
|
lat? ? :lat : :lng
|
29
45
|
end
|
30
|
-
|
46
|
+
|
31
47
|
# Returns the initial co-ordinates of blank maps (defaults to Leeds, UK)
|
32
48
|
def initial
|
33
49
|
options.fetch(:initial, [53.8003,-1.5519])
|
34
50
|
end
|
35
|
-
|
51
|
+
|
36
52
|
# Returns the initial zoom level for maps (defaults to 11)
|
37
53
|
def zoom
|
38
54
|
options.fetch(:zoom, 11)
|
39
55
|
end
|
40
|
-
|
56
|
+
|
41
57
|
def to_s
|
42
58
|
data
|
43
59
|
end
|
44
|
-
|
45
60
|
end
|
46
61
|
end
|
47
62
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
(function () {
|
2
|
+
L.GPlaceAutocomplete = {};
|
3
|
+
|
4
|
+
L.Control.GPlaceAutocomplete = L.Control.extend({
|
5
|
+
options: {
|
6
|
+
position: "topright",
|
7
|
+
prepend: true,
|
8
|
+
collapsed_mode: false,
|
9
|
+
autocomplete_options: {}
|
10
|
+
},
|
11
|
+
|
12
|
+
collapsedModeIsExpanded: true,
|
13
|
+
|
14
|
+
autocomplete: null,
|
15
|
+
icon: null,
|
16
|
+
searchBox: null,
|
17
|
+
|
18
|
+
initialize: function (options) {
|
19
|
+
if (options) {
|
20
|
+
L.Util.setOptions(this, options);
|
21
|
+
}
|
22
|
+
if (!this.options.callback) {
|
23
|
+
this.options.callback = this.onLocationComplete;
|
24
|
+
}
|
25
|
+
this._buildContainer();
|
26
|
+
},
|
27
|
+
|
28
|
+
_buildContainer: function () {
|
29
|
+
|
30
|
+
// build structure
|
31
|
+
this.container = L.DomUtil.create("div", "leaflet-gac-container leaflet-bar");
|
32
|
+
var searchWrapper = L.DomUtil.create("div", "leaflet-gac-wrapper");
|
33
|
+
this.searchBox = L.DomUtil.create("input", "leaflet-gac-control");
|
34
|
+
this.autocomplete = new google.maps.places.Autocomplete(this.searchBox, this.options.autocomplete_options);
|
35
|
+
|
36
|
+
// if collapse mode set - create icon and register events
|
37
|
+
if (this.options.collapsed_mode) {
|
38
|
+
this.collapsedModeIsExpanded = false;
|
39
|
+
|
40
|
+
this.icon = L.DomUtil.create("div", "leaflet-gac-search-btn");
|
41
|
+
L.DomEvent
|
42
|
+
.on(this.icon, "click", this._showSearchBar, this);
|
43
|
+
|
44
|
+
this.icon.appendChild(
|
45
|
+
L.DomUtil.create("div", "leaflet-gac-search-icon")
|
46
|
+
);
|
47
|
+
|
48
|
+
searchWrapper.appendChild(
|
49
|
+
this.icon
|
50
|
+
);
|
51
|
+
L.DomUtil.addClass(this.searchBox, "leaflet-gac-hidden");
|
52
|
+
}
|
53
|
+
|
54
|
+
searchWrapper.appendChild(
|
55
|
+
this.searchBox
|
56
|
+
);
|
57
|
+
// create and bind autocomplete
|
58
|
+
this.container.appendChild(
|
59
|
+
searchWrapper
|
60
|
+
);
|
61
|
+
|
62
|
+
},
|
63
|
+
|
64
|
+
//***
|
65
|
+
// Collapse mode callbacks
|
66
|
+
//***
|
67
|
+
|
68
|
+
_showSearchBar: function () {
|
69
|
+
this._toggleSearch(true);
|
70
|
+
},
|
71
|
+
|
72
|
+
_hideSearchBar: function () {
|
73
|
+
// if element is expanded, we need to change expanded flag and call collapse handler
|
74
|
+
if (this.collapsedModeIsExpanded) {
|
75
|
+
this._toggleSearch(false);
|
76
|
+
}
|
77
|
+
},
|
78
|
+
|
79
|
+
_toggleSearch: function (shouldDisplaySearch) {
|
80
|
+
if (shouldDisplaySearch) {
|
81
|
+
L.DomUtil.removeClass(this.searchBox, "leaflet-gac-hidden");
|
82
|
+
L.DomUtil.addClass(this.icon, "leaflet-gac-hidden");
|
83
|
+
this.searchBox.focus();
|
84
|
+
} else {
|
85
|
+
L.DomUtil.addClass(this.searchBox, "leaflet-gac-hidden");
|
86
|
+
L.DomUtil.removeClass(this.icon, "leaflet-gac-hidden");
|
87
|
+
}
|
88
|
+
this.collapsedModeIsExpanded = shouldDisplaySearch;
|
89
|
+
},
|
90
|
+
|
91
|
+
//***
|
92
|
+
// Default success callback
|
93
|
+
//***
|
94
|
+
|
95
|
+
onLocationComplete: function (place, map) {
|
96
|
+
// default callback
|
97
|
+
if (!place.geometry) {
|
98
|
+
alert("Location not found");
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
map.panTo([
|
102
|
+
place.geometry.location.lat(),
|
103
|
+
place.geometry.location.lng()
|
104
|
+
]);
|
105
|
+
|
106
|
+
},
|
107
|
+
|
108
|
+
onAdd: function () {
|
109
|
+
// stop propagation of click events
|
110
|
+
L.DomEvent.addListener(this.container, 'click', L.DomEvent.stop);
|
111
|
+
L.DomEvent.disableClickPropagation(this.container);
|
112
|
+
if (this.options.collapsed_mode) {
|
113
|
+
// if collapse mode - register handler
|
114
|
+
this._map.on('dragstart click', this._hideSearchBar, this);
|
115
|
+
}
|
116
|
+
return this.container;
|
117
|
+
},
|
118
|
+
|
119
|
+
addTo: function (map) {
|
120
|
+
this._map = map;
|
121
|
+
|
122
|
+
var container = this._container = this.onAdd(map),
|
123
|
+
pos = this.options.position,
|
124
|
+
corner = map._controlCorners[pos];
|
125
|
+
|
126
|
+
L.DomUtil.addClass(container, 'leaflet-control');
|
127
|
+
if (this.options.prepend) {
|
128
|
+
corner.insertBefore(container, corner.firstChild);
|
129
|
+
} else {
|
130
|
+
corner.appendChild(container)
|
131
|
+
}
|
132
|
+
|
133
|
+
var callback = this.options.callback;
|
134
|
+
var _this = this;
|
135
|
+
google.maps.event.addListener(this.autocomplete, "place_changed", function () {
|
136
|
+
callback(_this.autocomplete.getPlace(), map);
|
137
|
+
});
|
138
|
+
|
139
|
+
return this;
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
});
|
144
|
+
})();
|
@@ -0,0 +1,43 @@
|
|
1
|
+
.leaflet-gac-wrapper {
|
2
|
+
height: 30px;
|
3
|
+
}
|
4
|
+
|
5
|
+
.leaflet-control-container .leaflet-gac-control {
|
6
|
+
width: 300px;
|
7
|
+
height: 30px;
|
8
|
+
padding: 0 7px;
|
9
|
+
border-radius: 5px;
|
10
|
+
border: 1px #d0d0d0 solid;
|
11
|
+
}
|
12
|
+
|
13
|
+
.leaflet-control-container .leaflet-right .leaflet-gac-control {
|
14
|
+
position: absolute;
|
15
|
+
right: 0;
|
16
|
+
transition: width .3s ease .15s;
|
17
|
+
}
|
18
|
+
|
19
|
+
.leaflet-control-container .leaflet-gac-control:focus {
|
20
|
+
outline: none;
|
21
|
+
}
|
22
|
+
|
23
|
+
.leaflet-control-container .leaflet-gac-search-btn {
|
24
|
+
background: #fff;
|
25
|
+
width: 30px;
|
26
|
+
height: 30px;
|
27
|
+
border-radius: 4px;
|
28
|
+
}
|
29
|
+
|
30
|
+
.leaflet-control-container .leaflet-gac-search-btn .leaflet-gac-search-icon {
|
31
|
+
cursor: pointer;
|
32
|
+
width: 100%;
|
33
|
+
height: 100%;
|
34
|
+
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABOUlEQVQ4T6XTLUgmQRgH8N+Ligd+FOu1ww+wKPhxlwxXxHYnqCAGQZtgMBgU4eWaXLhyCgYxiAYVk6igJotgEaNiNYgGL6kHJwOzsO+yGzw3zszzm5nnP1vyzq+UU9+JUbTiCWdYw13eXmmgCr8wlbPwERPYys6lgVA8jSvM4RQfMIQF1KIfR2kkAdpxiRv04CGzUx9OcI02/EvmE+AH5jGG9YK+bmMQ3TjPApsYQXPcJc+Ywc/Y4I0ssIpxdOCi4ATl2Ivv2M0Ck1jBImZzgOrYoxZ8xG0WqI9Hb4pX2UkhNViKMe5jIC+FMPYVezGu4xhjHb7hUyx6wXDeFRK0C79jlMnYX4SmhZfZiwok7ymHwpBGyPs5RnaPRhzicxopAop+sYAc4Av+BPStQIAbsByffPl/gIrTvQLbJDoR8K3H6QAAAABJRU5ErkJggg==") no-repeat center center;
|
35
|
+
}
|
36
|
+
|
37
|
+
.leaflet-control-container .leaflet-gac-hidden {
|
38
|
+
opacity: 0;
|
39
|
+
width: 0;
|
40
|
+
height: 0;
|
41
|
+
overflow: hidden;
|
42
|
+
transition: width .3s ease .15s;
|
43
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: administrate-field-lat_lng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rich Daley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02
|
11
|
+
date: 2017-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: administrate
|
@@ -125,6 +125,8 @@ files:
|
|
125
125
|
- app/views/fields/lat_lng/_show.html.erb
|
126
126
|
- app/views/fields/lat_lng/_var.html.erb
|
127
127
|
- lib/administrate/field/lat_lng.rb
|
128
|
+
- vendor/assets/javascripts/leaflet-gplaces-autocomplete-0.0.8.js
|
129
|
+
- vendor/assets/stylesheets/leaflet-gplaces-autocomplete-0.0.8.css
|
128
130
|
homepage: https://github.com/fishpercolator/administrate-field-lat_lng
|
129
131
|
licenses:
|
130
132
|
- MIT
|