From 4ac4092b0ab4ca90c217eef99a18fd2c34d83d7a Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Fri, 2 Nov 2018 12:34:05 -0700 Subject: [PATCH 1/4] Allow user to define element other than map container for full screen control --- src/ui/control/fullscreen_control.js | 36 ++++++++++++++++--------- test/unit/ui/control/fullscreen.test.js | 11 ++++++++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/ui/control/fullscreen_control.js b/src/ui/control/fullscreen_control.js index 539a26b549b..79af6736fa3 100644 --- a/src/ui/control/fullscreen_control.js +++ b/src/ui/control/fullscreen_control.js @@ -7,26 +7,36 @@ import window from '../../util/window'; import type Map from '../map'; +type Options = { + source?: HTMLElement +}; + /** * A `FullscreenControl` control contains a button for toggling the map in and out of fullscreen mode. * * @implements {IControl} + * @param {Object} [options] + * @param {HTMLElement} [options.source] `source` is the [compatible DOM element](https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen#Compatible_elements) which should be made full screen. By default, the map container element will be made full screen. + * * @example - * map.addControl(new mapboxgl.FullscreenControl()); + * map.addControl(new mapboxgl.FullscreenControl({source: document.querySelector('body')})); * @see [View a fullscreen map](https://www.mapbox.com/mapbox-gl-js/example/fullscreen/) */ class FullscreenControl { _map: Map; - _mapContainer: HTMLElement; _container: HTMLElement; _fullscreen: boolean; _fullscreenchange: string; _fullscreenButton: HTMLElement; _className: string; + _source: HTMLElement; - constructor() { + constructor(options: Options) { this._fullscreen = false; + if (options && options.source) { + this._source = options.source; + } bindAll([ '_onClickFullscreen', '_changeIcon' @@ -45,7 +55,7 @@ class FullscreenControl { onAdd(map: Map) { this._map = map; - this._mapContainer = this._map.getContainer(); + if (!this._source) this._source = this._map.getContainer(); this._container = DOM.create('div', `${this._className} mapboxgl-ctrl-group`); if (this._checkFullscreenSupport()) { this._setupUI(); @@ -90,7 +100,7 @@ class FullscreenControl { (window.document: any).webkitFullscreenElement || (window.document: any).msFullscreenElement; - if ((fullscreenElement === this._mapContainer) !== this._fullscreen) { + if ((fullscreenElement === this._source) !== this._fullscreen) { this._fullscreen = !this._fullscreen; this._fullscreenButton.classList.toggle(`${this._className}-shrink`); this._fullscreenButton.classList.toggle(`${this._className}-fullscreen`); @@ -108,14 +118,14 @@ class FullscreenControl { } else if (window.document.webkitCancelFullScreen) { (window.document: any).webkitCancelFullScreen(); } - } else if (this._mapContainer.requestFullscreen) { - this._mapContainer.requestFullscreen(); - } else if ((this._mapContainer: any).mozRequestFullScreen) { - (this._mapContainer: any).mozRequestFullScreen(); - } else if ((this._mapContainer: any).msRequestFullscreen) { - (this._mapContainer: any).msRequestFullscreen(); - } else if ((this._mapContainer: any).webkitRequestFullscreen) { - (this._mapContainer: any).webkitRequestFullscreen(); + } else if (this._source.requestFullscreen) { + this._source.requestFullscreen(); + } else if ((this._source: any).mozRequestFullScreen) { + (this._source: any).mozRequestFullScreen(); + } else if ((this._source: any).msRequestFullscreen) { + (this._source: any).msRequestFullscreen(); + } else if ((this._source: any).webkitRequestFullscreen) { + (this._source: any).webkitRequestFullscreen(); } } } diff --git a/test/unit/ui/control/fullscreen.test.js b/test/unit/ui/control/fullscreen.test.js index 0c38581282b..83adb36590d 100644 --- a/test/unit/ui/control/fullscreen.test.js +++ b/test/unit/ui/control/fullscreen.test.js @@ -27,3 +27,14 @@ test('FullscreenControl does not appears when fullscreen is not enabled', (t) => t.equal(consoleWarn.getCall(0).args[0], 'This device does not support fullscreen mode.'); t.end(); }); + +test('FullscreenControl works with source element other than map container', (t) => { + window.document.fullscreenEnabled = true; + + const map = createMap(t); + const fullscreen = new FullscreenControl({source: 'body'}); + map.addControl(fullscreen); + + t.equal(map.getContainer().querySelectorAll('.mapboxgl-ctrl-fullscreen').length, 1); + t.end(); +}); From 9dfd431914c8b1801f9b19fae51dddf8ce804f5f Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Thu, 8 Nov 2018 13:19:12 -0800 Subject: [PATCH 2/4] Add warning for non DOM element sources --- src/ui/control/fullscreen_control.js | 6 +++++- test/unit/ui/control/fullscreen.test.js | 13 +------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/ui/control/fullscreen_control.js b/src/ui/control/fullscreen_control.js index 79af6736fa3..816a8dd5c57 100644 --- a/src/ui/control/fullscreen_control.js +++ b/src/ui/control/fullscreen_control.js @@ -35,7 +35,11 @@ class FullscreenControl { constructor(options: Options) { this._fullscreen = false; if (options && options.source) { - this._source = options.source; + if (options.source instanceof HTMLElement) { + this._source = options.source; + } else { + warnOnce('Full screen control \'source\' must be a DOM element.'); + } } bindAll([ '_onClickFullscreen', diff --git a/test/unit/ui/control/fullscreen.test.js b/test/unit/ui/control/fullscreen.test.js index 83adb36590d..8697e144019 100644 --- a/test/unit/ui/control/fullscreen.test.js +++ b/test/unit/ui/control/fullscreen.test.js @@ -14,7 +14,7 @@ test('FullscreenControl appears when fullscreen is enabled', (t) => { t.end(); }); -test('FullscreenControl does not appears when fullscreen is not enabled', (t) => { +test('FullscreenControl does not appear when fullscreen is not enabled', (t) => { window.document.fullscreenEnabled = false; const consoleWarn = t.stub(console, 'warn'); @@ -27,14 +27,3 @@ test('FullscreenControl does not appears when fullscreen is not enabled', (t) => t.equal(consoleWarn.getCall(0).args[0], 'This device does not support fullscreen mode.'); t.end(); }); - -test('FullscreenControl works with source element other than map container', (t) => { - window.document.fullscreenEnabled = true; - - const map = createMap(t); - const fullscreen = new FullscreenControl({source: 'body'}); - map.addControl(fullscreen); - - t.equal(map.getContainer().querySelectorAll('.mapboxgl-ctrl-fullscreen').length, 1); - t.end(); -}); From d5da51eeac4908500bb8c83a0e3ce1b3fab155c1 Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Tue, 13 Nov 2018 11:24:37 -0800 Subject: [PATCH 3/4] Use 'container' instead of 'source' for option name --- src/ui/control/fullscreen_control.js | 48 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/ui/control/fullscreen_control.js b/src/ui/control/fullscreen_control.js index 816a8dd5c57..30886e7b90f 100644 --- a/src/ui/control/fullscreen_control.js +++ b/src/ui/control/fullscreen_control.js @@ -8,7 +8,7 @@ import window from '../../util/window'; import type Map from '../map'; type Options = { - source?: HTMLElement + container?: HTMLElement }; /** @@ -16,29 +16,29 @@ type Options = { * * @implements {IControl} * @param {Object} [options] - * @param {HTMLElement} [options.source] `source` is the [compatible DOM element](https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen#Compatible_elements) which should be made full screen. By default, the map container element will be made full screen. + * @param {HTMLElement} [options.container] `container` is the [compatible DOM element](https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen#Compatible_elements) which should be made full screen. By default, the map container element will be made full screen. * * @example - * map.addControl(new mapboxgl.FullscreenControl({source: document.querySelector('body')})); + * map.addControl(new mapboxgl.FullscreenControl({container: document.querySelector('body')})); * @see [View a fullscreen map](https://www.mapbox.com/mapbox-gl-js/example/fullscreen/) */ class FullscreenControl { _map: Map; - _container: HTMLElement; + _controlContainer: HTMLElement; _fullscreen: boolean; _fullscreenchange: string; _fullscreenButton: HTMLElement; _className: string; - _source: HTMLElement; + _container: HTMLElement; constructor(options: Options) { this._fullscreen = false; - if (options && options.source) { - if (options.source instanceof HTMLElement) { - this._source = options.source; + if (options && options.container) { + if (options.container instanceof HTMLElement) { + this._container = options.container; } else { - warnOnce('Full screen control \'source\' must be a DOM element.'); + warnOnce('Full screen control \'container\' must be a DOM element.'); } } bindAll([ @@ -59,19 +59,19 @@ class FullscreenControl { onAdd(map: Map) { this._map = map; - if (!this._source) this._source = this._map.getContainer(); - this._container = DOM.create('div', `${this._className} mapboxgl-ctrl-group`); + if (!this._container) this._container = this._map.getContainer(); + this._controlContainer = DOM.create('div', `${this._className} mapboxgl-ctrl-group`); if (this._checkFullscreenSupport()) { this._setupUI(); } else { - this._container.style.display = 'none'; + this._controlContainer.style.display = 'none'; warnOnce('This device does not support fullscreen mode.'); } - return this._container; + return this._controlContainer; } onRemove() { - DOM.remove(this._container); + DOM.remove(this._controlContainer); this._map = (null: any); window.document.removeEventListener(this._fullscreenchange, this._changeIcon); } @@ -86,7 +86,7 @@ class FullscreenControl { } _setupUI() { - const button = this._fullscreenButton = DOM.create('button', (`${this._className}-icon ${this._className}-fullscreen`), this._container); + const button = this._fullscreenButton = DOM.create('button', (`${this._className}-icon ${this._className}-fullscreen`), this._controlContainer); button.setAttribute("aria-label", "Toggle fullscreen"); button.type = 'button'; this._fullscreenButton.addEventListener('click', this._onClickFullscreen); @@ -104,7 +104,7 @@ class FullscreenControl { (window.document: any).webkitFullscreenElement || (window.document: any).msFullscreenElement; - if ((fullscreenElement === this._source) !== this._fullscreen) { + if ((fullscreenElement === this._container) !== this._fullscreen) { this._fullscreen = !this._fullscreen; this._fullscreenButton.classList.toggle(`${this._className}-shrink`); this._fullscreenButton.classList.toggle(`${this._className}-fullscreen`); @@ -122,14 +122,14 @@ class FullscreenControl { } else if (window.document.webkitCancelFullScreen) { (window.document: any).webkitCancelFullScreen(); } - } else if (this._source.requestFullscreen) { - this._source.requestFullscreen(); - } else if ((this._source: any).mozRequestFullScreen) { - (this._source: any).mozRequestFullScreen(); - } else if ((this._source: any).msRequestFullscreen) { - (this._source: any).msRequestFullscreen(); - } else if ((this._source: any).webkitRequestFullscreen) { - (this._source: any).webkitRequestFullscreen(); + } else if (this._container.requestFullscreen) { + this._container.requestFullscreen(); + } else if ((this._container: any).mozRequestFullScreen) { + (this._container: any).mozRequestFullScreen(); + } else if ((this._container: any).msRequestFullscreen) { + (this._container: any).msRequestFullscreen(); + } else if ((this._container: any).webkitRequestFullscreen) { + (this._container: any).webkitRequestFullscreen(); } } } From 97baa5d02803b0d7b7dfd316ec77ead4ecfbf4b3 Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Tue, 13 Nov 2018 12:33:42 -0800 Subject: [PATCH 4/4] Add unit test --- src/ui/control/fullscreen_control.js | 2 +- test/unit/ui/control/fullscreen.test.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ui/control/fullscreen_control.js b/src/ui/control/fullscreen_control.js index 30886e7b90f..c5c6fbb3bb9 100644 --- a/src/ui/control/fullscreen_control.js +++ b/src/ui/control/fullscreen_control.js @@ -35,7 +35,7 @@ class FullscreenControl { constructor(options: Options) { this._fullscreen = false; if (options && options.container) { - if (options.container instanceof HTMLElement) { + if (options.container instanceof window.HTMLElement) { this._container = options.container; } else { warnOnce('Full screen control \'container\' must be a DOM element.'); diff --git a/test/unit/ui/control/fullscreen.test.js b/test/unit/ui/control/fullscreen.test.js index 8697e144019..56cf4371036 100644 --- a/test/unit/ui/control/fullscreen.test.js +++ b/test/unit/ui/control/fullscreen.test.js @@ -27,3 +27,18 @@ test('FullscreenControl does not appear when fullscreen is not enabled', (t) => t.equal(consoleWarn.getCall(0).args[0], 'This device does not support fullscreen mode.'); t.end(); }); + +test('FullscreenControl makes optional container element full screen', (t) => { + window.document.fullscreenEnabled = true; + + const map = createMap(t); + const fullscreen = new FullscreenControl({container: window.document.querySelector('body')}); + map.addControl(fullscreen); + const control = map._controls.find((ctrl) => { + return ctrl.hasOwnProperty('_fullscreen'); + }); + control._onClickFullscreen(); + + t.equal(control._container.tagName, 'BODY'); + t.end(); +});