Completed
Pull Request — develop (#235)
by Xaver
38s
created

lib/map/activearea.js   D

Complexity

Total Complexity 65
Complexity/F 3.61

Size

Lines of Code 349
Function Count 18

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
wmc 65
c 1
b 0
f 0
nc 147456
mnd 3
bc 57
fnc 18
dl 0
loc 349
rs 4.5
bpm 3.1666
cpm 3.6111
noi 15

How to fix   Complexity   

Complexity

Complex classes like lib/map/activearea.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
define(function () {
2
  /**
3
   * https://github.com/Mappy/Leaflet-active-area
4
   * Apache 2.0 license https://www.apache.org/licenses/LICENSE-2.0
5
   */
6
7
  var previousMethods = {
8
    getCenter: L.Map.prototype.getCenter,
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
    setView: L.Map.prototype.setView,
10
    setZoomAround: L.Map.prototype.setZoomAround,
11
    getBoundsZoom: L.Map.prototype.getBoundsZoom,
12
    PopupAdjustPan: L.Popup.prototype._adjustPan,
13
    RendererUpdate: L.Renderer.prototype._update
14
  };
15
16
  L.Map.include({
17
    getBounds: function () {
18
      if (this._viewport) {
19
        return this.getViewportLatLngBounds();
20
      }
21
      var bounds = this.getPixelBounds();
22
      var sw = this.unproject(bounds.getBottomLeft());
23
      var ne = this.unproject(bounds.getTopRight());
24
25
      return new L.LatLngBounds(sw, ne);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
26
    },
27
28
    getViewport: function () {
29
      return this._viewport;
30
    },
31
32
    getViewportBounds: function () {
33
      var vp = this._viewport;
34
      var topleft = L.point(vp.offsetLeft, vp.offsetTop);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
35
      var vpsize = L.point(vp.clientWidth, vp.clientHeight);
36
37
      if (vpsize.x === 0 || vpsize.y === 0) {
38
        // Our own viewport has no good size - so we fallback to the container size:
39
        vp = this.getContainer();
40
        if (vp) {
41
          topleft = L.point(0, 0);
42
          vpsize = L.point(vp.clientWidth, vp.clientHeight);
43
        }
44
      }
45
46
      return L.bounds(topleft, topleft.add(vpsize));
47
    },
48
49
    getViewportLatLngBounds: function () {
50
      var bounds = this.getViewportBounds();
51
      return L.latLngBounds(this.containerPointToLatLng(bounds.min), this.containerPointToLatLng(bounds.max));
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
52
    },
53
54
    getOffset: function () {
55
      var mCenter = this.getSize().divideBy(2);
56
      var vCenter = this.getViewportBounds().getCenter();
57
58
      return mCenter.subtract(vCenter);
59
    },
60
61
    getCenter: function (withoutViewport) {
62
      var center = previousMethods.getCenter.call(this);
63
64
      if (this.getViewport() && !withoutViewport) {
65
        var zoom = this.getZoom();
66
        var point = this.project(center, zoom);
67
        point = point.subtract(this.getOffset());
68
69
        center = this.unproject(point, zoom);
70
      }
71
72
      return center;
73
    },
74
75
    setView: function (center, zoom, options) {
76
      center = L.latLng(center);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
77
      zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);
78
79
      if (this.getViewport()) {
80
        var point = this.project(center, this._limitZoom(zoom));
81
        point = point.add(this.getOffset());
82
        center = this.unproject(point, this._limitZoom(zoom));
83
      }
84
85
      return previousMethods.setView.call(this, center, zoom, options);
86
    },
87
88
    setZoomAround: function (latlng, zoom, options) {
89
      var vp = this.getViewport();
90
91
      if (vp) {
92
        var scale = this.getZoomScale(zoom);
93
        var viewHalf = this.getViewportBounds().getCenter();
94
        var containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
95
96
        var centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale);
97
        var newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
98
99
        return this.setView(newCenter, zoom, { zoom: options });
100
      }
101
      return previousMethods.setZoomAround.call(this, latlng, zoom, options);
102
    },
103
104
    getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number
105
      bounds = L.latLngBounds(bounds);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
106
      padding = L.point(padding || [0, 0]);
107
108
      var zoom = this.getZoom() || 0;
109
      var min = this.getMinZoom();
110
      var max = this.getMaxZoom();
111
      var nw = bounds.getNorthWest();
112
      var se = bounds.getSouthEast();
113
      var vp = this.getViewport();
114
      var size = (vp ? L.point(vp.clientWidth, vp.clientHeight) : this.getSize()).subtract(padding);
115
      var boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom));
116
      var snap = L.Browser.any3d ? this.options.zoomSnap : 1;
117
118
      var scale = Math.min(size.x / boundsSize.x, size.y / boundsSize.y);
119
120
      zoom = this.getScaleZoom(scale, zoom);
121
122
      if (snap) {
123
        zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
124
        zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
125
      }
126
127
      return Math.max(min, Math.min(max, zoom));
128
    }
