* Add an HTTP header that will influence on the cache
*
* @param string $header Header name
- * @param array|null $option
- * @todo FIXME: Document the $option parameter; it appears to be for
- * X-Vary-Options but what format is acceptable?
+ * @param string[]|null $option Options for X-Vary-Options. Possible options are:
+ * - "string-contains=$XXX" varies on whether the header value as a string
+ * contains $XXX as a substring.
+ * - "list-contains=$XXX" varies on whether the header value as a
+ * comma-separated list contains $XXX as one of the list items.
*/
public function addVaryHeader( $header, $option = null ) {
if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
'mediawiki.ui.input',
'mediawiki.special.userlogin.common.styles'
) );
- $out->addModules( array(
- 'mediawiki.special.userlogin.common.js'
- ) );
if ( $this->mType == 'signup' ) {
// XXX hack pending RL or JS parse() support for complex content messages
'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css',
),
),
- 'mediawiki.special.userlogin.common.js' => array(
- 'scripts' => array(
- 'resources/src/mediawiki.special/mediawiki.special.userlogin.common.js',
- ),
- 'messages' => array(
- 'createacct-captcha',
- 'createacct-imgcaptcha-ph',
- ),
- ),
'mediawiki.special.userlogin.signup.js' => array(
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js',
'messages' => array(
'resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js',
'resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js',
'resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js',
),
'skinStyles' => array(
'default' => array(
+++ /dev/null
-/*!
- * JavaScript for login and signup forms.
- */
-( function ( mw, $ ) {
- // Move the FancyCaptcha image into a more attractive container.
- // The CAPTCHA is in a <div class="captcha"> at the top of the form. If it's a FancyCaptcha,
- // then we remove it and insert it lower down, in a customized div with just what we need (e.g.
- // no 'fancycaptcha-createaccount' message).
- function adjustFancyCaptcha( $content, buttonSubmit ) {
- var $submit = $content.find( buttonSubmit ),
- tabIndex,
- $captchaStuff,
- $captchaImageContainer,
- // JavaScript can't yet parse the message 'createacct-imgcaptcha-help' when it
- // contains a MediaWiki transclusion, so PHP parses it and sends the HTML.
- // This is only set for the signup form (and undefined for login).
- helpMsg = mw.config.get( 'wgCreateacctImgcaptchaHelp' ),
- helpHtml = '';
-
- if ( !$submit.length ) {
- return;
- }
- tabIndex = $submit.prop( 'tabIndex' ) - 1;
- $captchaStuff = $content.find( '.captcha' );
-
- if ( $captchaStuff.length ) {
- // The FancyCaptcha has this class in the ConfirmEdit extension since 2013-04-18.
- $captchaImageContainer = $captchaStuff.find( '.fancycaptcha-image-container' );
- if ( $captchaImageContainer.length !== 1 ) {
- return;
- }
-
- $captchaStuff.remove();
-
- if ( helpMsg ) {
- helpHtml = '<small class="mw-createacct-captcha-assisted">' + helpMsg + '</small>';
- }
-
- // Insert another div before the submit button that will include the
- // repositioned FancyCaptcha div, an input field, and possible help.
- $submit.closest( 'div' ).before( [
- '<div>',
- '<label for="wpCaptchaWord">' + mw.message( 'createacct-captcha' ).escaped() + '</label>',
- '<div class="mw-createacct-captcha-container">',
- '<div class="mw-createacct-captcha-and-reload" />',
- '<input id="wpCaptchaWord" class="mw-ui-input" name="wpCaptchaWord" type="text" placeholder="' +
- mw.message( 'createacct-imgcaptcha-ph' ).escaped() +
- '" tabindex="' + tabIndex + '" autocapitalize="off" autocorrect="off">',
- helpHtml,
- '</div>',
- '</div>'
- ].join( '' ) );
-
- // Stick the FancyCaptcha container inside our bordered and framed parents.
- $captchaImageContainer
- .prependTo( $content.find( '.mw-createacct-captcha-and-reload' ) );
-
- // Find the input field, add the text (if any) of the existing CAPTCHA
- // field (although usually it's blanked out on every redisplay),
- // and after it move over the hidden field that tells the CAPTCHA
- // what to do.
- $content.find( '#wpCaptchaWord' )
- .val( $captchaStuff.find( '#wpCaptchaWord' ).val() )
- .after( $captchaStuff.find( '#wpCaptchaId' ) );
- }
- }
-
- $( function () {
- // Work with both login and signup form
- adjustFancyCaptcha( $( '#mw-content-text' ), '#wpCreateaccount, #wpLoginAttempt' );
- } );
-}( mediaWiki, jQuery ) );
--- /dev/null
+/*!
+ * MediaWiki Widgets - CategorySelector class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Category selector widget. Displays an OO.ui.CapsuleMultiSelectWidget
+ * and autocompletes with available categories.
+ *
+ * @class
+ * @uses mw.Api
+ * @extends OO.ui.CapsuleMultiSelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ mw.widgets.CategorySelector = function ( config ) {
+ // Parent constructor
+ mw.widgets.CategorySelector.parent.call( this, config );
+
+ // Event handler to call the autocomplete methods
+ this.$input.on( 'change input cut paste', OO.ui.debounce( this.updateMenuItems.bind( this ), 100 ) );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.CategorySelector, OO.ui.CapsuleMultiSelectWidget );
+
+ /* Methods */
+
+ /**
+ * Gets new items based on the input by calling
+ * {@link #getNewMenuItems getNewItems} and updates the menu
+ * after removing duplicates based on the data value.
+ *
+ * @private
+ * @method
+ */
+ mw.widgets.CategorySelector.prototype.updateMenuItems = function () {
+ this.getNewMenuItems( this.$input.val() ).then( function ( items ) {
+ var existingItems, filteredItems,
+ menu = this.getMenu();
+
+ // Array of strings of the data of OO.ui.MenuOptionsWidgets
+ existingItems = menu.getItems().map( function ( item ) {
+ return item.data;
+ } );
+
+ // Remove if items' data already exists
+ filteredItems = items.filter( function ( item ) {
+ return existingItems.indexOf( item.data ) === -1;
+ } );
+
+ // Map to an array of OO.ui.MenuOptionWidgets
+ filteredItems = filteredItems.map( function ( item ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: item.data,
+ label: item.label
+ } );
+ } );
+
+ menu.addItems( filteredItems ).updateItemVisibility();
+ }.bind( this ) );
+ };
+
+ /**
+ * Searches for categories based on the input.
+ *
+ * @private
+ * @method
+ * @param {string} input The input used to prefix search categories
+ * @return {jQuery.Promise} Resolves with an array of categories
+ */
+ mw.widgets.CategorySelector.prototype.getNewMenuItems = function ( input ) {
+ var deferred = new $.Deferred(),
+ catNsId = mw.config.get( 'wgNamespaceIds' ).category,
+ api = new mw.Api();
+
+ api.get( {
+ action: 'opensearch',
+ namespace: catNsId,
+ limit: 10,
+ search: input
+ } ).done( function ( res ) {
+ var categoryNames = res[ 1 ].map( function ( name ) {
+ return mw.Title.newFromText( name, catNsId ).getMainText();
+ } );
+
+ deferred.resolve( categoryNames.map( function ( category ) {
+ return {
+ data: category,
+ label: category
+ };
+ } ) );
+ } );
+
+ return deferred.promise();
+ };
+}( jQuery, mediaWiki ) );