Merge pull request #12893 from andrewcoder002/main
Allow map target to be an external window
This commit is contained in:
@@ -323,7 +323,7 @@ class PluggableMap extends BaseObject {
|
||||
* @private
|
||||
* @type {?Array<import("./events.js").EventsKey>}
|
||||
*/
|
||||
this.keyHandlerKeys_ = null;
|
||||
this.targetChangeHandlerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @type {Collection<import("./control/Control.js").default>}
|
||||
@@ -356,12 +356,6 @@ class PluggableMap extends BaseObject {
|
||||
*/
|
||||
this.renderer_ = null;
|
||||
|
||||
/**
|
||||
* @type {undefined|function(Event): void}
|
||||
* @private
|
||||
*/
|
||||
this.handleResize_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Array<PostRenderFunction>}
|
||||
@@ -1146,21 +1140,11 @@ class PluggableMap extends BaseObject {
|
||||
* @private
|
||||
*/
|
||||
handleTargetChanged_() {
|
||||
// target may be undefined, null, a string or an Element.
|
||||
// If it's a string we convert it to an Element before proceeding.
|
||||
// If it's not now an Element we remove the viewport from the DOM.
|
||||
// If it's an Element we append the viewport element to it.
|
||||
|
||||
let targetElement;
|
||||
if (this.getTarget()) {
|
||||
targetElement = this.getTargetElement();
|
||||
}
|
||||
|
||||
if (this.mapBrowserEventHandler_) {
|
||||
for (let i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {
|
||||
unlistenByKey(this.keyHandlerKeys_[i]);
|
||||
for (let i = 0, ii = this.targetChangeHandlerKeys_.length; i < ii; ++i) {
|
||||
unlistenByKey(this.targetChangeHandlerKeys_[i]);
|
||||
}
|
||||
this.keyHandlerKeys_ = null;
|
||||
this.targetChangeHandlerKeys_ = null;
|
||||
this.viewport_.removeEventListener(
|
||||
EventType.CONTEXTMENU,
|
||||
this.boundHandleBrowserEvent_
|
||||
@@ -1169,15 +1153,17 @@ class PluggableMap extends BaseObject {
|
||||
EventType.WHEEL,
|
||||
this.boundHandleBrowserEvent_
|
||||
);
|
||||
if (this.handleResize_ !== undefined) {
|
||||
removeEventListener(EventType.RESIZE, this.handleResize_, false);
|
||||
this.handleResize_ = undefined;
|
||||
}
|
||||
this.mapBrowserEventHandler_.dispose();
|
||||
this.mapBrowserEventHandler_ = null;
|
||||
removeNode(this.viewport_);
|
||||
}
|
||||
|
||||
// target may be undefined, null, a string or an Element.
|
||||
// If it's a string we convert it to an Element before proceeding.
|
||||
// If it's not now an Element we remove the viewport from the DOM.
|
||||
// If it's an Element we append the viewport element to it.
|
||||
|
||||
const targetElement = this.getTargetElement();
|
||||
if (!targetElement) {
|
||||
if (this.renderer_) {
|
||||
clearTimeout(this.postRenderTimeoutHandle_);
|
||||
@@ -1217,10 +1203,11 @@ class PluggableMap extends BaseObject {
|
||||
PASSIVE_EVENT_LISTENERS ? {passive: false} : false
|
||||
);
|
||||
|
||||
const defaultView = this.getOwnerDocument().defaultView;
|
||||
const keyboardEventTarget = !this.keyboardEventTarget_
|
||||
? targetElement
|
||||
: this.keyboardEventTarget_;
|
||||
this.keyHandlerKeys_ = [
|
||||
this.targetChangeHandlerKeys_ = [
|
||||
listen(
|
||||
keyboardEventTarget,
|
||||
EventType.KEYDOWN,
|
||||
@@ -1233,12 +1220,8 @@ class PluggableMap extends BaseObject {
|
||||
this.handleBrowserEvent,
|
||||
this
|
||||
),
|
||||
listen(defaultView, EventType.RESIZE, this.updateSize, this),
|
||||
];
|
||||
|
||||
if (!this.handleResize_) {
|
||||
this.handleResize_ = this.updateSize.bind(this);
|
||||
window.addEventListener(EventType.RESIZE, this.handleResize_, false);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateSize();
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import MapProperty from '../MapProperty.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_UNSUPPORTED} from '../css.js';
|
||||
import {listen} from '../events.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import {replaceNode} from '../dom.js';
|
||||
|
||||
const events = [
|
||||
@@ -111,6 +112,12 @@ class FullScreen extends Control {
|
||||
this.cssClassName_ =
|
||||
options.className !== undefined ? options.className : 'ol-full-screen';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("../events.js").EventsKey>}
|
||||
*/
|
||||
this.documentListeners_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
@@ -157,7 +164,6 @@ class FullScreen extends Control {
|
||||
this.button_ = document.createElement('button');
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
this.setClassName_(this.button_, isFullScreen());
|
||||
this.button_.setAttribute('type', 'button');
|
||||
this.button_.title = tipLabel;
|
||||
this.button_.appendChild(this.labelNode_);
|
||||
@@ -168,17 +174,8 @@ class FullScreen extends Control {
|
||||
false
|
||||
);
|
||||
|
||||
const cssClasses =
|
||||
this.cssClassName_ +
|
||||
' ' +
|
||||
CLASS_UNSELECTABLE +
|
||||
' ' +
|
||||
CLASS_CONTROL +
|
||||
' ' +
|
||||
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.button_);
|
||||
this.element.className = `${this.cssClassName_} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
|
||||
this.element.appendChild(this.button_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -191,6 +188,17 @@ class FullScreen extends Control {
|
||||
* @type {HTMLElement|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isInFullscreen_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleMapTargetChange_ = this.handleMapTargetChange_.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,21 +214,22 @@ class FullScreen extends Control {
|
||||
* @private
|
||||
*/
|
||||
handleFullScreen_() {
|
||||
if (!isFullScreenSupported()) {
|
||||
return;
|
||||
}
|
||||
const map = this.getMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
if (isFullScreen()) {
|
||||
exitFullScreen();
|
||||
const doc = map.getOwnerDocument();
|
||||
if (!isFullScreenSupported(doc)) {
|
||||
return;
|
||||
}
|
||||
if (isFullScreen(doc)) {
|
||||
exitFullScreen(doc);
|
||||
} else {
|
||||
let element;
|
||||
if (this.source_) {
|
||||
element =
|
||||
typeof this.source_ === 'string'
|
||||
? document.getElementById(this.source_)
|
||||
? doc.getElementById(this.source_)
|
||||
: this.source_;
|
||||
} else {
|
||||
element = map.getTargetElement();
|
||||
@@ -238,16 +247,20 @@ class FullScreen extends Control {
|
||||
*/
|
||||
handleFullScreenChange_() {
|
||||
const map = this.getMap();
|
||||
if (isFullScreen()) {
|
||||
this.setClassName_(this.button_, true);
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
this.dispatchEvent(FullScreenEventType.ENTERFULLSCREEN);
|
||||
} else {
|
||||
this.setClassName_(this.button_, false);
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
this.dispatchEvent(FullScreenEventType.LEAVEFULLSCREEN);
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
if (map) {
|
||||
const wasInFullscreen = this.isInFullscreen_;
|
||||
this.isInFullscreen_ = isFullScreen(map.getOwnerDocument());
|
||||
if (wasInFullscreen !== this.isInFullscreen_) {
|
||||
this.setClassName_(this.button_, this.isInFullscreen_);
|
||||
if (this.isInFullscreen_) {
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
this.dispatchEvent(FullScreenEventType.ENTERFULLSCREEN);
|
||||
} else {
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
this.dispatchEvent(FullScreenEventType.LEAVEFULLSCREEN);
|
||||
}
|
||||
map.updateSize();
|
||||
}
|
||||
}
|
||||
@@ -274,37 +287,76 @@ class FullScreen extends Control {
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
const oldMap = this.getMap();
|
||||
if (oldMap) {
|
||||
oldMap.removeChangeListener(
|
||||
MapProperty.TARGET,
|
||||
this.boundHandleMapTargetChange_
|
||||
);
|
||||
}
|
||||
|
||||
super.setMap(map);
|
||||
|
||||
this.handleMapTargetChange_();
|
||||
if (map) {
|
||||
map.addChangeListener(
|
||||
MapProperty.TARGET,
|
||||
this.boundHandleMapTargetChange_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleMapTargetChange_() {
|
||||
const listeners = this.documentListeners_;
|
||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||
unlistenByKey(listeners[i]);
|
||||
}
|
||||
listeners.length = 0;
|
||||
|
||||
const map = this.getMap();
|
||||
if (map) {
|
||||
const doc = map.getOwnerDocument();
|
||||
if (isFullScreenSupported(doc)) {
|
||||
this.element.classList.remove(CLASS_UNSUPPORTED);
|
||||
} else {
|
||||
this.element.classList.add(CLASS_UNSUPPORTED);
|
||||
}
|
||||
|
||||
for (let i = 0, ii = events.length; i < ii; ++i) {
|
||||
this.listenerKeys.push(
|
||||
listen(document, events[i], this.handleFullScreenChange_, this)
|
||||
listeners.push(
|
||||
listen(doc, events[i], this.handleFullScreenChange_, this)
|
||||
);
|
||||
}
|
||||
this.handleFullScreenChange_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc The root document to check.
|
||||
* @return {boolean} Fullscreen is supported by the current platform.
|
||||
*/
|
||||
function isFullScreenSupported() {
|
||||
const body = document.body;
|
||||
function isFullScreenSupported(doc) {
|
||||
const body = doc.body;
|
||||
return !!(
|
||||
body['webkitRequestFullscreen'] ||
|
||||
(body['msRequestFullscreen'] && document['msFullscreenEnabled']) ||
|
||||
(body.requestFullscreen && document.fullscreenEnabled)
|
||||
(body['msRequestFullscreen'] && doc['msFullscreenEnabled']) ||
|
||||
(body.requestFullscreen && doc.fullscreenEnabled)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc The root document to check.
|
||||
* @return {boolean} Element is currently in fullscreen.
|
||||
*/
|
||||
function isFullScreen() {
|
||||
function isFullScreen(doc) {
|
||||
return !!(
|
||||
document['webkitIsFullScreen'] ||
|
||||
document['msFullscreenElement'] ||
|
||||
document.fullscreenElement
|
||||
doc['webkitIsFullScreen'] ||
|
||||
doc['msFullscreenElement'] ||
|
||||
doc.fullscreenElement
|
||||
);
|
||||
}
|
||||
|
||||
@@ -336,14 +388,15 @@ function requestFullScreenWithKeys(element) {
|
||||
|
||||
/**
|
||||
* Exit fullscreen.
|
||||
* @param {Document} doc The document to exit fullscren from
|
||||
*/
|
||||
function exitFullScreen() {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document['msExitFullscreen']) {
|
||||
document['msExitFullscreen']();
|
||||
} else if (document['webkitExitFullscreen']) {
|
||||
document['webkitExitFullscreen']();
|
||||
function exitFullScreen(doc) {
|
||||
if (doc.exitFullscreen) {
|
||||
doc.exitFullscreen();
|
||||
} else if (doc['msExitFullscreen']) {
|
||||
doc['msExitFullscreen']();
|
||||
} else if (doc['webkitExitFullscreen']) {
|
||||
doc['webkitExitFullscreen']();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,9 @@ export const altShiftKeysOnly = function (mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const focus = function (event) {
|
||||
return event.target.getTargetElement().contains(document.activeElement);
|
||||
const targetElement = event.map.getTargetElement();
|
||||
const activeElement = event.map.getOwnerDocument().activeElement;
|
||||
return targetElement.contains(activeElement);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user