129
  });
130
131
  L.Map.include({
132
    setActiveArea: function (css, keepCenter, animate) {
133
      var center;
134
      if (keepCenter && this._zoom) {
135
        // save center if map is already initialized
136
        // and keepCenter is passed
137
        center = this.getCenter();
138
      }
139
140
      if (!this._viewport) {
141
        // Make viewport if not already made
142
        var container = this.getContainer();
143
        this._viewport = L.DomUtil.create('div', '');
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
144
        container.insertBefore(this._viewport, container.firstChild);
145
      }
146
147
      if (typeof css === 'string') {
148
        this._viewport.className = css;
149
      } else {
150
        L.extend(this._viewport.style, css);
151
      }
152
153
      if (center) {
154
        this.setView(center, this.getZoom(), { animate: !!animate });
155
      }
156
      return this;
157
    }
158
  });
159
160
  L.Renderer.include({
161
    _onZoom: function () {
162
      this._updateTransform(this._map.getCenter(true), this._map.getZoom());
163
    },
164
165
    _update: function () {
166
      previousMethods.RendererUpdate.call(this);
167
      this._center = this._map.getCenter(true);
168
    }
169
  });
170
171
  L.GridLayer.include({
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
172
    _updateLevels: function () {
173
      var zoom = this._tileZoom;
174
      var maxZoom = this.options.maxZoom;
175
176
      if (zoom === undefined) {
177
        return undefined;
178
      }
179
180
      for (var z in this._levels) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
181
        if (this._levels[z].el.children.length || z === zoom) {
182
          this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);
183
        } else {
184
          L.DomUtil.remove(this._levels[z].el);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
185
          this._removeTilesAtZoom(z);
186
          delete this._levels[z];
187
        }
188
      }
189
190
      var level = this._levels[zoom];
191
      var map = this._map;
192
193
      if (!level) {
194
        level = this._levels[zoom] = {};
195
196
        level.el = L.DomUtil.create('div', 'leaflet-tile-container leaflet-zoom-animated', this._container);
197
        level.el.style.zIndex = maxZoom;
198
199
        level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();
200
        level.zoom = zoom;
201
202
        this._setZoomTransform(level, map.getCenter(true), map.getZoom());
203
204
        // force the browser to consider the newly added element for transition
205
        L.Util.falseFn(level.el.offsetWidth);
206
      }
207
208
      this._level = level;
209
210
      return level;
211
    },
212
213
    _resetView: function (e) {
214
      var animating = e && (e.pinch || e.flyTo);
215
      this._setView(this._map.getCenter(true), this._map.getZoom(), animating, animating);
216
    },
217
218
    _update: function (center) {
219
      var map = this._map;
220
      if (!map) {
221
        return;
222
      }
223
      var zoom = map.getZoom();
224
225
      if (center === undefined) {
226
        center = map.getCenter(this);
227
      }
228
      if (this._tileZoom === undefined) {
229
        return;
230
      }    // if out of minzoom/maxzoom
231
232
      var pixelBounds = this._getTiledPixelBounds(center);
233
      var tileRange = this._pxBoundsToTileRange(pixelBounds);
234
      var tileCenter = tileRange.getCenter();
235
      var queue = [];
236
237
      for (var key in this._tiles) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
238
        this._tiles[key].current = false;
239
      }
