diff --git a/contribs/gmf/apps/desktop/index.html b/contribs/gmf/apps/desktop/index.html index d116bcdff24..aed823596fa 100644 --- a/contribs/gmf/apps/desktop/index.html +++ b/contribs/gmf/apps/desktop/index.html @@ -228,7 +228,6 @@ diff --git a/contribs/gmf/apps/desktop_alt/index.html b/contribs/gmf/apps/desktop_alt/index.html index 7c7f39d6d24..d4f7eeeef74 100644 --- a/contribs/gmf/apps/desktop_alt/index.html +++ b/contribs/gmf/apps/desktop_alt/index.html @@ -257,8 +257,8 @@ @@ -417,9 +417,10 @@ defaultFeatureNS: 'http://mapserver.gis.umn.edu/mapserver', defaultFeaturePrefix: 'feature' })); + module.constant('ngeoTilesPreloadingLimit', 0); module.constant('ngeoQueryOptions', { limit: 50 - }) + }); })(); diff --git a/contribs/gmf/apps/desktop_alt/js/controller.js b/contribs/gmf/apps/desktop_alt/js/controller.js index 205f840db02..8137a39323d 100644 --- a/contribs/gmf/apps/desktop_alt/js/controller.js +++ b/contribs/gmf/apps/desktop_alt/js/controller.js @@ -147,6 +147,12 @@ app.desktop_alt.Controller = function($scope, $injector, ngeoFile, gettext, $q) gettextCatalog.getString('Add a theme'); gettextCatalog.getString('Add a sub theme'); gettextCatalog.getString('Add a layer'); + + /** + * @type {string} + * @export + */ + this.bgOpacityOptions = 'Test aus Olten'; }; ol.inherits(app.desktop_alt.Controller, gmf.controllers.AbstractDesktopController); diff --git a/contribs/gmf/apps/mobile/index.html b/contribs/gmf/apps/mobile/index.html index 011078cab1f..b8077422b62 100644 --- a/contribs/gmf/apps/mobile/index.html +++ b/contribs/gmf/apps/mobile/index.html @@ -116,7 +116,6 @@ id="background" class="gmf-mobile-nav-slide" data-header-title="{{'Background' | translate}}" - gmf-backgroundlayerselector-dimensions="::mainCtrl.dimensions" gmf-backgroundlayerselector-map="::mainCtrl.map" gmf-backgroundlayerselector-select="mainCtrl.hideNav()"> diff --git a/contribs/gmf/apps/mobile_alt/index.html b/contribs/gmf/apps/mobile_alt/index.html index 9fd4228dce7..c1dfe3cb96b 100644 --- a/contribs/gmf/apps/mobile_alt/index.html +++ b/contribs/gmf/apps/mobile_alt/index.html @@ -119,7 +119,6 @@ id="background" class="gmf-mobile-nav-slide" data-header-title="{{'Background' | translate}}" - gmf-backgroundlayerselector-dimensions="::mainCtrl.dimensions" gmf-backgroundlayerselector-map="::mainCtrl.map" gmf-backgroundlayerselector-select="mainCtrl.hideNav()"> @@ -240,6 +239,7 @@ defaultFeatureNS: 'http://mapserver.gis.umn.edu/mapserver', defaultFeaturePrefix: 'feature' })); + module.constant('ngeoTilesPreloadingLimit', 0); })(); diff --git a/contribs/gmf/examples/backgroundlayerselector.html b/contribs/gmf/examples/backgroundlayerselector.html index 7e09fae7a97..d52f636263c 100644 --- a/contribs/gmf/examples/backgroundlayerselector.html +++ b/contribs/gmf/examples/backgroundlayerselector.html @@ -13,7 +13,6 @@ directive to select the map background layer.

