MediaWiki:Gadget-mediawiki.toolbar.js
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;
Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5./**
* Interface for the classic edit toolbar.
*
* Adapted from MediaWiki Core, before it was removed from it on 2018-10-17
*
* Dependencies:
* - jquery.textSelection, used when calling insertTags() (when clicking on a button, or manually called)
*/
( function () {
'use strict';
var toolbar, deferred, currentFocused;
/**
* Internal helper that does the actual insertion of the button into the toolbar.
*
* For backwards-compatibility, passing `imageFile`, `speedTip`, `tagOpen`, `tagClose`,
* `sampleText` and `imageId` as separate arguments (in this order) is also supported.
*
* @private
*
* @param {Object} button Object with the following properties.
* You are required to provide *either* the `callback` parameter, or the three parameters
* `tagOpen`, `tagClose` and `sampleText`, but not both (they're mutually exclusive).
* @param {string} [button.imageFile] Image to use for the button.
* @param {string} button.speedTip Tooltip displayed when user mouses over the button.
* @param {Function} [button.callback] Function to be executed when the button is clicked.
* @param {string} [button.tagOpen]
* @param {string} [button.tagClose]
* @param {string} [button.sampleText] Alternative to `callback`. `tagOpen`, `tagClose` and
* `sampleText` together provide the markup that should be inserted into page text at
* current cursor position.
* @param {string} [button.imageId] `id` attribute of the button HTML element. Can be
* used to define the image with CSS if it's not provided as `imageFile`.
* @param {string} [speedTip]
* @param {string} [tagOpen]
* @param {string} [tagClose]
* @param {string} [sampleText]
* @param {string} [imageId]
*/
function insertButton( button, speedTip, tagOpen, tagClose, sampleText, imageId ) {
var oldButton, $button;
// Backwards compatibility
if ( typeof button !== 'object' ) {
button = {
imageFile: button,
speedTip: speedTip,
tagOpen: tagOpen,
tagClose: tagClose,
sampleText: sampleText,
imageId: imageId
};
}
if ( button.imageId ) {
var oldButton = document.getElementById( button.imageId );
if ( oldButton ) {
oldButton.parentNode.removeChild( oldButton );
}
}
if ( button.imageFile ) {
$button = $( '<img>' ).attr( {
src: button.imageFile,
alt: button.speedTip,
title: button.speedTip,
id: button.imageId || undefined,
'class': 'mw-toolbar-editbutton'
} );
} else {
$button = $( '<div>' ).attr( {
title: button.speedTip,
id: button.imageId || undefined,
'class': 'mw-toolbar-editbutton'
} );
}
$button.click( function ( e ) {
e.preventDefault();
if ( button.callback ) {
button.callback();
} else {
toolbar.insertTags( button.tagOpen, button.tagClose, button.sampleText );
}
} );
getToolbar().append( $button );
}
/**
* Get the toolbar, lazy-creating it the first time this function is called.
*
* The result is a jQuery object, that may be empty if toolbar creation failed.
*
* @private
* @return {jQuery}
*/
function getToolbar() {
var $toolbar, textbox;
if ( !getToolbar.$cache ) {
$toolbar = $( '#toolbar' );
if ( !$toolbar.length ) {
textbox = getTextbox();
if ( textbox ) {
$toolbar = $( '<div>' ).attr( 'id', 'toolbar' );
// Undo #toolbar {height:22px} added by MediaWiki,
// which causes troubles if the toolbar takes several lines
$toolbar.css( 'height', 'auto' );
$toolbar.insertBefore( textbox );
}
}
getToolbar.$cache = $toolbar;
}
return getToolbar.$cache;
}
/**
* Get the wpTextbox1 element, using a cache for performance.
*
* @private
* @return {HTMLTextAreaElement|null}
*/
function getTextbox() {
if ( !getTextbox.cache ) {
getTextbox.cache = document.getElementById( 'wpTextbox1' );
}
return getTextbox.cache;
}
/**
* @private
* @property {jQuery.Deferred}
* Deferred object that will be resolved when the toolbar is ready to be populated.
*/
deferred = $.Deferred();
/**
* @class mw.toolbar
* @singleton
*/
toolbar = {
/**
* Add buttons to the toolbar.
*
* Takes care of race conditions and time-based dependencies by placing buttons in a queue if
* this method is called before the toolbar is created.
*
* For backwards-compatibility, passing `imageFile`, `speedTip`, `tagOpen`, `tagClose`,
* `sampleText` and `imageId` as separate arguments (in this order) is also supported.
*
* @inheritdoc #insertButton
*/
addButton: function () {
var buttonArguments = [].slice.call( arguments );
deferred.done( function () {
insertButton.apply( toolbar, buttonArguments );
} );
},
/**
* Apply tagOpen/tagClose to selection in currently focused textarea.
*
* Uses `sampleText` if selection is empty.
*
* @param {string} tagOpen
* @param {string} tagClose
* @param {string} sampleText
*/
insertTags: function ( tagOpen, tagClose, sampleText ) {
var target = this.getCurrentFocused();
if ( !target ) {
return;
}
$( target ).textSelection(
'encapsulateSelection', {
pre: tagOpen || '',
peri: sampleText || '',
post: tagClose || ''
}
);
},
/**
* Get the element whose selection is to be manipulated.
*
* @return {HTMLTextAreaElement|HTMLInputElement|null}
*/
getCurrentFocused: function () {
if ( !currentFocused ) {
currentFocused = getTextbox();
}
return currentFocused;
}
};
// Expose API publicly
mw.toolbar = toolbar;
$( function ( $ ) {
deferred.resolve();
// Apply to dynamically created textboxes as well as normal ones
$( document ).on( 'focus', 'textarea, input:text, .CodeMirror', function () {
if ( this.classList.contains( 'CodeMirror' ) ) {
// CodeMirror hooks into #wpTextbox1 for textSelection changes
currentFocused = getTextbox();
} else {
currentFocused = this;
}
} );
} );
}() );