240
241
      // _update just loads more tiles. If the tile zoom level differs too much
242
      // from the map's, let _setView reset levels and prune old tiles.
243
      if (Math.abs(zoom - this._tileZoom) > 1) {
244
        this._setView(center, zoom);
245
        return;
246
      }
247
248
      // create a queue of coordinates to load tiles from
249
      for (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
250
        for (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
251
          var coords = new L.Point(i, j);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
252
          coords.z = this._tileZoom;
253
254
          if (!this._isValidTile(coords)) {
255
            continue;
256
          }
257
258
          var tile = this._tiles[this._tileCoordsToKey(coords)];
259
          if (tile) {
260
            tile.current = true;
261
          } else {
262
            queue.push(coords);
263
          }
264
        }
265
      }
266
267
      // sort tile queue to load tiles in order of their distance to center
268
      queue.sort(function (a, b) {
269
        return a.distanceTo(tileCenter) - b.distanceTo(tileCenter);
270
      });
271
272
      if (queue.length !== 0) {
273
        // if its the first batch of tiles to load
274
        if (!this._loading) {
275
          this._loading = true;
276
          // @event loading: Event
277
          // Fired when the grid layer starts loading tiles
278
          this.fire('loading');
279
        }
280
281
        // create DOM fragment to append tiles in one batch
282
        var fragment = document.createDocumentFragment();
283
284
        for (i = 0; i < queue.length; i++) {
285
          this._addTile(queue[i], fragment);
286
        }
287
288
        this._level.el.appendChild(fragment);
289
      }
290
    }
291
  });
292
293
  L.Popup.include({
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
294
    _adjustPan: function () {
295
      if (!this._map._viewport) {
296
        previousMethods.PopupAdjustPan.call(this);
297
      } else {
298
        if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) {
299
          return;
300
        }
301
302
        var map = this._map;
303
        var vp = map._viewport;
304
        var containerHeight = this._container.offsetHeight;
305
        var containerWidth = this._containerWidth;
306
        var vpTopleft = L.point(vp.offsetLeft, vp.offsetTop);
0 ignored issues
show
Bug introduced by
The variable L seems to be never declared. If this is a global, consider adding a /** global: L */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
307
308
        var layerPos = new L.Point(
309
          this._containerLeft - vpTopleft.x,
310
          -containerHeight - this._containerBottom - vpTopleft.y);
311
312
        if (this._zoomAnimated) {
313
          layerPos._add(L.DomUtil.getPosition(this._container));
314
        }
315
316
        var containerPos = map.layerPointToContainerPoint(layerPos);
317
        var padding = L.point(this.options.autoPanPadding);
318
        var paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding);
319
        var paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding);
320
        var size = L.point(vp.clientWidth, vp.clientHeight);
321
        var dx = 0;
322
        var dy = 0;
323
324
        if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
325
          dx = containerPos.x + containerWidth - size.x + paddingBR.x;
326
        }
327
        if (containerPos.x - dx - paddingTL.x < 0) { // left
328
          dx = containerPos.x - paddingTL.x;
329
        }
330
        if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
331
          dy = containerPos.y + containerHeight - size.y + paddingBR.y;
332
        }
333
        if (containerPos.y - dy - paddingTL.y < 0) { // top
334
          dy = containerPos.y - paddingTL.y;
335
        }
336
337
        // @namespace Map
338
        // @section Popup events
339
        // @event autopanstart
340
        // Fired when the map starts autopanning when opening a popup.
341
        if (dx || dy) {
342
          map
343
            .fire('autopanstart')
344
            .panBy([dx, dy]);
345
        }
346
      }
347
    }
348
  });
349
});
350