diff --git a/contribs/gmf/examples/backgroundlayerselector.js b/contribs/gmf/examples/backgroundlayerselector.js index c10c43f5a42..28a139669de 100644 --- a/contribs/gmf/examples/backgroundlayerselector.js +++ b/contribs/gmf/examples/backgroundlayerselector.js @@ -36,12 +36,6 @@ gmfapp.backgroundlayerselector.MainController = function(gmfThemes) { gmfThemes.loadThemes(); - /** - * @type {Object.} - * @export - */ - this.dimensions = {}; - /** * @type {ol.Map} * @export diff --git a/contribs/gmf/less/contextualdata.less b/contribs/gmf/less/contextualdata.less index 4dd96be6602..97497f9ede0 100644 --- a/contribs/gmf/less/contextualdata.less +++ b/contribs/gmf/less/contextualdata.less @@ -4,5 +4,10 @@ table { width: 100%; + tr { + td { + white-space: nowrap; + } + } } } diff --git a/contribs/gmf/less/map.less b/contribs/gmf/less/map.less index 689d80cc54e..5c531f95edf 100644 --- a/contribs/gmf/less/map.less +++ b/contribs/gmf/less/map.less @@ -95,6 +95,20 @@ button[ngeo-mobile-geolocation] { content: @fa-var-check; } } + + &.gmf-backgroundlayerselector-disabled{ + border-top-color: @map-tools-color; + pointer-events: none; + } + + span.gmf-backgroundlayerselector-opacity-check { + &::after { + width: (18em / 14); + font-family: FontAwesome; + content: @fa-var-check; + text-align: center; + } + } } .gmf-text { @@ -108,6 +122,12 @@ button[ngeo-mobile-geolocation] { height: @map-tools-size; margin: 0 @half-app-margin; } + + input.gmf-backgroundlayerselector-opacity-slider { + margin: 1rem 0 2rem 0; + padding-left: @half-app-margin !important; + padding-right: @half-app-margin !important; + } } /** Disclaimer and tablet redirect */ diff --git a/contribs/gmf/less/popover.less b/contribs/gmf/less/popover.less index db441921e8c..25353df7fd4 100644 --- a/contribs/gmf/less/popover.less +++ b/contribs/gmf/less/popover.less @@ -6,6 +6,7 @@ .popover { border-radius: 0; + z-index: @above-content-index; .popover-content { ul { margin-bottom: 0; diff --git a/contribs/gmf/src/authentication/Service.js b/contribs/gmf/src/authentication/Service.js index 7077fa27752..53ca517f3dd 100644 --- a/contribs/gmf/src/authentication/Service.js +++ b/contribs/gmf/src/authentication/Service.js @@ -21,12 +21,13 @@ gmf.authentication.Service = class extends ol.events.EventTarget { /** * @param {angular.$http} $http Angular http service. + * @param {angular.$injector} $injector Main injector. * @param {angular.Scope} $rootScope The directive's scope. * @param {string} authenticationBaseUrl URL to "authentication" web service. * @param {gmfx.User} gmfUser User. * @ngInject */ - constructor($http, $rootScope, authenticationBaseUrl, gmfUser) { + constructor($http, $injector, $rootScope, authenticationBaseUrl, gmfUser) { super(); @@ -55,6 +56,16 @@ gmf.authentication.Service = class extends ol.events.EventTarget { */ this.user_ = gmfUser; + /** + * Don't request a new user object from the back-end after + * logging out if the logged-in user's role has this role. + * @type {?string} + * @private + */ + this.noReloadRole_ = $injector.has('gmfAuthenticationNoReloadRole') + ? $injector.get('gmfAuthenticationNoReloadRole') + : null; + this.load_(); } @@ -114,9 +125,11 @@ gmf.authentication.Service = class extends ol.events.EventTarget { * @export */ logout() { + const noReload = this.user_['role_name'] === this.noReloadRole_; const url = `${this.baseUrl_}/${gmf.authentication.Service.RouteSuffix.LOGOUT}`; - return this.$http_.get(url, {withCredentials: true}).then( - this.resetUser_.bind(this)); + return this.$http_.get(url, {withCredentials: true}).then(() => { + this.resetUser_(noReload); + }); } /** @@ -191,15 +204,20 @@ gmf.authentication.Service = class extends ol.events.EventTarget { /** * @private + * @param {boolean} noReload Don't request a new user object from + * the back-end after logging out, defaults to false. */ - resetUser_() { + resetUser_(noReload) { + noReload = noReload || false; for (const key in this.user_) { this.user_[key] = null; } /** @type {gmfx.AuthenticationEvent} */ const event = new ngeo.CustomEvent('logout', {user: this.user_}); this.dispatchEvent(event); - this.load_(); + if (!noReload) { + this.load_(); + } } }; diff --git a/contribs/gmf/src/backgroundlayerselector/component.html b/contribs/gmf/src/backgroundlayerselector/component.html index 22c76f851dc..e6d5838a58e 100644 --- a/contribs/gmf/src/backgroundlayerselector/component.html +++ b/contribs/gmf/src/backgroundlayerselector/component.html @@ -1,9 +1,20 @@ diff --git a/contribs/gmf/src/backgroundlayerselector/component.js b/contribs/gmf/src/backgroundlayerselector/component.js index 0825ee00c50..2f390aee4c8 100644 --- a/contribs/gmf/src/backgroundlayerselector/component.js +++ b/contribs/gmf/src/backgroundlayerselector/component.js @@ -1,7 +1,6 @@ goog.provide('gmf.backgroundlayerselector.component'); goog.require('gmf'); // nowebpack -goog.require('goog.asserts'); goog.require('gmf.theme.Themes'); goog.require('ngeo.map.BackgroundLayerMgr'); goog.require('ol.events'); @@ -54,8 +53,8 @@ function gmfBackgroundlayerselectorTemplateUrl($element, $attrs, gmfBackgroundla * Example: * * * * @@ -63,9 +62,8 @@ function gmfBackgroundlayerselectorTemplateUrl($element, $attrs, gmfBackgroundla * * * thumbnail: The URL used for the icon. * - * @htmlAttribute {Object.} gmf-backgroundlayerselector-dimensions - * The dimensions. * @htmlAttribute {ol.Map=} gmf-backgroundlayerselector-map The map. + * @htmlAttribute {string} gmf-backgroundlayer-opacity-options The opacity slider options. * @htmlAttribute {Function} gmf-backgroundlayerselector-select Function called * when a layer was selected by the user. * @@ -75,8 +73,8 @@ function gmfBackgroundlayerselectorTemplateUrl($element, $attrs, gmfBackgroundla gmf.backgroundlayerselector.component.component_ = { controller: 'GmfBackgroundlayerselectorController as ctrl', bindings: { - 'dimensions': '=gmfBackgroundlayerselectorDimensions', 'map': '=gmfBackgroundlayerselectorMap', + 'opacityOptions': '=gmfBackgroundlayerOpacityOptions', 'select': '&?gmfBackgroundlayerselectorSelect' }, templateUrl: gmfBackgroundlayerselectorTemplateUrl @@ -101,16 +99,16 @@ gmf.backgroundlayerselector.component.component('gmfBackgroundlayerselector', gmf.backgroundlayerselector.component.Controller_ = function($scope, ngeoBackgroundLayerMgr, gmfThemes) { /** - * @type {!Object.} + * @type {?ol.Map} * @export */ - this.dimensions; + this.map; /** - * @type {?ol.Map} + * @type {!string|undefined} * @export */ - this.map; + this.opacityOptions; /** * Function called when a layer was selected by the user. @@ -131,6 +129,12 @@ gmf.backgroundlayerselector.component.Controller_ = function($scope, ngeoBackgro */ this.bgLayers; + /** + * @type {ol.layer.Base} + * @export + */ + this.opacityLayer; + /** * @type {!gmf.theme.Themes} * @private @@ -167,7 +171,6 @@ gmf.backgroundlayerselector.component.Controller_ = function($scope, ngeoBackgro * Initialise the controller. */ gmf.backgroundlayerselector.component.Controller_.prototype.$onInit = function() { - goog.asserts.assert(this.dimensions, 'The dimensions object is required'); this.handleThemesChange_(); }; @@ -179,9 +182,34 @@ gmf.backgroundlayerselector.component.Controller_.prototype.$onInit = function() gmf.backgroundlayerselector.component.Controller_.prototype.handleThemesChange_ = function() { this.gmfThemes_.getBgLayers().then((layers) => { this.bgLayers = layers; + + if (this.opacityOptions !== undefined) { + const opacityLayer = layers.find(layer => layer.get('label') === this.opacityOptions); + if (opacityLayer !== undefined) { + this.setOpacityBgLayer(opacityLayer); + this.opacityLayer = opacityLayer; + + // Reorder for the UI the bgArray copy with the opacity layer at the end + this.bgLayers = this.bgLayers.slice(); + const indexOpa = this.bgLayers.findIndex(layer => layer === this.opacityLayer); + this.bgLayers.splice(indexOpa, 1); + this.bgLayers.push(opacityLayer); + } + } }); }; +/** + * Getter/setter for background layer overlay, used by opacity slider. + * @param {?number} val The opacity. + * @returns {number} The background layer opacity. + */ +gmf.backgroundlayerselector.component.Controller_.prototype.getSetBgLayerOpacity = function(val) { + if (val) { + this.opacityLayer.setOpacity(val); + } + return this.opacityLayer.getOpacity(); +}; /** * @param {ol.layer.Base} layer Layer. @@ -196,6 +224,13 @@ gmf.backgroundlayerselector.component.Controller_.prototype.setLayer = function( } }; +/** + * Set a background layer overlay, used by the opacity slider. + * @param {ol.layer.Base} layer The opacity background layer. + */ +gmf.backgroundlayerselector.component.Controller_.prototype.setOpacityBgLayer = function(layer) { + this.backgroundLayerMgr_.setOpacityBgLayer(this.map, layer); +}; /** * @private diff --git a/contribs/gmf/src/controllers/AbstractAppController.js b/contribs/gmf/src/controllers/AbstractAppController.js index de4cb40130b..5426614af32 100644 --- a/contribs/gmf/src/controllers/AbstractAppController.js +++ b/contribs/gmf/src/controllers/AbstractAppController.js @@ -659,7 +659,7 @@ gmf.controllers.AbstractAppController.prototype.setDefaultBackground_ = function // get the background from the permalink layer = this.permalink_.getBackgroundLayer(layers); - if (!layer) { + if (!layer && this.gmfUser.functionalities) { // get the background from the user settings layer = gmf.controllers.AbstractAppController.getLayerByLabels(layers, this.gmfUser.functionalities.default_basemap); } diff --git a/contribs/gmf/src/gmf.js b/contribs/gmf/src/gmf.js index a0262d79e0a..52d661170f8 100644 --- a/contribs/gmf/src/gmf.js +++ b/contribs/gmf/src/gmf.js @@ -6,6 +6,12 @@ goog.provide('gmf'); */ gmf.baseModuleTemplateUrl = 'gmf'; // nowebpack +/** + * @const + * @export + */ +gmf.BACKGROUNDLAYERGROUP_NAME = 'background'; + /** * @const * @export diff --git a/contribs/gmf/src/query/gridComponent.html b/contribs/gmf/src/query/gridComponent.html index c60192ace83..d2650418e8f 100644 --- a/contribs/gmf/src/query/gridComponent.html +++ b/contribs/gmf/src/query/gridComponent.html @@ -10,15 +10,15 @@ role="tablist">
  • @@ -34,11 +34,11 @@
    + id="{{ctrl.escapeValue(gridSource.source.label)}}"> 0) { this.collectData_(source); @@ -417,12 +418,12 @@ gmf.query.gridComponent.Controller_.prototype.hasOneWithTooManyResults_ = functi }; /** - * Returns an escaped value. + * Returns the value with all symbols and spaces replaced by an underscore. * @param {string|number} value A value to escape. * @returns {string|number} value An escaped value. - * @private + * @export */ -gmf.query.gridComponent.Controller_.prototype.escapeValue_ = function(value) { +gmf.query.gridComponent.Controller_.prototype.escapeValue = function(value) { // Work-around for Number.isInteger() when not always getting a number ... if (Number.isInteger(/** @type {number} */ (value))) { return value; @@ -739,21 +740,21 @@ gmf.query.gridComponent.Controller_.prototype.selectTab = function(gridSource) { } this.updateFeatures_(gridSource); - this.reflowGrid_(source.id); + this.reflowGrid_(); }; /** * @private - * @param {string|number} sourceId Id of the source that should be refreshed. */ -gmf.query.gridComponent.Controller_.prototype.reflowGrid_ = function(sourceId) { +gmf.query.gridComponent.Controller_.prototype.reflowGrid_ = function() { // This is a "work-around" to make sure that the grid is rendered correctly. // When a pane is activated by setting `this.selectedTab`, the class `active` // is not yet set on the pane. That's why the class is set manually, and // after the pane is shown (in the next digest loop), the grid table can // be refreshed. - const activePane = this.$element_.find(`div.tab-pane#${sourceId}`); + const id = this.escapeValue(this.selectedTab || ''); + const activePane = this.$element_.find(`div.tab-pane#${id}`); activePane.removeClass('active').addClass('active'); this.$timeout_(() => { activePane.find('div.ngeo-grid-table-container table')['trigger']('reflow'); diff --git a/contribs/gmf/src/search/component.js b/contribs/gmf/src/search/component.js index 640d1b0d135..0abac9607bd 100644 --- a/contribs/gmf/src/search/component.js +++ b/contribs/gmf/src/search/component.js @@ -477,7 +477,9 @@ gmf.search.component.SearchController_ = class { resultIndex = parseInt(this.ngeoLocation_.getParam('search-select-index'), 10); } let mapZoom; - if (this.ngeoLocation_.getParam('map_zoom')) { + if (this.ngeoLocation_.getParam('search-maxzoom')) { + mapZoom = parseInt(this.ngeoLocation_.getParam('search-maxzoom'), 10); + } else if (this.ngeoLocation_.getParam('map_zoom')) { mapZoom = parseInt(this.ngeoLocation_.getParam('map_zoom'), 10); } this.fulltextsearch_(searchQuery, resultIndex, mapZoom); @@ -1056,6 +1058,7 @@ gmf.search.component.SearchController_ = class { const fitOptions = /** @type {olx.view.FitOptions} */ ({}); if (opt_zoom !== undefined) { fitOptions.maxZoom = opt_zoom; + fitOptions.size = this.map.getSize(); } this.map.getView().fit(feature.getGeometry().getExtent(), fitOptions); this.inputValue = /** @type {string} */ (feature.get('label')); diff --git a/src/map/Backgroundlayermgr.js b/src/map/Backgroundlayermgr.js index 5c798ff9b37..06836e294f2 100644 --- a/src/map/Backgroundlayermgr.js +++ b/src/map/Backgroundlayermgr.js @@ -52,10 +52,12 @@ goog.require('ol.source.WMTS'); * @extends {ol.Observable} * @constructor * @struct + * @param {ngeo.map.LayerHelper} ngeoLayerHelper Themes service. + * @ngInject * @ngdoc service * @ngname ngeoBackgroundLayerMgr */ -ngeo.map.BackgroundLayerMgr = function() { +ngeo.map.BackgroundLayerMgr = function(ngeoLayerHelper) { ol.Observable.call(this); @@ -65,6 +67,17 @@ ngeo.map.BackgroundLayerMgr = function() { * @private */ this.mapUids_ = {}; + + /** + * @type {ngeo.map.LayerHelper} + * @private + */ + this.ngeoLayerHelper_ = ngeoLayerHelper; + + /** + * @type {string} + */ + this.BACKGROUNDLAYERGROUP_NAME = 'background'; }; ol.inherits(ngeo.map.BackgroundLayerMgr, ol.Observable); @@ -78,7 +91,7 @@ ol.inherits(ngeo.map.BackgroundLayerMgr, ol.Observable); */ ngeo.map.BackgroundLayerMgr.prototype.get = function(map) { const mapUid = ol.getUid(map).toString(); - return mapUid in this.mapUids_ ? map.getLayers().item(0) : null; + return mapUid in this.mapUids_ ? this.ngeoLayerHelper_.getGroupFromMap(map, this.BACKGROUNDLAYERGROUP_NAME).getLayers().item(0) : null; }; @@ -91,18 +104,26 @@ ngeo.map.BackgroundLayerMgr.prototype.get = function(map) { * @export */ ngeo.map.BackgroundLayerMgr.prototype.set = function(map, layer) { + const ZIndex = -200; const mapUid = ol.getUid(map).toString(); const previous = this.get(map); + if (layer !== null) { + layer.setZIndex(ZIndex); + this.ngeoLayerHelper_.setZIndexToFirstLevelChildren(layer, ZIndex); + } + + const bgGroup = this.ngeoLayerHelper_.getGroupFromMap(map, this.BACKGROUNDLAYERGROUP_NAME); + if (previous !== null) { goog.asserts.assert(mapUid in this.mapUids_); if (layer !== null) { - map.getLayers().setAt(0, layer); + bgGroup.getLayers().setAt(0, layer); } else { - map.getLayers().removeAt(0); + bgGroup.getLayers().removeAt(0); delete this.mapUids_[mapUid]; } } else if (layer !== null) { - map.getLayers().insertAt(0, layer); + bgGroup.getLayers().insertAt(0, layer); this.mapUids_[mapUid] = true; } /** @type {ngeox.BackgroundEvent} */ @@ -115,6 +136,37 @@ ngeo.map.BackgroundLayerMgr.prototype.set = function(map, layer) { return previous; }; +/** + * Return the current background layer overlay of a given map, used by the opacity slider. + * `null` is returned if the map does not have an opacity background layer. + * @param {ol.Map} map Map. + * @return {ol.layer.Base} layer The opacity background layer. + * @export + */ +ngeo.map.BackgroundLayerMgr.prototype.getOpacityBgLayer = function(map) { + const mapUid = ol.getUid(map).toString(); + return mapUid in this.mapUids_ ? this.ngeoLayerHelper_.getGroupFromMap(map, this.BACKGROUNDLAYERGROUP_NAME).getLayers().item(1) : null; +}; + +/** + * Set an background layer overlay, used by the opacity slider. + * @param {ol.Map} map The map. + * @param {ol.layer.Base} layer The opacity background layer. + */ +ngeo.map.BackgroundLayerMgr.prototype.setOpacityBgLayer = function(map, layer) { + const ZIndex = -100; + layer.setOpacity(0); + layer.setVisible(true); + layer.setZIndex(ZIndex); + this.ngeoLayerHelper_.setZIndexToFirstLevelChildren(layer, ZIndex); + const bgGroup = this.ngeoLayerHelper_.getGroupFromMap(map, this.BACKGROUNDLAYERGROUP_NAME); + + const index = bgGroup.getLayers().getArray().indexOf(layer); + if (index === -1) { + bgGroup.getLayers().push(layer); + } +}; + /** * @param {ol.Map} map The map. * @param {Object.} dimensions The global dimensions object. diff --git a/src/map/LayerHelper.js b/src/map/LayerHelper.js index e7ec405e971..6d5ed48934d 100644 --- a/src/map/LayerHelper.js +++ b/src/map/LayerHelper.js @@ -17,13 +17,16 @@ goog.require('ol.uri'); * Provides help functions that helps you to create and manage layers. * @param {angular.$q} $q Angular promises/deferred service. * @param {angular.$http} $http Angular http service. + * @param {number} ngeoTilesPreloadingLimit Load tiles up to preload levels. By default preload is Infinity, + * which means load all tiles on the top of the visible level. See also preload value + * in documentation for ol.Layer.Tile. * @constructor * @struct * @ngdoc service * @ngname ngeoLayerHelper * @ngInject */ -ngeo.map.LayerHelper = function($q, $http) { +ngeo.map.LayerHelper = function($q, $http, ngeoTilesPreloadingLimit) { /** * @type {angular.$q} @@ -36,6 +39,13 @@ ngeo.map.LayerHelper = function($q, $http) { * @private */ this.$http_ = $http; + + /** + * The Tiles Preloading Limit value + * @type {number} + * @private + */ + this.tilesPreloadingLimit_ = ngeoTilesPreloadingLimit; }; @@ -153,7 +163,7 @@ ngeo.map.LayerHelper.prototype.createBasicWMSLayerFromDataSource = function( ngeo.map.LayerHelper.prototype.createWMTSLayerFromCapabilitites = function(capabilitiesURL, layerName, opt_matrixSet, opt_dimensions) { const parser = new ol.format.WMTSCapabilities(); const layer = new ol.layer.Tile({ - preload: Infinity + preload: this.tilesPreloadingLimit_ }); const $q = this.$q_; @@ -416,6 +426,20 @@ ngeo.map.LayerHelper.prototype.refreshWMSLayer = function(layer) { }; +/** + * Set ZIndex property to first level children elements + * @param {ol.layer.Group|ol.layer.Base} element The group of layer with first level children layers. + * @param {number} ZIndex The ZIndex for children element. + */ +ngeo.map.LayerHelper.prototype.setZIndexToFirstLevelChildren = function(element, ZIndex) { + if (!(element instanceof ol.layer.Group)) { + return; + } + const innerGroupLayers = element.getLayers(); + innerGroupLayers.forEach(innerLayer => innerLayer.setZIndex(ZIndex)); +}; + + /** * Update the LAYERS parameter of the source of the given WMS layer. * @param {ol.layer.Image} layer The WMS layer. @@ -457,5 +481,6 @@ ngeo.map.LayerHelper.prototype.getQuerySourceIds = function(layer) { /** * @type {!angular.Module} */ -ngeo.map.LayerHelper.module = angular.module('ngeoLayerHelper', []); -ngeo.map.LayerHelper.module.service('ngeoLayerHelper', ngeo.map.LayerHelper); +ngeo.map.LayerHelper.module = angular.module('ngeoLayerHelper', []) + .service('ngeoLayerHelper', ngeo.map.LayerHelper) + .value('ngeoTilesPreloadingLimit', Infinity); diff --git a/test/spec/services/backgroundlayermgr.spec.js b/test/spec/services/backgroundlayermgr.spec.js index 99fb78321dd..8efb0fac5b9 100644 --- a/test/spec/services/backgroundlayermgr.spec.js +++ b/test/spec/services/backgroundlayermgr.spec.js @@ -1,13 +1,18 @@ +goog.require('ol.Collection'); goog.require('ol.Map'); +goog.require('ol.layer.Group'); goog.require('ol.layer.Tile'); describe('ngeo.map.BackgroundLayerMgr', () => { let ngeoBackgroundLayerMgr; + let ngeoLayerHelper; let map; + const BACKGROUNDLAYERGROUP_NAME = 'background'; beforeEach(() => { - angular.mock.inject((_ngeoBackgroundLayerMgr_) => { + angular.mock.inject((_ngeoBackgroundLayerMgr_, _ngeoLayerHelper_) => { ngeoBackgroundLayerMgr = _ngeoBackgroundLayerMgr_; + ngeoLayerHelper = _ngeoLayerHelper_; }); map = new ol.Map({}); @@ -18,15 +23,17 @@ describe('ngeo.map.BackgroundLayerMgr', () => { it('sets the background layer #1', () => { const layer = new ol.layer.Tile(); ngeoBackgroundLayerMgr.set(map, layer); - expect(map.getLayers().item(0)).toBe(layer); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + expect(bgGroup.getLayers().item(0)).toBe(layer); }); it('sets the background layer #2', () => { - map.addLayer(new ol.layer.Tile()); const layer = new ol.layer.Tile(); ngeoBackgroundLayerMgr.set(map, layer); - expect(map.getLayers().getLength()).toBe(2); - expect(map.getLayers().item(0)).toBe(layer); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + bgGroup.getLayers().setAt(1, new ol.layer.Tile()); + expect(bgGroup.getLayers().getLength()).toBe(2); + expect(bgGroup.getLayers().item(0)).toBe(layer); }); it('sets the background layer #3', () => { @@ -34,15 +41,74 @@ describe('ngeo.map.BackgroundLayerMgr', () => { ngeoBackgroundLayerMgr.set(map, layer1); const layer2 = new ol.layer.Tile(); ngeoBackgroundLayerMgr.set(map, layer2); - expect(map.getLayers().getLength()).toBe(1); - expect(map.getLayers().item(0)).toBe(layer2); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + expect(bgGroup.getLayers().getLength()).toBe(1); + expect(bgGroup.getLayers().item(0)).toBe(layer2); + }); + + it('sets the opacity background layer', () => { + const layer1 = new ol.layer.Tile(); + ngeoBackgroundLayerMgr.set(map, layer1); + const layer2 = new ol.layer.Tile(); + ngeoBackgroundLayerMgr.setOpacityBgLayer(map, layer2); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + expect(bgGroup.getLayers().getLength()).toBe(2); + expect(bgGroup.getLayers().item(0)).toBe(layer1); + expect(bgGroup.getLayers().item(1)).toBe(layer2); + }); + + it('sets the ZINdex on active background layergroup', () => { + const layer1 = new ol.layer.Tile(); + const layer2 = new ol.layer.Tile(); + const group = new ol.layer.Group(); + const collection = new ol.Collection(); + + collection.push(layer1); + collection.push(layer2); + group.setLayers(collection); + + ngeoBackgroundLayerMgr.set(map, group); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + const bgGroupLayers = bgGroup.getLayers().item(0).getLayers(); + + // We don't set ZIndex on the group, as OL is + // just ordering it without regard it is group or layer + expect(bgGroup.getZIndex()).toBe(0); + + // As we just set the layers ZIndex, this is where it is expected + expect(bgGroupLayers.item(0).getZIndex()).toBe(-200); + expect(bgGroupLayers.item(1).getZIndex()).toBe(-200); + }); + + it('sets the ZINdex on overlay background layergroup', () => { + const layer1 = new ol.layer.Tile(); + const layer2 = new ol.layer.Tile(); + const group = new ol.layer.Group(); + const collection = new ol.Collection(); + + collection.push(layer1); + collection.push(layer2); + group.setLayers(collection); + + ngeoBackgroundLayerMgr.setOpacityBgLayer(map, group); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + const bgGroupLayers = bgGroup.getLayers().item(0).getLayers(); + + // We don't set ZIndex on the group, as OL is + // just ordering it without regard it is group or layer + expect(bgGroup.getZIndex()).toBe(0); + + // As we just set the layers ZIndex, this is where it is expected + expect(bgGroupLayers.item(0).getZIndex()).toBe(-100); + expect(bgGroupLayers.item(1).getZIndex()).toBe(-100); }); it('unsets the background layer', () => { const layer = new ol.layer.Tile(); ngeoBackgroundLayerMgr.set(map, layer); ngeoBackgroundLayerMgr.set(map, null); - expect(map.getLayers().getLength()).toBe(0); + const bgGroup = ngeoLayerHelper.getGroupFromMap(map, BACKGROUNDLAYERGROUP_NAME); + expect(bgGroup.getLayers().getLength()).toBe(0); }); }); @@ -60,6 +126,20 @@ describe('ngeo.map.BackgroundLayerMgr', () => { const layer = ngeoBackgroundLayerMgr.get(map); expect(layer).toBe(expectedLayer); }); + + it('returns `null` if no opacity background layer', () => { + const layer = ngeoBackgroundLayerMgr.getOpacityBgLayer(map); + expect(layer).toBe(null); + }); + + it('returns the current opacity background layer', () => { + const activeBgLayer = new ol.layer.Tile(); + ngeoBackgroundLayerMgr.set(map, activeBgLayer); + const opacityBgLayer = new ol.layer.Tile(); + ngeoBackgroundLayerMgr.setOpacityBgLayer(map, opacityBgLayer); + const layer = ngeoBackgroundLayerMgr.getOpacityBgLayer(map); + expect(layer).toBe(opacityBgLayer); + }); }); });