diff --git a/examples/acceptance/multiclient-gmaps.html b/examples/acceptance/multiclient-gmaps.html new file mode 100644 index 0000000000..7b885278bb --- /dev/null +++ b/examples/acceptance/multiclient-gmaps.html @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/src/api/v4/native/google-maps-map-type.js b/src/api/v4/native/google-maps-map-type.js index a0d674f92e..fd17db87fd 100644 --- a/src/api/v4/native/google-maps-map-type.js +++ b/src/api/v4/native/google-maps-map-type.js @@ -22,6 +22,7 @@ function GoogleMapsMapType (layers, engine, map) { this._internalView = new GMapsCartoDBLayerGroupView(this._engine._cartoLayerGroup, { nativeMap: map }); + this._id = this._internalView._id; this._internalView.on('featureClick', this._onFeatureClick, this); this._internalView.on('featureOver', this._onFeatureOver, this); this._internalView.on('featureOut', this._onFeatureOut, this); diff --git a/src/geo/gmaps/gmaps-cartodb-layer-group-view.js b/src/geo/gmaps/gmaps-cartodb-layer-group-view.js index 7c3e2654e7..c1f70ad27c 100644 --- a/src/geo/gmaps/gmaps-cartodb-layer-group-view.js +++ b/src/geo/gmaps/gmaps-cartodb-layer-group-view.js @@ -20,6 +20,10 @@ function setImageOpacityIE8 (img, opacity) { } } +function generateId () { + return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1); +} + var GMapsCartoDBLayerGroupView = function (layerModel, options) { var self = this; var hovers = []; @@ -83,6 +87,9 @@ var GMapsCartoDBLayerGroupView = function (layerModel, options) { blankImage: options.blankImage || 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' }; + // internal id + this._id = generateId(); + // non-configurable options this.interactive = true; this.tileSize = new google.maps.Size(256, 256); @@ -107,9 +114,10 @@ _.extend( }, remove: function () { - var overlayIndex = this.gmapsMap.overlayMapTypes.getArray().indexOf(this); + var overlayIndex = this._getOverlayIndex(); + if (overlayIndex >= 0) { - this.gmapsMap.overlayMapTypes.removeAt(0); + this.gmapsMap.overlayMapTypes.removeAt(overlayIndex); } this._clearInteraction(); @@ -272,9 +280,9 @@ _.extend( _reload: function () { var tileURLTemplates; if (this.model.hasTileURLTemplates()) { - tileURLTemplates = [ this.model.getTileURLTemplatesWithSubdomains()[0] ]; + tileURLTemplates = [this.model.getTileURLTemplatesWithSubdomains()[0]]; } else { - tileURLTemplates = [ EMPTY_GIF ]; + tileURLTemplates = [EMPTY_GIF]; } this.options.tiles = tileURLTemplates; @@ -285,11 +293,12 @@ _.extend( }, _refreshView: function () { - var overlayIndex = this.gmapsMap.overlayMapTypes.getArray().indexOf(this); + var overlays = this.gmapsMap.overlayMapTypes; + var overlayIndex = this._getOverlayIndex(); + if (overlayIndex >= 0) { - this.gmapsMap.overlayMapTypes.removeAt(overlayIndex); + overlays.setAt(overlayIndex, overlays.getAt(overlayIndex)); } - this.gmapsMap.overlayMapTypes.setAt(0, this); }, _checkLayer: function () { @@ -298,6 +307,14 @@ _.extend( } }, + _getOverlayIndex: function () { + var overlays = this.gmapsMap.overlayMapTypes.getArray(); + + return _.findIndex(overlays, function (overlay) { + return overlay && overlay._id === this._id; + }, this); + }, + /** * Creates an instance of a googleMaps Point */ diff --git a/test/spec/geo/gmaps/gmaps-cartodb-layer-group.spec.js b/test/spec/geo/gmaps/gmaps-cartodb-layer-group.spec.js index e40e68a719..92f1e8cefd 100644 --- a/test/spec/geo/gmaps/gmaps-cartodb-layer-group.spec.js +++ b/test/spec/geo/gmaps/gmaps-cartodb-layer-group.spec.js @@ -1,6 +1,9 @@ /* global google */ var GoogleCartoDBLayerGroupClass = require('../../../../src/geo/gmaps/gmaps-cartodb-layer-group-view'); var cartoLayerGroupViewTests = require('../shared-tests-for-carto-layer-group'); +var CartoDBLayer = require('../../../../src/geo/map/cartodb-layer'); +var LayersCollection = require('../../../../src/geo/map/layers'); +var CartoDBLayerGroup = require('../../../../src/geo/cartodb-layer-group'); describe('gmaps-cartodb-layer-group-view', function () { /** @@ -37,5 +40,100 @@ describe('gmaps-cartodb-layer-group-view', function () { pixel: { x: 243, y: 274 } }; + // -- Shared tests for carto layer group cartoLayerGroupViewTests(createNativeMap, GoogleCartoDBLayerGroupClass, getTileUrl, event); + + // -- Google maps specific tests + describe('GMapsCartoDBLayerGroupView', function () { + var nativeMap; + var container; + var cartoDbLayer0; + var cartoDbLayer1; + var layerGroupView0; + var layerGroupView1; + + var layerGroupModelMock; + var layersCollection; + + var engineMock = { + on: jasmine.createSpy('on') + }; + + var mapModelMock = { + on: jasmine.createSpy('on'), + isFeatureInteractivityEnabled: jasmine.createSpy('isFeatureInteractivityEnabled').and.returnValue(false) + }; + + beforeEach(function () { + container = document.createElement('div'); + nativeMap = createNativeMap(container); + + cartoDbLayer0 = new CartoDBLayer({}, { engine: engineMock }); + cartoDbLayer1 = new CartoDBLayer({}, { engine: engineMock }); + + layersCollection = new LayersCollection([cartoDbLayer0, cartoDbLayer1]); + + layerGroupModelMock = new CartoDBLayerGroup({ + urls: { + 'subdomains': [0, 1, 2, 3], + 'tiles': 'http://{s}.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/{layerIndexes}/{z}/{x}/{y}.png', + 'grids': [ + [ + 'http://0.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/0/{z}/{x}/{y}.grid.json', + 'http://1.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/0/{z}/{x}/{y}.grid.json', + 'http://2.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/0/{z}/{x}/{y}.grid.json', + 'http://3.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/0/{z}/{x}/{y}.grid.json' + ], + [ + 'http://0.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/1/{z}/{x}/{y}.grid.json', + 'http://1.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/1/{z}/{x}/{y}.grid.json', + 'http://2.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/1/{z}/{x}/{y}.grid.json', + 'http://3.ashbu.cartocdn.com/documentation/api/v1/map/0123456789/1/{z}/{x}/{y}.grid.json' + ] + ], + 'attributes': [ + 'http://ashbu.cartocdn.com/documentation/api/v1/map/0123456789/0/attributes', + 'http://ashbu.cartocdn.com/documentation/api/v1/map/0123456789/1/attributes' + ] + }, + indexOfLayersInWindshaft: [1, 2] + }, { + layersCollection: layersCollection + }); + + layerGroupView0 = new GoogleCartoDBLayerGroupClass(layerGroupModelMock, { nativeMap: nativeMap, mapModel: mapModelMock }); + layerGroupView1 = new GoogleCartoDBLayerGroupClass(layerGroupModelMock, { nativeMap: nativeMap, mapModel: mapModelMock }); + nativeMap.overlayMapTypes.push(layerGroupView0); + nativeMap.overlayMapTypes.push(layerGroupView1); + }); + + describe('._getOverlayIndex', function () { + it('returns the index of the given layour group', function () { + expect(layerGroupView0._getOverlayIndex()).toEqual(0); + expect(layerGroupView1._getOverlayIndex()).toEqual(1); + }); + }); + + describe('._refreshView', function () { + it('sets the layer group in the same position', function () { + layerGroupView0._refreshView(); + + expect(nativeMap.overlayMapTypes.getAt(0)).toEqual(layerGroupView0); + expect(nativeMap.overlayMapTypes.getAt(1)).toEqual(layerGroupView1); + }); + }); + + describe('.remove', function () { + it('removes the correct layer group', function () { + layerGroupView0.remove(); + + expect(nativeMap.overlayMapTypes.getLength()).toEqual(1); + expect(nativeMap.overlayMapTypes.getAt(0)).toEqual(layerGroupView1); + }); + }); + + afterEach(function () { + document.body.removeChild(container); + }); + }); });