kmz_compressor 1.0.6 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79e17ac2936c8d47cc6da99e1629f206f1fb0d4e
4
- data.tar.gz: dd115027b9ace264fa4d1f8a6794099a25cfa992
3
+ metadata.gz: ebde16462c1697fb99bcde921668d7bb36ea5c79
4
+ data.tar.gz: e6e2b43e2e112c910fdd05088274fb5c14d2c169
5
5
  SHA512:
6
- metadata.gz: 334c98a719886b620636e1db952050ca98b12cfd5811c24c463fe5489c80cd757a839bbad4d6e447c62bc16c59a789d09c289e576cbddc94769a82f78125248a
7
- data.tar.gz: cf6c715e44da2f7252763819d3e760b7e698d4c690dde4ff5633da3e743cbd773d04385167670fbee1d4dd84fa7f908ad83698374d222e4c83a9142b0000bca0
6
+ metadata.gz: cced39b8c3f876a615ec6c2b22c6d67c4a51b828e636b08d593e6b53035edf2937943f478aeb57df124594e7e45aa2858702c699417cec3edf9b842790ac1059
7
+ data.tar.gz: c609706c23a23010294500544b3346829918609d88a7ce337284b681a91104244757394a201a054013f4163e63d33f29524f370797a14a380f09f9d03e4a12b8
@@ -1,178 +1,191 @@
1
- MapLayerManager = {
2
- host: location.protocol + "//" + location.host,
3
- layers: [],
4
- loadingCount: 0, // How many layers are being loaded
5
- requestTimestamps: { },
6
- layerLoadingEventName: 'map:layerLoading',
7
- layerLoadedEventName: 'map:layerLoaded',
8
-
9
- // Prime the KMZ cache on the server before unleashing google's many tilemills
10
- cacheAndLoadKMLLayer: function(map, kmlPath, layerName, options) {
11
- var requestTimestamp = new Date;
12
- kmlPath = this.sanitizeURI(kmlPath);
13
-
14
- $.ajax(this.host + kmlPath, {type:'head', complete:function(){
15
- if (!MapLayerManager.requestTimestamps[layerName] || MapLayerManager.requestTimestamps[layerName] < requestTimestamp){
16
- MapLayerManager.requestTimestamps[layerName] = requestTimestamp;
17
- MapLayerManager.loadKMLLayer(map, MapLayerManager.cachedKMZPath(kmlPath), layerName, options)
18
- }
19
- }});
20
- },
21
- loadKMLLayer: function(map, kmlPath, layerName, options) {
22
- // Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
23
- kmlPath = this.sanitizeURI(kmlPath);
24
- options = options || {}
25
- options.map = map;
26
-
27
- var kmlLayer = new google.maps.KmlLayer(this.host + kmlPath, options);
28
- var layer = MapLayerManager.addLayer(layerName, kmlLayer)
29
- this.loadingCount++
30
- $(window.document).trigger({type: this.layerLoadingEventName, layer:layer})
31
-
32
- // Try and catch the defaultviewport_changed event so we can remove the old layer (sometimes this works, sometimes not)
33
- google.maps.event.addListener(kmlLayer, 'defaultviewport_changed', function(){
34
- MapLayerManager.sweep();
35
- });
36
-
37
- // Add a listener to catch clicks and close all info windows on other layers
38
- google.maps.event.addListener(kmlLayer, 'click', function(){
39
- MapLayerManager.everyLayer(function(layer){
40
- if (layer.kml != kmlLayer){ // Don't close this layer's info window
41
- layer.kml.setOptions({suppressInfoWindows:true})
42
- layer.kml.setOptions({suppressInfoWindows:false})
43
- }
44
- })
45
- });
46
- },
47
- // Generates the url of the cached KMZ for the given kmlPath
48
- cachedKMZPath: function(kmlPath){
49
- return '/kmz/' + hex_sha256(kmlPath) + '.kmz'
50
- },
51
- centerWhenLoaded: function(map, layerNames){
52
- var handler = function(){
53
- // If we have no layer names
54
- if (!layerNames || layerNames.length == 0){
55
- layerNames = MapLayerManager.layerNames()
56
- }
1
+ window.MapLayerManager = function(map){
2
+ var map = map;
3
+ var host = location.protocol + "//" + location.host
4
+ var layers = []
5
+ var loadingCount = 0 // How many layers are being loade
6
+ var requestTimestamps = { }
7
+ var layerLoadingEventName = 'map:layerLoading'
8
+ var layerLoadedEventName = 'map:layerLoaded'
57
9
 
58
- if (MapLayerManager.layersLoaded(layerNames)){
59
- $(window.document).unbind(MapLayerManager.layerLoadedEventName, handler)
60
- MapLayerManager.centerOnLayers(map, layerNames);
61
- }
62
- }
10
+ // Prime the KMZ cache on the server before unleashing google's many tilemills
11
+ function cacheAndLoadKMLLayer(kmlPath, layerName, options) {
12
+ var requestTimestamp = new Date;
13
+ kmlPath = sanitizeURI(kmlPath);
63
14
 
64
- $(window.document).bind(this.layerLoadedEventName, handler)
65
- },
66
- // Returns the layer names
67
- layerNames: function(){
68
- return $(this.layers.slice(0)).map(function(){return this.name})
69
- },
70
- addLayer: function(layerName, kml){
71
- this.layers.unshift({name:layerName, kml:kml})
72
- return this.layers[0]
73
- },
74
- getLayer: function(layerName){
75
- var desiredLayer
76
- this.everyLayer(function(layer, index){
77
- if (layer.name == layerName){
78
- desiredLayer = layer
79
- return false;
80
- }
81
- })
82
- return desiredLayer
83
- },
84
- // Shows the layer and returns true, returns false if the layer couldn't be hidden
85
- hideLayer: function(layerName){
86
- var layer = this.getLayer(layerName);
87
- if (layer && layer.kml){
88
- layer.oldMap = layer.kml.getMap();
89
- layer.kml.setMap(null)
90
- layer.hidden = true
91
- return true
92
- } else if (layer) {
93
- layer.hidden = true
94
- } else {
95
- return false
96
- }
97
- },
98
- // Shows the layer and returns true, returns false if the layer couldn't be shown
99
- showLayer: function(layerName){
100
- var layer = this.getLayer(layerName);
101
- if (layer && layer.kml && layer.oldMap){
102
- layer.kml.setMap(layer.oldMap);
103
- layer.oldMap = null
104
- layer.hidden = false
105
- return true
106
- } else {
107
- return false
15
+ $.ajax(host + kmlPath, {type:'head', complete:function(){
16
+ if (!requestTimestamps[layerName] || requestTimestamps[layerName] < requestTimestamp){
17
+ requestTimestamps[layerName] = requestTimestamp;
18
+ loadKMLLayer(cachedKMZPath(kmlPath), layerName, options)
108
19
  }
109
- },
110
- layersLoaded: function(layerNames){
111
- for (var i = 0; i < layerNames.length; i++){
112
- var layer = this.getLayer(layerNames[i]);
113
- if (!layer || !layer.loaded){
114
- return false;
115
- }
116
- }
117
- return true
118
- },
119
- centerOnLayers: function(map, layerNames){
120
- var bounds;
121
-
122
- for (var i = 0; i < layerNames.length; i++){
123
- var layer = this.getLayer(layerNames[i])
124
- if (layer.error){
125
- continue
126
- }
20
+ }});
21
+ }
127
22
 
128
- if (layer.kml.getDefaultViewport().toSpan().toString() != "(180, 360)"){
129
- bounds = bounds || layer.kml.getDefaultViewport();
130
- bounds.union(layer.kml.getDefaultViewport());
131
- }
132
- }
133
- if (bounds){
134
- map.fitBounds(bounds);
23
+ function loadKMLLayer(kmlPath, layerName, options) {
24
+ // Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
25
+ kmlPath = sanitizeURI(kmlPath);
26
+ options = options || {}
27
+ options.map = map;
28
+
29
+ var kmlLayer = new google.maps.KmlLayer(host + kmlPath, options);
30
+ var layer = addLayer(layerName, kmlLayer)
31
+ loadingCount++
32
+ $(window.document).trigger({type: layerLoadingEventName, layer:layer})
33
+
34
+ // Try and catch the defaultviewport_changed event so we can remove the old layer (sometimes this works, sometimes not)
35
+ google.maps.event.addListener(kmlLayer, 'defaultviewport_changed', function(){
36
+ sweep();
37
+ });
38
+
39
+ // Add a listener to catch clicks and close all info windows on other layers
40
+ google.maps.event.addListener(kmlLayer, 'click', function(){
41
+ everyLayer(function(layer){
42
+ if (layer.kml != kmlLayer){ // Don't close this layer's info window
43
+ layer.kml.setOptions({suppressInfoWindows:true})
44
+ layer.kml.setOptions({suppressInfoWindows:false})
45
+ }
46
+ })
47
+ });
48
+ }
49
+
50
+ // Generates the url of the cached KMZ for the given kmlPath
51
+ function cachedKMZPath(kmlPath){
52
+ return '/kmz/' + hex_sha256(kmlPath) + '.kmz'
53
+ }
54
+
55
+ function centerWhenLoaded(layerNamez){
56
+ var handler = function(){
57
+ // If we have no layer names
58
+ if (!layerNamez || layerNamez.length == 0){
59
+ layerNamez = layerNames()
60
+ }
61
+
62
+ if (layersLoaded(layerNamez)){
63
+ $(window.document).unbind(layerLoadedEventName, handler)
64
+ centerOnLayers(layerNamez);
65
+ }
66
+ }
67
+
68
+ $(window.document).bind(layerLoadedEventName, handler)
69
+ }
70
+
71
+ // Returns the layer names
72
+ function layerNames(){
73
+ return $(layers.slice(0)).map(function(){return name})
74
+ }
75
+
76
+ function addLayer(layerName, kml){
77
+ layers.unshift({name:layerName, kml:kml})
78
+ return layers[0]
79
+ }
80
+
81
+ function getLayer(layerName){
82
+ var desiredLayer
83
+ everyLayer(function(layer, index){
84
+ if (layer.name == layerName){
85
+ desiredLayer = layer
86
+ return false;
135
87
  }
136
- },
137
- removeLayer: function(layerName){
138
- this.everyLayer(function(layer, index){
139
- if (layer.name == layerName){
140
- layer.kml.setMap(null)
141
- MapLayerManager.layers.splice(index, 1);
142
- return;
88
+ })
89
+ return desiredLayer
90
+ }
91
+
92
+ // Hides the layer and returns true, returns false if the layer couldn't be hidden, returns nothing if the layer existed but the kml hadn't yet been loaded
93
+ function hideLayer(layerName){
94
+ var layer = getLayer(layerName);
95
+ if (layer && layer.kml){
96
+ layer.oldMap = layer.kml.getMap();
97
+ layer.kml.setMap(null)
98
+ layer.hidden = true
99
+ return true
100
+ } else if (layer) {
101
+ layer.hidden = true
102
+ } else {
103
+ return false
104
+ }
105
+ }
106
+
107
+ // Shows the layer and returns true, returns false if the layer couldn't be shown
108
+ function showLayer(layerName){
109
+ var layer = getLayer(layerName);
110
+ if (layer && layer.kml && layer.oldMap){
111
+ layer.kml.setMap(layer.oldMap);
112
+ layer.oldMap = null
113
+ layer.hidden = false
114
+ return true
115
+ } else {
116
+ return false
117
+ }
118
+ }
119
+
120
+ function layersLoaded(layerNames){
121
+ for (var i = 0; i < layerNames.length; i++){
122
+ var layer = getLayer(layerNames[i]);
123
+ if (!layer || !layer.loaded){
124
+ return false;
143
125
  }
144
- });
145
- },
146
- removeLayers: function(){
147
- this.everyLayer(function(layer){
148
- MapLayerManager.removeLayer(layer.name);
126
+ }
127
+ return true
128
+ }
129
+
130
+ function centerOnLayers(layerNames){
131
+ var bounds;
132
+
133
+ for (var i = 0; i < layerNames.length; i++){
134
+ var layer = getLayer(layerNames[i])
135
+ if (layer.error){
136
+ continue
137
+ }
138
+
139
+ if (layer.kml.getDefaultViewport().toSpan().toString() != "(180, 360)"){
140
+ bounds = bounds || layer.kml.getDefaultViewport();
141
+ bounds.union(layer.kml.getDefaultViewport());
142
+ }
143
+ }
144
+ if (bounds){
145
+ map.fitBounds(bounds);
146
+ }
147
+ }
148
+
149
+ function removeLayer(layerName){
150
+ everyLayer(function(layer, index){
151
+ if (layer.name == layerName){
152
+ layer.kml.setMap(null)
153
+ layers.splice(index, 1);
154
+ return;
155
+ }
156
+ });
157
+ }
158
+
159
+ function removeLayers(){
160
+ everyLayer(function(layer){
161
+ removeLayer(layer.name);
149
162
  })
150
- },
151
- everyLayer: function(fn){
152
- // NOTE: We use an iterator instead of a for loop because modifications to this.layers that occur during iteration can mess us up
163
+ }
164
+ function everyLayer(fn){
165
+ // NOTE: We use an iterator instead of a for loop because modifications to layers that occur during iteration can mess us up
153
166
  // e.g. if we're responding to an event during the loop and the event adds a layer, we may end up re-iterating on a layer we've already processed
154
- $.each(this.layers.slice(0), function(index, layer){
167
+ $.each(layers.slice(0), function(index, layer){
155
168
  fn(layer, index);
156
169
  })
157
- },
170
+ }
158
171
 
159
172
  // Keep layers synced with their state
160
- sweep: function(){
173
+ function sweep(){
161
174
  var foundLayers = [];
162
- this.everyLayer(function(layer, index){
175
+ everyLayer(function(layer, index){
163
176
  var kmlStatus = layer.kml ? layer.kml.getStatus() : null;
164
177
 
165
178
  // If the layer just finished loading
166
179
  if (!layer.loaded && kmlStatus) {
167
- MapLayerManager.loadingCount--
180
+ loadingCount--
168
181
  layer.loaded = true
169
182
  layer.error = kmlStatus == 'OK' ? null : kmlStatus // if there were any errors, record them
170
- $(window.document).trigger({type: MapLayerManager.layerLoadedEventName, layer:layer})
183
+ $(window.document).trigger({type: layerLoadedEventName, layer:layer})
171
184
  }
172
185
 
173
186
  // A layer should be hidden, but the kml is showing, hide it (i.e. correct layers that were hidden before the kml was loaded)
174
187
  if (layer.hidden && layer.loaded && layer.kml.getMap()){
175
- MapLayerManager.hideLayer(layer.name)
188
+ hideLayer(layer.name)
176
189
  }
177
190
 
178
191
  // Remove old layers
@@ -180,18 +193,47 @@ MapLayerManager = {
180
193
  // Don't delete an instance if we haven't yet seen a version of it with status 'OK'
181
194
  if ($.inArray(layer.name, foundLayers) > -1){
182
195
  layer.kml.setMap(null);
183
- MapLayerManager.layers.splice(index, 1);
196
+ layers.splice(index, 1);
184
197
  } else if (layer.loaded) {
185
198
  foundLayers.push(layer.name)
186
199
  }
187
200
  })
188
- },
189
- sanitizeURI: function(uri){
190
- // Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
191
- // Matches the middleware process
192
- return encodeURI(decodeURI(uri))
193
201
  }
194
- };
195
202
 
196
- // Because google events sometimes get missed, we ensure we're up to date every now and again
197
- setInterval(function(){MapLayerManager.sweep()}, 1000)
203
+ // Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
204
+ // Matches the middleware process
205
+ function sanitizeURI(uri){
206
+ var url = $('<a href="' + uri + '"/>')[0]
207
+ var pathname = decodeURI(url.pathname).trim().replace(/^\/\//, '/') // IE will return a path name with a leading double slash, so ensure it's only a single slash
208
+ var search = decodeURIComponent(url.search.replace(/\+/g, '%20')).trim().replace(/^\?/, '') // Ensure all "plus spaces" are hex encoded spaces
209
+
210
+ output = pathname
211
+
212
+ if (search !== ''){
213
+ output += '?'
214
+ }
215
+
216
+ // Encode the individual uri components
217
+ output += $.map(search.split('&'), function(component){
218
+ return $.map(component.split('='), function(kv){
219
+ // HACK: Firefox 'helps' us out by encoding apostrophes as %27 in AJAX requests, However its encodeURIcomponent method
220
+ // does not. This difference causes a mismatch between the url we use to calculate the cache path in the browser
221
+ // and on the server. This hack undoes the damage. See https://bugzilla.mozilla.org/show_bug.cgi?id=407172
222
+ return encodeURIComponent(kv).replace(/'/g, '%27')
223
+ }).join('=')
224
+ }).join('&')
225
+
226
+ return output
227
+ }
228
+
229
+
230
+ // INIT
231
+
232
+ // Because google events sometimes get missed, we ensure we're up to date every now and again
233
+ setInterval(sweep, 1000)
234
+
235
+
236
+ // PUBLIC INTERFACE
237
+
238
+ return {cacheAndLoadKMLLayer:cacheAndLoadKMLLayer, loadKMLLayer:loadKMLLayer, centerWhenLoaded:centerWhenLoaded, addLayer:addLayer, removeLayer:removeLayer, map:map}
239
+ }
@@ -9,16 +9,10 @@ module KMZCompressor
9
9
 
10
10
  # If the User is asking for a KMZ file
11
11
  if request.path_info.end_with? '.kmz'
12
- # HACK: Firefox 'helps' us out by encoding apostrophes as %27 in AJAX requests, However its encodeURI method
13
- # does not. This difference causes a mismatch between the browser's cached KMZ path, and the server.
14
- # This hack undoes the damage. See https://bugzilla.mozilla.org/show_bug.cgi?id=407172
15
- recoded_uri = URI.encode(URI.decode(request.fullpath))
16
-
17
- # HACK: Also encode brackets of nested params because the javascript version does, but the ruby version does not
18
- recoded_uri = recoded_uri.gsub('[', '%5B').gsub(']','%5D')
12
+ uri = request.fullpath
19
13
 
20
14
  # Use a hash of the request path (before we gsub it) as the filename we will save on the HD
21
- cache_path = "public/kmz/#{Digest::SHA2.hexdigest(recoded_uri)}.kmz"
15
+ cache_path = "public/kmz/#{Digest::SHA2.hexdigest(uri)}.kmz"
22
16
  file_exists = File.exists?(cache_path)
23
17
 
24
18
  if file_exists
@@ -1,3 +1,3 @@
1
1
  module KMZCompressor
2
- VERSION = "1.0.6"
2
+ VERSION = "2.0.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kmz_compressor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Wallace
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-28 00:00:00.000000000 Z
12
+ date: 2014-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails