Файловый менеджер - Редактировать - /var/www/html/mediawiki.widgets.zip
Ðазад
PK ! �0��� � ( mw.widgets.NamespacesMenuOptionWidget.jsnu �Iw�� /*! * MediaWiki Widgets - NamespacesMenuOptionWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Returns an item match text that includes both the label * and the data, so the menu can filter on either. * * @class * @extends OO.ui.MenuOptionWidget * * @constructor * @description Create an mw.widgets.NamespacesMenuOptionWidget object. * @param {Object} [config] Configuration options */ mw.widgets.NamespacesMenuOptionWidget = function MwWidgetsNamespacesMenuOptionWidget( config ) { // Parent mw.widgets.NamespacesMenuOptionWidget.super.call( this, config ); }; /* Setup */ OO.inheritClass( mw.widgets.NamespacesMenuOptionWidget, OO.ui.MenuOptionWidget ); /** * @inheritdoc */ mw.widgets.NamespacesMenuOptionWidget.prototype.getMatchText = function () { return this.getData() + ' ' + this.getLabel(); }; }() ); PK ! y���� � mw.widgets.TitleOptionWidget.jsnu �Iw�� /*! * MediaWiki Widgets - TitleOptionWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Title option widget. * * @class * @extends OO.ui.MenuOptionWidget * * @constructor * @description Create a mw.widgets.TitleOptionWidget object. * @param {Object} config Configuration options * @param {string} config.data Label to display * @param {string} config.url URL of page * @param {boolean} [config.showImages] Whether to attempt to show images * @param {string} [config.imageUrl] Thumbnail image URL with URL encoding * @param {string} [config.description] Page description * @param {boolean} [config.missing] Page doesn't exist * @param {boolean} [config.redirect] Page is a redirect * @param {boolean} [config.disambiguation] Page is a disambiguation page * @param {string} [config.query] Matching query string to highlight * @param {Function} [config.compare] String comparison function for query highlighting */ mw.widgets.TitleOptionWidget = function MwWidgetsTitleOptionWidget( config ) { let icon; if ( !config.showImages ) { icon = null; } else if ( config.missing ) { icon = 'articleNotFound'; } else if ( config.redirect ) { icon = 'articleRedirect'; } else if ( config.disambiguation ) { icon = 'articleDisambiguation'; } else { icon = 'article'; } // Config initialization config = Object.assign( { icon: icon, label: config.data, autoFitLabel: false, $label: $( '<a>' ) }, config ); // Parent constructor mw.widgets.TitleOptionWidget.super.call( this, config ); // Remove check icon this.checkIcon.$element.remove(); // Initialization this.$label.attr( 'href', config.url ); this.$element.addClass( 'mw-widget-titleOptionWidget' ); // OOUI OptionWidgets make an effort to not be tab accessible, but // adding a link inside them would undo that. So, explicitly make it // not tabbable. this.$label.attr( 'tabindex', '-1' ); // Allow opening the link in new tab, but not regular navigation. this.$label.on( 'click', ( e ) => { // Don't interfere with special clicks (e.g. to open in new tab) if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) { e.preventDefault(); } } ); // Highlight matching parts of link suggestion if ( config.query ) { this.setHighlightedQuery( config.data, config.query, config.compare, true ); } this.$label.attr( 'title', config.data ); if ( config.missing ) { this.$label.addClass( 'new' ); } else if ( config.redirect ) { this.$label.addClass( 'mw-redirect' ); } else if ( config.disambiguation ) { this.$label.addClass( 'mw-disambig' ); } if ( config.showImages && config.imageUrl ) { this.$icon .addClass( 'mw-widget-titleOptionWidget-hasImage mw-no-invert' ) .css( 'background-image', 'url(' + config.imageUrl + ')' ); } if ( config.description ) { this.$element.append( $( '<span>' ) .addClass( 'mw-widget-titleOptionWidget-description' ) .text( config.description ) .attr( 'title', config.description ) ); } }; /* Setup */ OO.inheritClass( mw.widgets.TitleOptionWidget, OO.ui.MenuOptionWidget ); }() ); PK ! F��8V 8V mw.widgets.DateInputWidget.jsnu �Iw�� /*! * MediaWiki Widgets – DateInputWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ /* global moment */ ( function () { /** * @classdesc Date input widget. * * @example * // Date input widget showcase * let fieldset = new OO.ui.FieldsetLayout( { * items: [ * new OO.ui.FieldLayout( * new mw.widgets.DateInputWidget(), * { * align: 'top', * label: 'Select date' * } * ), * new OO.ui.FieldLayout( * new mw.widgets.DateInputWidget( { precision: 'month' } ), * { * align: 'top', * label: 'Select month' * } * ), * new OO.ui.FieldLayout( * new mw.widgets.DateInputWidget( { * inputFormat: 'DD.MM.YYYY', * displayFormat: 'Do [of] MMMM [anno Domini] YYYY' * } ), * { * align: 'top', * label: 'Select date (custom formats)' * } * ) * ] * } ); * $( document.body ).append( fieldset.$element ); * * // The value is stored in 'YYYY-MM-DD' or 'YYYY-MM' format * * @example * // Accessing values in a date input widget * let dateInput = new mw.widgets.DateInputWidget(); * let $label = $( '<p>' ); * $( document.body ).append( $label, dateInput.$element ); * dateInput.on( 'change', function () { * // The value will always be a valid date or empty string, malformed input is ignored * let date = dateInput.getValue(); * $label.text( 'Selected date: ' + ( date || '(none)' ) ); * } ); * * @class * @extends OO.ui.TextInputWidget * @mixes OO.ui.mixin.IndicatorElement * * @constructor * @description Create an mw.widgets.DateInputWidget object. * @param {Object} [config] Configuration options * @param {string} [config.precision='day'] Date precision to use, 'day' or 'month' * @param {string} [config.value] Day or month date (depending on `precision`), in the format 'YYYY-MM-DD' * or 'YYYY-MM'. If not given or empty string, no date is selected. * @param {string} [config.inputFormat] Date format string to use for the textual input field. Displayed * while the widget is active, and the user can type in a date in this format. Should be short * and easy to type. When not given, defaults to 'YYYY-MM-DD' or 'YYYY-MM', depending on * `precision`. * @param {string} [config.displayFormat] Date format string to use for the clickable label. Displayed * while the widget is inactive. Should be as unambiguous as possible (for example, prefer to * spell out the month, rather than rely on the order), even if that makes it longer. When not * given, the default is language-specific. * @param {boolean} [config.longDisplayFormat=false] If a custom displayFormat is not specified, use * unabbreviated day of the week and month names in the default language-specific displayFormat. * @param {string} [config.placeholderLabel=No date selected] Placeholder text shown when the widget is not * selected. Default text taken from message `mw-widgets-dateinput-no-date`. * @param {string} [config.placeholderDateFormat] User-visible date format string displayed in the textual input * field when it's empty. Should be the same as `inputFormat`, but translated to the user's * language. When not given, defaults to a translated version of 'YYYY-MM-DD' or 'YYYY-MM', * depending on `precision`. * @param {boolean} [config.required=false] Mark the field as required. Implies `indicator: 'required'`. * @param {string} [config.mustBeAfter] Validates the date to be after this. In the 'YYYY-MM-DD' format. * @param {string} [config.mustBeBefore] Validates the date to be before this. In the 'YYYY-MM-DD' format. * @param {jQuery} [config.$overlay] Render the calendar into a separate layer. This configuration is * useful in cases where the expanded calendar is larger than its container. The specified * overlay layer is usually on top of the container and has a larger area. By default, the * calendar uses relative positioning. * @param {Object} [config.calendar] Configuration options for the this input's * {@link mw.widgets.CalendarWidget CalendarWidget}. */ mw.widgets.DateInputWidget = function MWWDateInputWidget( config ) { // Config initialization config = Object.assign( { precision: 'day', longDisplayFormat: false, required: false, placeholderLabel: mw.msg( 'mw-widgets-dateinput-no-date' ) }, config ); if ( config.required ) { if ( config.indicator === undefined ) { config.indicator = 'required'; } } let placeholderDateFormat; if ( config.placeholderDateFormat ) { placeholderDateFormat = config.placeholderDateFormat; } else if ( config.inputFormat ) { // We have no way to display a translated placeholder for custom formats placeholderDateFormat = ''; } else { // The following messages are used here: // * mw-widgets-dateinput-placeholder-day // * mw-widgets-dateinput-placeholder-month placeholderDateFormat = mw.msg( 'mw-widgets-dateinput-placeholder-' + config.precision ); } // Properties (must be set before parent constructor, which calls #setValue) this.$handle = $( '<div>' ); this.innerLabel = new OO.ui.LabelWidget(); this.textInput = new OO.ui.TextInputWidget( { required: config.required, placeholder: placeholderDateFormat, validate: this.validateDate.bind( this ) } ); this.calendar = new mw.widgets.CalendarWidget( Object.assign( { lazyInitOnToggle: true, // Can't pass `$floatableContainer: this.$element` here, the latter is not set yet. // Instead we call setFloatableContainer() below. precision: config.precision }, config.calendar ) ); this.inCalendar = 0; this.inTextInput = 0; this.closing = false; this.inputFormat = config.inputFormat; this.displayFormat = config.displayFormat; this.longDisplayFormat = config.longDisplayFormat; this.required = config.required; this.placeholderLabel = config.placeholderLabel; // Validate and set min and max dates as properties if ( config.mustBeAfter !== undefined ) { const mustBeAfter = moment( config.mustBeAfter, 'YYYY-MM-DD' ); if ( mustBeAfter.isValid() ) { this.mustBeAfter = mustBeAfter; } } if ( config.mustBeBefore !== undefined ) { const mustBeBefore = moment( config.mustBeBefore, 'YYYY-MM-DD' ); if ( mustBeBefore.isValid() ) { this.mustBeBefore = mustBeBefore; } } // Parent constructor mw.widgets.DateInputWidget.super.call( this, config ); // Mixin constructors OO.ui.mixin.IndicatorElement.call( this, config ); // Events this.calendar.connect( this, { change: 'onCalendarChange' } ); this.textInput.connect( this, { enter: 'onEnter', change: 'onTextInputChange' } ); this.$element.on( { focusout: this.onBlur.bind( this ) } ); this.calendar.$element.on( { focusout: this.onBlur.bind( this ), click: this.onCalendarClick.bind( this ), keypress: this.onCalendarKeyPress.bind( this ) } ); this.$handle.on( { click: this.onClick.bind( this ), keypress: this.onKeyPress.bind( this ), focus: this.onFocus.bind( this ) } ); // Initialization // Move 'tabindex' from this.$input (which is invisible) to the visible handle if ( !this.isDisabled() ) { this.setTabIndexedElement( this.$handle ); } this.$handle .append( this.innerLabel.$element, this.$indicator ) .addClass( 'mw-widget-dateInputWidget-handle' ); this.calendar.$element .addClass( 'mw-widget-dateInputWidget-calendar' ); this.$element .addClass( 'mw-widget-dateInputWidget' ) .append( this.$handle, this.textInput.$element, this.calendar.$element ); const $overlay = config.$overlay === true ? OO.ui.getDefaultOverlay() : config.$overlay; if ( $overlay ) { this.calendar.setFloatableContainer( this.$element ); $overlay.append( this.calendar.$element ); // The text input and calendar are not in DOM order, so fix up focus transitions. this.textInput.$input.on( 'keydown', ( e ) => { if ( e.which === OO.ui.Keys.TAB ) { if ( e.shiftKey ) { // Tabbing backward from text input: normal browser behavior } else { // Tabbing forward from text input: just focus the calendar this.calendar.$element.trigger( 'focus' ); return false; } } } ); this.calendar.$element.on( 'keydown', ( e ) => { if ( e.which === OO.ui.Keys.TAB ) { if ( e.shiftKey ) { // Tabbing backward from calendar: just focus the text input this.textInput.$input.trigger( 'focus' ); return false; } else { // Tabbing forward from calendar: focus the text input, then allow normal browser // behavior to move focus to next focusable after it this.textInput.$input.trigger( 'focus' ); } } } ); } // Set handle label and hide stuff this.updateUI(); this.textInput.toggle( false ); this.calendar.toggle( false ); // Hide unused <input> from PHP after infusion is done // See InputWidget#reusePreInfuseDOM about config.$input if ( config.$input ) { config.$input.addClass( 'oo-ui-element-hidden' ); } }; /* Inheritance */ OO.inheritClass( mw.widgets.DateInputWidget, OO.ui.TextInputWidget ); OO.mixinClass( mw.widgets.DateInputWidget, OO.ui.mixin.IndicatorElement ); /* Events */ /** * Fired when the widget is deactivated (when the calendar is closed). This can happen because * the user selected a value, or because the user blurred the widget. * * @event mw.widgets.DateInputWidget.deactivate * @param {boolean} userSelected Whether the deactivation happened because the user selected a value */ /* Methods */ /** * @inheritdoc * @protected */ mw.widgets.DateInputWidget.prototype.getInputElement = function () { return $( '<input>' ).attr( 'type', 'hidden' ); }; /** * Respond to calendar date change events. * * @private */ mw.widgets.DateInputWidget.prototype.onCalendarChange = function () { this.inCalendar++; if ( !this.inTextInput ) { // If this is caused by user typing in the input field, do not set anything. // The value may be invalid (see #onTextInputChange), but displayable on the calendar. this.setValue( this.calendar.getDate() ); } this.inCalendar--; }; /** * Respond to text input value change events. * * @private */ mw.widgets.DateInputWidget.prototype.onTextInputChange = function () { const widget = this, value = this.textInput.getValue(), mom = moment( value, this.getInputFormat() ), valid = this.isValidDate( value ); this.inTextInput++; if ( value === '' ) { // No date selected widget.setValue( '' ); } else if ( valid ) { // Well-formed date value, parse and set it // Use English locale to avoid number formatting widget.setValue( mom.locale( 'en' ).format( widget.getInternalFormat() ) ); } else { // Not well-formed, but possibly partial? Try updating the calendar, but do not set the // internal value. Generally this only makes sense when 'inputFormat' is little-endian (e.g. // 'YYYY-MM-DD'), but that's hard to check for, and might be difficult to handle the parsing // right for weird formats. So limit this trick to only when we're using the default // 'inputFormat', which is the same as the internal format, 'YYYY-MM-DD'. if ( widget.getInputFormat() === widget.getInternalFormat() ) { widget.calendar.setMoment( mom ); } } widget.inTextInput--; }; /** * @inheritdoc */ mw.widgets.DateInputWidget.prototype.setValue = function ( value ) { const oldValue = this.value; if ( !moment( value, this.getInternalFormat() ).isValid() ) { value = ''; } mw.widgets.DateInputWidget.super.prototype.setValue.call( this, value ); if ( this.value !== oldValue ) { this.updateUI(); this.setValidityFlag(); } return this; }; /** * Handle text input and calendar blur events. * * @private */ mw.widgets.DateInputWidget.prototype.onBlur = function () { setTimeout( () => { const $focussed = $( ':focus' ); // Deactivate unless the focus moved to something else inside this widget if ( !OO.ui.contains( this.$element[ 0 ], $focussed[ 0 ], true ) && // Calendar might be in an $overlay !OO.ui.contains( this.calendar.$element[ 0 ], $focussed[ 0 ], true ) ) { this.deactivate(); } }, 0 ); }; /** * @inheritdoc */ mw.widgets.DateInputWidget.prototype.focus = function () { this.activate(); return this; }; /** * @inheritdoc */ mw.widgets.DateInputWidget.prototype.blur = function () { this.deactivate(); return this; }; /** * Update the contents of the label, text input and status of calendar to reflect selected value. * * @private */ mw.widgets.DateInputWidget.prototype.updateUI = function () { if ( this.getValue() === '' ) { this.textInput.setValue( '' ); this.calendar.setDate( null ); this.innerLabel.setLabel( this.placeholderLabel ); this.$element.addClass( 'mw-widget-dateInputWidget-empty' ); } else { const moment = this.getMoment(); if ( !this.inTextInput ) { this.textInput.setValue( moment.format( this.getInputFormat() ) ); } if ( !this.inCalendar ) { this.calendar.setDate( this.getValue() ); } this.innerLabel.setLabel( moment.format( this.getDisplayFormat() ) ); this.$element.removeClass( 'mw-widget-dateInputWidget-empty' ); } }; /** * Deactivate this input field for data entry. Closes the calendar and hides the text field. * * @private * @param {boolean} [userSelected] Whether we are deactivating because the user selected a value */ mw.widgets.DateInputWidget.prototype.deactivate = function ( userSelected ) { this.$element.removeClass( 'mw-widget-dateInputWidget-active' ); this.$handle.show(); this.textInput.toggle( false ); this.calendar.toggle( false ); this.setValidityFlag(); if ( userSelected ) { // Prevent focusing the handle from reopening the calendar this.closing = true; this.$handle.trigger( 'focus' ); this.closing = false; } this.emit( 'deactivate', !!userSelected ); }; /** * Activate this input field for data entry. Opens the calendar and shows the text field. * * @private */ mw.widgets.DateInputWidget.prototype.activate = function () { this.calendar.resetUI(); this.$element.addClass( 'mw-widget-dateInputWidget-active' ); this.$handle.hide(); this.textInput.toggle( true ); this.calendar.toggle( true ); this.textInput.$input.trigger( 'focus' ); }; /** * Get the date format to be used for handle label when the input is inactive. * * @private * @return {string} Format string */ mw.widgets.DateInputWidget.prototype.getDisplayFormat = function () { if ( this.displayFormat !== undefined ) { return this.displayFormat; } if ( this.calendar.getPrecision() === 'month' ) { return 'MMMM YYYY'; } else { // The formats Moment.js provides: // * ll: Month name, day of month, year // * lll: Month name, day of month, year, time // * llll: Month name, day of month, day of week, year, time // // The format we want: // * ????: Month name, day of month, day of week, year // // We try to construct it as 'llll - (lll - ll)' and hope for the best. // This seems to work well for many languages (maybe even all?). const localeData = moment.localeData( moment.locale() ); const llll = localeData.longDateFormat( 'llll' ); const lll = localeData.longDateFormat( 'lll' ); const ll = localeData.longDateFormat( 'll' ); let format = llll.replace( lll.replace( ll, '' ), '' ); if ( this.longDisplayFormat ) { // Replace MMM to MMMM and ddd to dddd but don't change MMMM and dddd format = format.replace( /MMMM?/, 'MMMM' ).replace( /dddd?/, 'dddd' ); } return format; } }; /** * Get the date format to be used for the text field when the input is active. * * @private * @return {string} Format string */ mw.widgets.DateInputWidget.prototype.getInputFormat = function () { if ( this.inputFormat !== undefined ) { return this.inputFormat; } return { day: 'YYYY-MM-DD', month: 'YYYY-MM' }[ this.calendar.getPrecision() ]; }; /** * Get the date format to be used internally for the value. This is not configurable in any way, * and always either 'YYYY-MM-DD' or 'YYYY-MM'. * * @private * @return {string} Format string */ mw.widgets.DateInputWidget.prototype.getInternalFormat = function () { return { day: 'YYYY-MM-DD', month: 'YYYY-MM' }[ this.calendar.getPrecision() ]; }; /** * Get the Moment object for current value. * * @return {Object} Moment object */ mw.widgets.DateInputWidget.prototype.getMoment = function () { return moment( this.getValue(), this.getInternalFormat() ); }; /** * Handle mouse click events. * * @private * @param {jQuery.Event} e Mouse click event * @return {boolean} False to cancel the default event */ mw.widgets.DateInputWidget.prototype.onClick = function ( e ) { if ( !this.isDisabled() && !this.isReadOnly() && e.which === 1 ) { this.activate(); } return false; }; /** * Handle key press events. * * @private * @param {jQuery.Event} e Key press event * @return {boolean|undefined} False to cancel the default event */ mw.widgets.DateInputWidget.prototype.onKeyPress = function ( e ) { if ( !this.isDisabled() && !this.isReadOnly() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) { this.activate(); return false; } }; /** * Handle focus events. * * @private */ mw.widgets.DateInputWidget.prototype.onFocus = function () { if ( !this.isDisabled() && !this.isReadOnly() && !this.closing ) { this.activate(); } }; /** * Handle calendar key press events. * * @private * @param {jQuery.Event} e Key press event * @return {boolean|undefined} False to cancel the default event */ mw.widgets.DateInputWidget.prototype.onCalendarKeyPress = function ( e ) { if ( !this.isDisabled() && e.which === OO.ui.Keys.ENTER ) { this.deactivate( true ); return false; } }; /** * Handle calendar click events. * * @private * @param {jQuery.Event} e Mouse click event * @return {boolean|undefined} False to cancel the default event */ mw.widgets.DateInputWidget.prototype.onCalendarClick = function ( e ) { const targetClass = this.calendar.getPrecision() === 'month' ? 'mw-widget-calendarWidget-month' : 'mw-widget-calendarWidget-day'; if ( !this.isDisabled() && e.which === 1 && // eslint-disable-next-line no-jquery/no-class-state $( e.target ).hasClass( targetClass ) ) { this.deactivate( true ); return false; } }; /** * Handle text input enter events. * * @private */ mw.widgets.DateInputWidget.prototype.onEnter = function () { this.deactivate( true ); }; /** * @private * @param {string} date Date string, to be valid, must be in 'YYYY-MM-DD' or 'YYYY-MM' format or * (unless the field is required) empty * @return {boolean} */ mw.widgets.DateInputWidget.prototype.validateDate = function ( date ) { let isValid; if ( date === '' ) { isValid = !this.required; } else { isValid = this.isValidDate( date ) && this.isInRange( date ); } return isValid; }; /** * @private * @param {string} date Date string, to be valid, must be in 'YYYY-MM-DD' or 'YYYY-MM' format * @return {boolean} */ mw.widgets.DateInputWidget.prototype.isValidDate = function ( date ) { // "Half-strict mode": for example, for the format 'YYYY-MM-DD', 2015-1-3 instead of 2015-01-03 // is okay, but 2015-01 isn't, and neither is 2015-01-foo. Use Moment's "fuzzy" mode and check // parsing flags for the details (stolen from implementation of moment#isValid). const mom = moment( date, this.getInputFormat() ), flags = mom.parsingFlags(); return mom.isValid() && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0; }; /** * Validates if the date is within the range configured with {@link #cfg-mustBeAfter} * and {@link #cfg-mustBeBefore}. * * @private * @param {string} date Date string, to be valid, must be empty (no date selected) or in * 'YYYY-MM-DD' or 'YYYY-MM' format to be valid * @return {boolean} */ mw.widgets.DateInputWidget.prototype.isInRange = function ( date ) { if ( this.mustBeAfter === undefined && this.mustBeBefore === undefined ) { return true; } const momentDate = moment( date, 'YYYY-MM-DD' ); const isAfter = ( this.mustBeAfter === undefined || momentDate.isAfter( this.mustBeAfter ) ); const isBefore = ( this.mustBeBefore === undefined || momentDate.isBefore( this.mustBeBefore ) ); return isAfter && isBefore; }; /** * Get the validity of current value. * * This method returns a promise that resolves if the value is valid and rejects if * it isn't. Uses {@link #validateDate}. * * @return {jQuery.Promise} A promise that resolves if the value is valid, rejects if not. */ mw.widgets.DateInputWidget.prototype.getValidity = function () { const isValid = this.validateDate( this.getValue() ); if ( isValid ) { return $.Deferred().resolve().promise(); } else { return $.Deferred().reject().promise(); } }; /** * Sets the 'invalid' flag appropriately. * * @param {boolean} [isValid] Optionally override validation result */ mw.widgets.DateInputWidget.prototype.setValidityFlag = function ( isValid ) { const widget = this, setFlag = function ( valid ) { if ( !valid ) { widget.$input.attr( 'aria-invalid', 'true' ); } else { widget.$input.removeAttr( 'aria-invalid' ); } widget.setFlags( { invalid: !valid } ); }; if ( isValid !== undefined ) { setFlag( isValid ); } else { this.getValidity().then( () => { setFlag( true ); }, () => { setFlag( false ); } ); } }; }() ); PK ! '��= = mw.widgets.CalendarWidget.lessnu �Iw�� /*! * MediaWiki Widgets – CalendarWidget styles. * * @copyright 2011-2023 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ /* stylelint-disable no-duplicate-selectors */ @import 'mediawiki.skin.variables.less'; @import 'mediawiki.mixins.less'; @calendarWidth: 21em; @calendarHeight: 14em; .mw-widget-calendarWidget { width: @calendarWidth; } .mw-widget-calendarWidget-header { position: relative; line-height: 2.5; // Overwrite OOUI's `.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child` .oo-ui-buttonWidget.oo-ui-iconElement { margin-left: 0; margin-right: 0; } .mw-widget-calendarWidget-labelButton { margin: 0 auto; display: block; width: @calendarWidth - 2 * 3em; .oo-ui-buttonElement-button { width: @calendarWidth - 2 * 3em; text-align: center; } } } .mw-widget-calendarWidget-upButton { position: absolute; top: 0; right: 3em; pointer-events: none; } .mw-widget-calendarWidget-prevButton { float: left; } .mw-widget-calendarWidget-nextButton { float: right; } .mw-widget-calendarWidget-body-outer-wrapper { clear: both; position: relative; overflow: hidden; // Fit 7 days, 3em each width: @calendarWidth; // Fit 6 weeks + heading line, 2em each height: @calendarHeight; } .mw-widget-calendarWidget-body-wrapper { .mw-widget-calendarWidget-body { display: inline-block; display: inline-grid; // Fit 7 days, 3em each width: @calendarWidth; // Fit 6 weeks + heading line, 2em each height: @calendarHeight; } .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):first-child { margin-top: -@calendarHeight; margin-left: -@calendarWidth; } .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):last-child { margin-top: 0; margin-left: 0; } } .mw-widget-calendarWidget-body-wrapper-fade-previous { width: @calendarWidth * 2; height: @calendarHeight; .mw-widget-calendarWidget-body:first-child { margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */ margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */ transition: margin-left 500ms; } } .mw-widget-calendarWidget-body-wrapper-fade-next { width: @calendarWidth * 2; height: @calendarHeight; .mw-widget-calendarWidget-body:first-child { margin-left: -@calendarWidth !important; /* stylelint-disable-line declaration-no-important */ margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */ transition: margin-left 500ms; } } .mw-widget-calendarWidget-body-wrapper-fade-up { width: @calendarWidth; height: @calendarHeight * 2; .mw-widget-calendarWidget-body { display: block; display: grid; } .mw-widget-calendarWidget-body:first-child { margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */ margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */ transition: margin-top 500ms; } } .mw-widget-calendarWidget-body-wrapper-fade-down { width: @calendarWidth; height: @calendarHeight * 2; .mw-widget-calendarWidget-body { display: block; display: grid; } .mw-widget-calendarWidget-body:first-child { margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */ margin-top: -@calendarHeight !important; /* stylelint-disable-line declaration-no-important */ transition: margin-top 500ms; } } // Support: Browsers that render CSS Grid. All others ignore unknown `grid-*` properties. // This avoids any calculation issues pushing items to next line. .mw-widget-calendarWidget-body-month { grid-template-columns: auto auto auto auto auto auto auto; } .mw-widget-calendarWidget-body-year { grid-template-columns: auto auto; } .mw-widget-calendarWidget-body-duodecade { grid-template-columns: auto auto auto auto auto; } .mw-widget-calendarWidget-day, .mw-widget-calendarWidget-day-heading, .mw-widget-calendarWidget-month, .mw-widget-calendarWidget-year { display: inline-block; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; } .mw-widget-calendarWidget-day, .mw-widget-calendarWidget-day-heading { // 7x7 grid width: (@calendarWidth / 7); line-height: (@calendarHeight / 7); // Don't overlap the hacked-up fake box-shadow border we get when focussed &:nth-child( 7n ) { width: (@calendarWidth / 7 - 0.2em); margin-right: 0.2em; } &:nth-child( 7n+1 ) { width: (@calendarWidth / 7 - 0.2em); margin-left: 0.2em; } &:nth-child( 42 ) ~ & { line-height: (@calendarHeight / 7 - 0.2em); margin-bottom: 0.2em; } } .mw-widget-calendarWidget-month { // 2x6 grid width: (@calendarWidth / 2); line-height: (@calendarHeight / 6); // Don't overlap the hacked-up fake box-shadow border we get when focussed &:nth-child( 2n ) { width: (@calendarWidth / 2 - 0.2em); margin-right: 0.2em; } &:nth-child( 2n+1 ) { width: (@calendarWidth / 2 - 0.2em); margin-left: 0.2em; } &:nth-child( 10 ) ~ & { line-height: (@calendarHeight / 6 - 0.2em); margin-bottom: 0.2em; } } .mw-widget-calendarWidget-year { // 5x4 grid width: (@calendarWidth / 5); line-height: (@calendarHeight / 4); // Don't overlap the hacked-up fake box-shadow border we get when focussed &:nth-child( 5n ) { width: (@calendarWidth / 5 - 0.2em); margin-right: 0.2em; } &:nth-child( 5n+1 ) { width: (@calendarWidth / 5 - 0.2em); margin-left: 0.2em; } &:nth-child( 15 ) ~ & { line-height: (@calendarHeight / 4 - 0.2em); margin-bottom: 0.2em; } } .mw-widget-calendarWidget-item { cursor: pointer; } /* Theme-specific */ .mw-widget-calendarWidget { box-sizing: border-box; border: @border-base; transition: border-color 100ms, box-shadow 100ms; &:focus { border-color: @border-color-progressive--focus; box-shadow: @box-shadow-inset-small @box-shadow-color-progressive--focus; outline: @outline-base--focus; } &-day { color: @color-base; border-radius: @border-radius-base; } &-day-heading { color: @color-subtle; font-weight: bold; } &-day-additional { color: #a2a9b1; &:hover { color: #202122; } } &-day-today { box-shadow: @box-shadow-inset-small @box-shadow-color-progressive-selected; } &-item { transition: background-color 250ms, color 250ms; &:hover { background-color: #36c; color: #fff; } &-selected { background-color: #2a4b8d; color: #fff; } } } PK ! B��� � ) mw.widgets.ComplexNamespaceInputWidget.jsnu �Iw�� /*! * MediaWiki Widgets - ComplexNamespaceInputWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Displays a dropdown box with the choice of available namespaces, * plus two checkboxes to include associated namespace or to invert selection. * * @class * @extends OO.ui.Widget * * @constructor * @description Create an instance of `mw.widgets.ComplexNamespaceInputWidget`. * @param {Object} [config] Configuration options * @param {Object} config.namespace Configuration for the NamespaceInputWidget dropdown with list * of namespaces * @param {string} config.namespace.includeAllValue If specified, add a "all namespaces" * option to the dropdown, and use this as the input value for it * @param {Object} config.invert Configuration for the "invert selection" CheckboxInputWidget. If * null, the checkbox will not be generated. * @param {Object} config.associated Configuration for the "include associated namespace" * CheckboxInputWidget. If null, the checkbox will not be generated. * @param {Object} config.invertLabel Configuration for the FieldLayout with label wrapping the * "invert selection" checkbox * @param {string} config.invertLabel.label Label text for the label * @param {Object} config.associatedLabel Configuration for the FieldLayout with label wrapping * the "include associated namespace" checkbox * @param {string} config.associatedLabel.label Label text for the label */ mw.widgets.ComplexNamespaceInputWidget = function MwWidgetsComplexNamespaceInputWidget( config ) { // Configuration initialization config = Object.assign( { // Config options for nested widgets namespace: {}, invert: {}, invertLabel: {}, associated: {}, associatedLabel: {} }, config ); // Parent constructor mw.widgets.ComplexNamespaceInputWidget.super.call( this, config ); // Properties this.config = config; this.namespace = new mw.widgets.NamespaceInputWidget( config.namespace ); if ( config.associated !== null ) { this.associated = new OO.ui.CheckboxInputWidget( Object.assign( { value: '1' }, config.associated ) ); // TODO Should use a LabelWidget? But they don't work like HTML <label>s yet this.associatedLabel = new OO.ui.FieldLayout( this.associated, Object.assign( { align: 'inline' }, config.associatedLabel ) ); } if ( config.invert !== null ) { this.invert = new OO.ui.CheckboxInputWidget( Object.assign( { value: '1' }, config.invert ) ); // TODO Should use a LabelWidget? But they don't work like HTML <label>s yet this.invertLabel = new OO.ui.FieldLayout( this.invert, Object.assign( { align: 'inline' }, config.invertLabel ) ); } // Events this.namespace.connect( this, { change: 'updateCheckboxesState' } ); // Initialization this.$element .addClass( 'mw-widget-complexNamespaceInputWidget' ) .append( this.namespace.$element, this.invert ? this.invertLabel.$element : '', this.associated ? this.associatedLabel.$element : '' ); this.updateCheckboxesState(); }; /* Setup */ OO.inheritClass( mw.widgets.ComplexNamespaceInputWidget, OO.ui.Widget ); /* Methods */ /** * Update the disabled state of checkboxes when the value of namespace dropdown changes. * * @private */ mw.widgets.ComplexNamespaceInputWidget.prototype.updateCheckboxesState = function () { const disabled = this.namespace.getValue() === this.namespace.allValue; if ( this.invert ) { this.invert.setDisabled( disabled ); } if ( this.associated ) { this.associated.setDisabled( disabled ); } }; /** * @inheritdoc */ mw.widgets.ComplexNamespaceInputWidget.prototype.setDisabled = function ( disabled ) { mw.widgets.ComplexNamespaceInputWidget.super.prototype.setDisabled.call( this, disabled ); if ( this.namespace ) { this.namespace.setDisabled( disabled ); } if ( this.invert ) { this.invert.setDisabled( disabled ); } if ( this.associated ) { this.associated.setDisabled( disabled ); } return this; }; }() ); PK ! 3�\� � mw.widgets.SizeFilterWidget.jsnu �Iw�� /*! * MediaWiki Widgets - SizeFilterWidget class. * * @copyright 2011-2018 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Size filter widget. * * @example * mw.loader.using( 'mediawiki.widgets.SizeFilterWidget', function () { * let sf = new mw.widgets.SizeFilterWidget(); * $( document.body ).append( sf.$element ); * } ); * * @class mw.widgets.SizeFilterWidget * @extends OO.ui.Widget * @uses OO.ui.RadioSelectInputWidget * @uses OO.ui.TextInputWidget * * @constructor * @description Use a RadioSelectInputWidget and a TextInputWidget to set minimum or maximum byte size. * @param {Object} [config] Configuration options * @param {Object} [config.radioselectinput] Config for the radio select input * @param {Object} [config.textinput] Config for the text input * @param {boolean} [config.selectMin=true] Whether to select 'min', false would select 'max' */ mw.widgets.SizeFilterWidget = function MwWidgetsSizeFilterWidget( config ) { // Config initialization config = Object.assign( { selectMin: true }, config ); config.textinput = Object.assign( { type: 'number' }, config.textinput ); config.radioselectinput = Object.assign( { options: [ { data: 'min', label: mw.msg( 'minimum-size' ) }, { data: 'max', label: mw.msg( 'maximum-size' ) } ] }, config.radioselectinput ); // Properties this.radioselectinput = new OO.ui.RadioSelectInputWidget( config.radioselectinput ); this.textinput = new OO.ui.TextInputWidget( config.textinput ); this.label = new OO.ui.LabelWidget( { label: mw.msg( 'pagesize' ) } ); // Parent constructor mw.widgets.SizeFilterWidget.super.call( this, config ); // Initialization this.radioselectinput.setValue( config.selectMin ? 'min' : 'max' ); this.$element .addClass( 'mw-widget-sizeFilterWidget' ) .append( this.radioselectinput.$element, this.textinput.$element, this.label.$element ); }; /* Setup */ OO.inheritClass( mw.widgets.SizeFilterWidget, OO.ui.Widget ); /* Static Methods */ /** * @inheritdoc */ mw.widgets.SizeFilterWidget.static.reusePreInfuseDOM = function ( node, config ) { config = mw.widgets.SizeFilterWidget.super.static.reusePreInfuseDOM( node, config ); config.radioselectinput = OO.ui.RadioSelectInputWidget.static.reusePreInfuseDOM( $( node ).find( '.oo-ui-radioSelectInputWidget' ), config.radioselectinput ); config.textinput = OO.ui.TextInputWidget.static.reusePreInfuseDOM( $( node ).find( '.oo-ui-textInputWidget' ), config.textinput ); return config; }; /** * @inheritdoc */ mw.widgets.SizeFilterWidget.static.gatherPreInfuseState = function ( node, config ) { const state = mw.widgets.SizeFilterWidget.super.static.gatherPreInfuseState( node, config ); state.radioselectinput = OO.ui.RadioSelectInputWidget.static.gatherPreInfuseState( $( node ).find( '.oo-ui-radioSelectInputWidget' ), config.radioselectinput ); state.textinput = OO.ui.TextInputWidget.static.gatherPreInfuseState( $( node ).find( '.oo-ui-textInputWidget' ), config.textinput ); return state; }; /* Methods */ /** * @inheritdoc */ mw.widgets.SizeFilterWidget.prototype.restorePreInfuseState = function ( state ) { mw.widgets.SizeFilterWidget.super.prototype.restorePreInfuseState.call( this, state ); this.radioselectinput.restorePreInfuseState( state.radioselectinput ); this.textinput.restorePreInfuseState( state.textinput ); }; }() ); PK ! ��� � mw.widgets.TitleSearchWidget.jsnu �Iw�� /*! * MediaWiki Widgets - TitleSearchWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Title search widget. * * @class * @extends OO.ui.SearchWidget * @mixes OO.ui.mixin.RequestManager * @mixes mw.widgets.TitleWidget * * @constructor * @description Create an mw.widgets.TitleSearchWidget object. * @param {Object} [config] Configuration options */ mw.widgets.TitleSearchWidget = function MwWidgetsTitleSearchWidget( config ) { config = config || {}; // Parent constructor mw.widgets.TitleSearchWidget.super.call( this, config ); // Mixin constructors mw.widgets.TitleWidget.call( this, config ); OO.ui.mixin.RequestManager.call( this, config ); this.query.setValidation( this.isQueryValid.bind( this ) ); // Events this.results.connect( this, { choose: 'onTitleSearchResultsChoose' } ); // Initialization this.$element.addClass( 'mw-widget-titleSearchWidget' ); this.results.$element.addClass( 'mw-widget-titleWidget-menu' ); if ( this.showImages ) { this.results.$element.addClass( 'mw-widget-titleWidget-menu-withImages' ); } if ( this.showDescriptions ) { this.results.$element.addClass( 'mw-widget-titleWidget-menu-withDescriptions' ); } if ( this.maxLength !== undefined ) { this.getQuery().$input.attr( 'maxlength', this.maxLength ); } }; /* Setup */ OO.inheritClass( mw.widgets.TitleSearchWidget, OO.ui.SearchWidget ); OO.mixinClass( mw.widgets.TitleSearchWidget, OO.ui.mixin.RequestManager ); OO.mixinClass( mw.widgets.TitleSearchWidget, mw.widgets.TitleWidget ); /* Methods */ /** * @inheritdoc */ mw.widgets.TitleSearchWidget.prototype.getQueryValue = function () { return this.getQuery().getValue(); }; /** * Handle choose events from the result widget. * * @param {OO.ui.OptionWidget} item Chosen item */ mw.widgets.TitleSearchWidget.prototype.onTitleSearchResultsChoose = function ( item ) { this.getQuery().setValue( item.getData() ); }; /** * @inheritdoc */ mw.widgets.TitleSearchWidget.prototype.onQueryChange = function () { this.getRequestData().done( ( data ) => { if ( this.query.isReadOnly() ) { // The request object is always abortable, so just // prevent the results from displaying return; } // Parent method mw.widgets.TitleSearchWidget.super.prototype.onQueryChange.call( this ); this.results.addItems( this.getOptionsFromData( data ) ); } ); }; /** * @inheritdoc */ mw.widgets.TitleSearchWidget.prototype.getRequestQuery = function () { return this.getQueryValue(); }; /** * @inheritdoc */ mw.widgets.TitleSearchWidget.prototype.getRequest = function () { return this.getSuggestionsPromise(); }; /** * @inheritdoc */ mw.widgets.TitleSearchWidget.prototype.getRequestCacheDataFromResponse = function ( response ) { return response.query || {}; }; /** * Check if the widget is read-only. * * @return {boolean} */ mw.widgets.TitleSearchWidget.prototype.isReadOnly = function () { return this.query.isReadOnly(); }; /** * Set the read-only state of the widget. * * @param {boolean} readOnly Make input read-only * @chainable * @return {mw.widgets.TitleSearchWidget} The widget, for chaining */ mw.widgets.TitleSearchWidget.prototype.setReadOnly = function ( readOnly ) { this.query.setReadOnly( readOnly ); if ( readOnly ) { // Hide results this.results.clearItems(); } return this; }; }() ); PK ! �fb�- - % mw.widgets.ComplexTitleInputWidget.jsnu �Iw�� /*! * MediaWiki Widgets - ComplexTitleInputWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc Like TitleInputWidget, but the namespace has to be input through a separate dropdown field. * * @class * @extends OO.ui.Widget * * @constructor * @description Create an instance of `mw.widgets.ComplexTitleInputWidget`. * @param {Object} [config] Configuration options * @param {Object} config.namespace Configuration for the NamespaceInputWidget dropdown with list of * namespaces * @param {Object} config.title Configuration for the TitleInputWidget text field */ mw.widgets.ComplexTitleInputWidget = function MwWidgetsComplexTitleInputWidget( config ) { // Parent constructor mw.widgets.ComplexTitleInputWidget.super.call( this, config ); // Properties this.namespace = new mw.widgets.NamespaceInputWidget( config.namespace ); this.title = new mw.widgets.TitleInputWidget( Object.assign( {}, config.title, { relative: true, namespace: config.namespace.value || null } ) ); // Events this.namespace.connect( this, { change: 'updateTitleNamespace' } ); // Initialization this.$element .addClass( 'mw-widget-complexTitleInputWidget' ) .append( this.namespace.$element, this.title.$element ); this.updateTitleNamespace(); }; /* Setup */ OO.inheritClass( mw.widgets.ComplexTitleInputWidget, OO.ui.Widget ); /* Static Methods */ /** * @inheritdoc */ mw.widgets.ComplexTitleInputWidget.static.reusePreInfuseDOM = function ( node, config ) { config = mw.widgets.ComplexTitleInputWidget.super.static.reusePreInfuseDOM( node, config ); config.namespace = mw.widgets.NamespaceInputWidget.static.reusePreInfuseDOM( $( node ).find( '.mw-widget-namespaceInputWidget' ), config.namespace ); config.title = mw.widgets.TitleInputWidget.static.reusePreInfuseDOM( $( node ).find( '.mw-widget-titleInputWidget' ), config.title ); return config; }; /** * @inheritdoc */ mw.widgets.ComplexTitleInputWidget.static.gatherPreInfuseState = function ( node, config ) { const state = mw.widgets.ComplexTitleInputWidget.super.static.gatherPreInfuseState( node, config ); state.namespace = mw.widgets.NamespaceInputWidget.static.gatherPreInfuseState( $( node ).find( '.mw-widget-namespaceInputWidget' ), config.namespace ); state.title = mw.widgets.TitleInputWidget.static.gatherPreInfuseState( $( node ).find( '.mw-widget-titleInputWidget' ), config.title ); return state; }; /* Methods */ /** * Update the namespace to use for search suggestions of the title when the value of namespace * dropdown changes. */ mw.widgets.ComplexTitleInputWidget.prototype.updateTitleNamespace = function () { this.title.setNamespace( Number( this.namespace.getValue() ) ); }; /** * @inheritdoc */ mw.widgets.ComplexTitleInputWidget.prototype.restorePreInfuseState = function ( state ) { mw.widgets.ComplexTitleInputWidget.super.prototype.restorePreInfuseState.call( this, state ); this.namespace.restorePreInfuseState( state.namespace ); this.title.restorePreInfuseState( state.title ); }; /** * @inheritdoc */ mw.widgets.ComplexTitleInputWidget.prototype.setDisabled = function ( disabled ) { mw.widgets.ComplexTitleInputWidget.super.prototype.setDisabled.call( this, disabled ); if ( this.namespace ) { this.namespace.setDisabled( disabled ); } if ( this.title ) { this.title.setDisabled( disabled ); } return this; }; }() ); PK ! ��i7� � 0 mw.widgets.ComplexNamespaceInputWidget.base.lessnu �Iw�� /*! * MediaWiki Widgets - base ComplexNamespaceInputWidget styles. * * @copyright 2011-2024 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ .mw-widget-complexNamespaceInputWidget { .mw-widget-namespaceInputWidget, .oo-ui-fieldLayout { display: inline-block; margin-right: 1em; } /* TODO FieldLayout is not supposed to be used the way we use it here */ .oo-ui-fieldLayout { vertical-align: middle; margin-bottom: 0; &.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label { padding-left: 0.5em; } } .mw-widget-namespaceInputWidget { max-width: 20em; } } PK ! l� { { mw.widgets.UserInputWidget.jsnu �Iw�� /*! * MediaWiki Widgets - UserInputWidget class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ ( function () { /** * @classdesc User input widget. * * @class * @extends OO.ui.TextInputWidget * @mixes OO.ui.mixin.LookupElement * * @constructor * @description Create a mw.widgets.UserInputWidget object. * @param {Object} [config] Configuration options * @param {number} [config.limit=10] Number of results to show * @param {boolean} [config.excludenamed] Whether to exclude named users or not * @param {boolean} [config.excludetemp] Whether to exclude temporary users or not * @param {mw.Api} [config.api] API object to use, creates a default mw.Api instance if not specified */ mw.widgets.UserInputWidget = function MwWidgetsUserInputWidget( config ) { // Config initialization config = config || {}; // Parent constructor mw.widgets.UserInputWidget.super.call( this, Object.assign( {}, config, { autocomplete: false } ) ); // Mixin constructors OO.ui.mixin.LookupElement.call( this, config ); // Properties this.limit = config.limit || 10; this.excludeNamed = config.excludenamed || false; this.excludeTemp = config.excludetemp || false; this.api = config.api || new mw.Api(); // Initialization this.$element.addClass( 'mw-widget-userInputWidget' ); this.lookupMenu.$element.addClass( 'mw-widget-userInputWidget-menu' ); }; /* Setup */ OO.inheritClass( mw.widgets.UserInputWidget, OO.ui.TextInputWidget ); OO.mixinClass( mw.widgets.UserInputWidget, OO.ui.mixin.LookupElement ); /* Methods */ /** * Handle menu item 'choose' event, updating the text input value to the value of the clicked item. * * @param {OO.ui.MenuOptionWidget} item Selected item */ mw.widgets.UserInputWidget.prototype.onLookupMenuChoose = function ( item ) { this.closeLookupMenu(); this.setLookupsDisabled( true ); this.setValue( item.getData() ); this.setLookupsDisabled( false ); }; /** * @inheritdoc */ mw.widgets.UserInputWidget.prototype.focus = function () { // Prevent programmatic focus from opening the menu this.setLookupsDisabled( true ); // Parent method const retval = mw.widgets.UserInputWidget.super.prototype.focus.apply( this, arguments ); this.setLookupsDisabled( false ); return retval; }; /** * @inheritdoc */ mw.widgets.UserInputWidget.prototype.getLookupRequest = function () { return this.api.get( { action: 'query', list: 'allusers', auprefix: this.value, aulimit: this.limit, auexcludenamed: this.excludeNamed, auexcludetemp: this.excludeTemp } ); }; /** * Get lookup cache item from server response data. * * @method * @param {any} response Response from server * @return {Object} */ mw.widgets.UserInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) { return response.query.allusers || {}; }; /** * Get list of menu items from a server response. * * @param {Object} data Query result * @return {OO.ui.MenuOptionWidget[]} Menu items */ mw.widgets.UserInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) { const items = []; for ( let i = 0, len = data.length; i < len; i++ ) { const user = data[ i ] || {}; items.push( new OO.ui.MenuOptionWidget( { label: user.name, data: user.name } ) ); } return items; }; }() ); PK ! ^���� � mw.widgets.DateInputWidget.lessnu �Iw�� /*! * MediaWiki Widgets – JS DateInputWidget styles. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ @import 'mediawiki.skin.variables.less'; @import 'mediawiki.mixins.less'; .oo-ui-unselectable() { -webkit-touch-callout: none; .user-select( none ); } @size-indicator: unit( 12 / 16 / 0.8, em ); .mw-widget-dateInputWidget { &-handle { .oo-ui-unselectable(); > .oo-ui-indicatorElement-indicator { display: none; } } &.oo-ui-indicatorElement .mw-widget-dateInputWidget-handle > .oo-ui-indicatorElement-indicator { display: block; position: absolute; top: 0; right: 0; width: @size-indicator; height: 100%; margin: 0 0.775em; } > .oo-ui-textInputWidget { z-index: 2; } &-calendar { background-color: @background-color-base; position: absolute; margin-top: -2px; border-radius: @border-radius-base; box-shadow: @box-shadow-drop-medium; z-index: 1; &:focus { box-shadow: @box-shadow-inset-small @box-shadow-color-progressive--focus, @box-shadow-drop-medium; z-index: 3; } } &-empty { .mw-widget-dateInputWidget-handle { color: @color-subtle; outline: 0; } } &.oo-ui-flaggedElement-invalid { .mw-widget-dateInputWidget-handle { border-color: @border-color-error; box-shadow: none; } } &.oo-ui-widget-enabled { .mw-widget-dateInputWidget-handle:hover { border-color: @border-color-interactive; } .oo-ui-inputWidget-input[ readonly ]:not( .oo-ui-pendingElement-pending ) ~ .mw-widget-dateInputWidget-handle { background-color: @background-color-interactive-subtle; } } &.oo-ui-widget-disabled { .mw-widget-dateInputWidget-handle { background-color: @background-color-disabled-subtle; color: @color-disabled; border-color: @border-color-disabled; text-shadow: 0 1px 1px #fff; cursor: @cursor-base--disabled; > .oo-ui-indicatorElement-indicator { opacity: @opacity-icon-base--disabled; } } } } PK ! �D� � index.jsnu �Iw�� require( './mw.widgets.NamespaceInputWidget.js' ); require( './mw.widgets.ComplexNamespaceInputWidget.js' ); require( './mw.widgets.CopyTextLayout.js' ); require( './mw.widgets.TitleWidget.js' ); require( './mw.widgets.TitleInputWidget.js' ); require( './mw.widgets.TitleSearchWidget.js' ); require( './mw.widgets.ComplexTitleInputWidget.js' ); require( './mw.widgets.TitleOptionWidget.js' ); PK ! ��� � mw.widgets.CopyTextLayout.jsnu �Iw�� /*! * MediaWiki Widgets - CopyTextLayout class. * * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ /** * @classdesc Extends CopyTextLayout with MediaWiki notifications. * * @class * @extends OO.ui.CopyTextLayout * * @constructor * @description Create an instance of `mw.widgets.CopyTextLayout`. * @param {Object} [config] Configuration options * @param {string} [config.successMessage] Success message, * defaults to the {@link mw.Message} 'mw-widgets-copytextlayout-copy-success'. * @param {string} [config.failMessage] Failure message, * defaults to the {@link mw.Message} 'mw-widgets-copytextlayout-copy-fail'. */ mw.widgets.CopyTextLayout = function MwWidgetsCopyTextLayout( config ) { // Parent constructor mw.widgets.CopyTextLayout.super.apply( this, arguments ); this.successMessage = config.successMessage || mw.msg( 'mw-widgets-copytextlayout-copy-success' ); this.failMessage = config.failMessage || mw.msg( 'mw-widgets-copytextlayout-copy-fail' ); this.connect( this, { copy: 'onMwCopy' } ); }; /* Inheritence */ OO.inheritClass( mw.widgets.CopyTextLayout, OO.ui.CopyTextLayout ); /* Methods */ /** * Handle copy events. * * @param {boolean} copied */ mw.widgets.CopyTextLayout.prototype.onMwCopy = function ( copied ) { if ( copied ) { mw.notify( this.successMessage ); } else { mw.notify( this.failMessage, { type: 'error' } ); } }; PK ! �D%=# =# "