diff --git a/jsduck.json b/jsduck.json index ba2fa9e0b4b..ef934720cc0 100644 --- a/jsduck.json +++ b/jsduck.json @@ -24,7 +24,8 @@ "resources/src/es6-polyfills", "resources/src/vue", "resources/src/codex", - "resources/src/codex-search" + "resources/src/codex-search", + "resources/src/mediawiki.page.teleportTarget.js" ], "--": [ "maintenance/jsduck/external.js", diff --git a/resources/Resources.php b/resources/Resources.php index 70d0fa38f30..2f4133fbca2 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -553,6 +553,9 @@ return [ ], ], + 'dependencies' => [ + 'mediawiki.page.teleportTarget' + ] ], // Alias for 'vue', for backwards compatibility @@ -1716,6 +1719,16 @@ return [ 'mediawiki.page.media' => [ 'scripts' => 'resources/src/mediawiki.page.media.js', ], + 'mediawiki.page.teleportTarget' => [ + 'localBasePath' => MW_INSTALL_PATH . '/resources/src', + 'remoteBasePath' => "$wgResourceBasePath/resources/src", + 'packageFiles' => [ + 'mediawiki.page.teleportTarget.js', + ], + 'skinStyles' => [ + 'default' => 'mediawiki.page.teleportTarget.less' + ] + ], /* MediaWiki Special pages */ diff --git a/resources/src/mediawiki.page.teleportTarget.js b/resources/src/mediawiki.page.teleportTarget.js new file mode 100644 index 00000000000..caa118d5bb4 --- /dev/null +++ b/resources/src/mediawiki.page.teleportTarget.js @@ -0,0 +1,28 @@ +/** + * Setup a dedicated container element for any modal or dialog + * elements which may need to be displayed on the page. This + * script appends an empty div to the end of the body tag + * that can be used by Codex Dialogs and similar components. + * + * Skins should apply body content styles to this element so that + * dialogs will use the same styles (font sizes, etc). + * + * When this script runs, it immediately adds the div to the + * end of the body tag. Additionally, it makes the created + * DOM node available via module.exports, in case other code + * needs to require it (to spare developers from remembering + * the exact HTML ID for example). + */ +( function () { + const ID = 'mw-teleport-target'; + + // Create an empty div with appropriate ID + const target = document.createElement( 'div' ); + target.setAttribute( 'id', ID ); + + // Append the node to the body + document.body.appendChild( target ); + + // Export the node in case other code needs to reference it + module.exports = target; +}() ); diff --git a/resources/src/mediawiki.page.teleportTarget.less b/resources/src/mediawiki.page.teleportTarget.less new file mode 100644 index 00000000000..96a1aaf3e9b --- /dev/null +++ b/resources/src/mediawiki.page.teleportTarget.less @@ -0,0 +1,6 @@ +@import 'mediawiki.skin.variables.less'; + +#mw-teleport-target { + position: absolute; + z-index: @z-index-overlay; +} diff --git a/resources/src/vue/index.js b/resources/src/vue/index.js index d8f57f34e05..f59cd18b70e 100644 --- a/resources/src/vue/index.js +++ b/resources/src/vue/index.js @@ -2,6 +2,7 @@ const Vue = require( '../../lib/vue/vue.js' ); const errorLogger = require( './errorLogger.js' ); const i18n = require( './i18n.js' ); + const teleportTarget = require( 'mediawiki.page.teleportTarget' ); /** * Replace the given DOM element with its children. @@ -43,6 +44,7 @@ const app = Vue.createApp( options, ...otherArgs ); app.use( errorLogger ); app.use( i18n ); + app.provide( 'CdxTeleportTarget', teleportTarget ); if ( options.store ) { // Provide backwards compatibility for callers expecting Vuex 3