/*!
* VisualEditor MediaWiki DesktopArticleTarget init.
*
* This file must remain as widely compatible as the base compatibility
* for MediaWiki itself (see mediawiki/core:/resources/startup.js).
* Avoid use of: SVG, HTML5 DOM, ContentEditable etc.
*
* @copyright See AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/* eslint-disable no-jquery/no-global-selector */
// TODO: ve.now and ve.track should be moved to mw.libs.ve
/* global ve */
/**
* Platform preparation for the MediaWiki view page. This loads (when user needs it) the
* actual MediaWiki integration and VisualEditor library.
*
* @class mw.libs.ve
* @alternateClassName ve.init.mw.DesktopArticleTarget.init
* @singleton
*/
( function () {
var conf, tabMessages, url, pageExists, viewUrl, veEditUrl, veEditSourceUrl,
init, targetPromise,
tabPreference, initialWikitext, oldId,
isLoading, tempWikitextEditor, tempWikitextEditorData,
$toolbarPlaceholder, $toolbarPlaceholderBar,
contentTop, wasFloating,
configData = require( './data.json' ),
veactionToMode = {
edit: 'visual',
editsource: 'source'
},
availableModes = [],
active = false,
targetLoaded = false,
plugins = [],
welcomeDialogDisabled = false,
educationPopupsDisabled = false,
// Defined after document-ready below
$targetContainer = null;
if ( mw.config.get( 'wgMFMode' ) ) {
mw.log.warn( 'Attempted to load desktop target on mobile.' );
return;
}
/**
* Show the loading progress bar
*
* @return {string} mode Edit mode, 'visual' or 'source'
*/
function showLoading() {
if ( isLoading ) {
return;
}
isLoading = true;
$( 'html' ).addClass( 've-activated ve-loading' );
if ( !init.$loading ) {
init.progressBar = new mw.libs.ve.ProgressBarWidget();
init.$loading = $( '
' )
.addClass( 've-init-mw-desktopArticleTarget-loading-overlay' )
.append( init.progressBar.$element );
}
$( document ).on( 'keydown', onDocumentKeyDown );
$toolbarPlaceholderBar.append( init.$loading );
}
/**
* Increment loading progress by one step
*
* See mw.libs.ve.ProgressBarWidget for steps.
*/
function incrementLoadingProgress() {
init.progressBar.incrementLoadingProgress();
}
/**
* Clear and hide the loading progress bar
*/
function clearLoading() {
init.progressBar.clearLoading();
isLoading = false;
$( document ).off( 'keydown', onDocumentKeyDown );
$( 'html' ).removeClass( 've-loading' );
if ( init.$loading ) {
init.$loading.detach();
}
if ( tempWikitextEditor ) {
teardownTempWikitextEditor();
}
hideToolbarPlaceholder();
}
/**
* Handle window scroll events
*
* @param {Event} e
*/
function onWindowScroll() {
var scrollTop = $( document.documentElement ).scrollTop();
var floating = scrollTop > contentTop;
if ( floating !== wasFloating ) {
var width = $targetContainer.outerWidth();
$toolbarPlaceholder.toggleClass( 've-init-mw-desktopArticleTarget-toolbarPlaceholder-floating', floating );
$toolbarPlaceholderBar.css( 'width', width );
wasFloating = floating;
}
}
var onWindowScrollListener = mw.util.throttle( onWindowScroll, 250 );
/**
* Show a placeholder for the VE toolbar
*/
function showToolbarPlaceholder() {
if ( !$toolbarPlaceholder ) {
// Create an equal-height placeholder for the toolbar to avoid vertical jump
// when the real toolbar is ready.
$toolbarPlaceholder = $( '
' ).addClass( 've-init-mw-desktopArticleTarget-toolbarPlaceholder' );
$toolbarPlaceholderBar = $( '
' ).addClass( 've-init-mw-desktopArticleTarget-toolbarPlaceholder-bar' );
$toolbarPlaceholder.append( $toolbarPlaceholderBar );
}
// Toggle -floating class before append (if required) to avoid content moving later
contentTop = $targetContainer.offset().top;
wasFloating = null;
onWindowScroll();
var scrollTopBefore = $( document.documentElement ).scrollTop();
$targetContainer.prepend( $toolbarPlaceholder );
window.addEventListener( 'scroll', onWindowScrollListener, { passive: true } );
if ( wasFloating ) {
// Browser might not support scroll anchoring:
// https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor/Guide_to_scroll_anchoring
// ...so compute the new scroll offset ourselves.
window.scrollTo( 0, scrollTopBefore + $toolbarPlaceholder.outerHeight() );
}
// Add class for transition after first render
setTimeout( function () {
$toolbarPlaceholder.addClass( 've-init-mw-desktopArticleTarget-toolbarPlaceholder-open' );
} );
}
/**
* Hide the placeholder for the VE toolbar
*/
function hideToolbarPlaceholder() {
if ( $toolbarPlaceholder ) {
window.removeEventListener( 'scroll', onWindowScrollListener );
$toolbarPlaceholder.detach();
$toolbarPlaceholder.removeClass( 've-init-mw-desktopArticleTarget-toolbarPlaceholder-open' );
}
}
/**
* Create a temporary `