{
- "extends": "wikimedia",
- "env": {
- "browser": true
- },
+ "extends": [
+ "wikimedia/client",
+ "wikimedia/jquery"
+ ],
"globals": {
"require": false,
"module": false,
"mw": false,
- "$": false,
"OO": false
},
"rules": {
- "no-restricted-properties": [
- 2,
- {
- "object": "$",
- "property": "map",
- "message": "Please use Array.prototype.map instead"
- },
- {
- "object": "$",
- "property": "inArray",
- "message": "Please use Array.prototype.indexOf instead"
- },
- {
- "object": "$",
- "property": "each",
- "message": "Please consider different approaches to $.each, especially when using Array's. You can override this warning if necessary with eslint-disable-next-line."
- },
- {
- "object": "$",
- "property": "isArray",
- "message": "Please use Array.isArray instead"
- },
- {
- "object": "$",
- "property": "isFunction",
- "message": "Please use typeof (e.g. typeof e === 'function') instead"
- },
- {
- "object": "$",
- "property": "grep",
- "message": "Please use Array.prototype.filter instead"
- },
- {
- "object": "$",
- "property": "trim",
- "message": "Please use String.prototype.trim instead"
- },
- {
- "object": "$",
- "property": "proxy",
- "message": "Please use Function.prototype.bind instead"
- },
-
- {
- "property": "codePointAt",
- "message": "Unsupported method String.prototype.codePointAt requires ES6."
- },
- {
- "property": "endsWith",
- "message": "Unsupported method String.prototype.endsWith requires ES6."
- },
- {
- "property": "normalize",
- "message": "Unsupported method String.prototype.normalize requires ES6."
- },
- {
- "property": "padEnd",
- "message": "Unsupported method String.prototype.padEnd requires ES2017."
- },
- {
- "property": "padStart",
- "message": "Unsupported method String.prototype.padStart requires ES2017."
- },
- {
- "property": "repeat",
- "message": "Unsupported method String.prototype.repeat requires ES6."
- },
- {
- "property": "startsWith",
- "message": "Unsupported method String.prototype.startsWith requires ES6."
- },
- {
- "property": "trimEnd",
- "message": "Unsupported method String.prototype.trimEnd is still experimental."
- },
- {
- "property": "trimLeft",
- "message": "Unsupported method String.prototype.trimLeft is still experimental."
- },
- {
- "property": "trimRight",
- "message": "Unsupported method String.prototype.trimRight is still experimental."
- },
- {
- "property": "trimStart",
- "message": "Unsupported method String.prototype.trimStart is still experimental."
- },
- {
- "property": "copyWithin",
- "message": "Unsupported method Array.prototype.copyWithin requires ES6."
- },
- {
- "property": "entries",
- "message": "Unsupported method Array.prototype.entries requires ES6."
- },
- {
- "property": "fill",
- "message": "Unsupported method Array.prototype.fill requires ES6."
- },
- {
- "property": "findIndex",
- "message": "Unsupported method Array.prototype.findIndex requires ES6."
- },
- {
- "property": "flat",
- "message": "Unsupported method Array.prototype.flat is still experimental."
- },
- {
- "property": "flatMap",
- "message": "Unsupported method Array.prototype.flatMap is still experimental."
- },
- {
- "object": "String",
- "property": "fromCodePoint",
- "message": "Unsupported method String.fromCodePoint requires ES6."
- },
- {
- "object": "String",
- "property": "raw",
- "message": "Unsupported method String.raw requires ES6."
- },
- {
- "object": "Array",
- "property": "from",
- "message": "Unsupported method Array.from requires ES6."
- },
- {
- "object": "Array",
- "property": "of",
- "message": "Unsupported method Array.of requires ES6."
- },
- {
- "object": "Object",
- "property": "assign",
- "message": "Unsupported method Object.assign requires ES6."
- },
- {
- "object": "Object",
- "property": "entries",
- "message": "Unsupported method Object.entries requires ES2017."
- },
- {
- "object": "Object",
- "property": "getOwnPropertyDescriptors",
- "message": "Unsupported method Object.getOwnPropertyDescriptors requires ES2017."
- },
- {
- "object": "Object",
- "property": "getOwnPropertySymbols",
- "message": "Unsupported method Object.getOwnPropertySymbols requires ES6."
- },
- {
- "object": "Object",
- "property": "is",
- "message": "Unsupported method Object.is requires ES6."
- },
- {
- "object": "Object",
- "property": "values",
- "message": "Unsupported method Object.values requires ES2017."
- }
- ],
- "no-restricted-syntax": [
- 2,
- {
- // Match expressions like .includes( … ) (false positives when used as a property name)
- "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='includes']",
- "message": "Unsupported methods String.prototype.includes and Array.prototype.includes require ES6 and ES2016 respectively."
- },
- {
- // Match expressions like .find( function ( … ) { … } ) (avoid $( … ).find( … ))
- "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='find'][arguments.length=1][arguments.0.type='FunctionExpression']",
- "message": "Unsupported method Array.prototype.find requires ES6."
- },
- {
- // Match expressions like .keys( … ), except Object.keys( … ) (which is valid)
- "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='keys'][callee.object.name!='Object']",
- "message": "Unsupported method Array.prototype.keys requires ES6."
- },
- {
- // Match expressions like .values( … ), except Object.values( … ) (disallowed separately)
- "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='values'][callee.object.name!='Object']",
- "message": "Unsupported method Array.prototype.values requires ES6."
- }
- ],
"dot-notation": 0,
"max-len": 0
}
},
"devDependencies": {
"deepmerge": "1.3.2",
- "eslint": "5.0.1",
- "eslint-config-wikimedia": "0.8.1",
- "eslint-plugin-qunit": "3.3.1",
+ "eslint-config-wikimedia": "0.9.0",
"grunt": "1.0.3",
"grunt-banana-checker": "0.6.0",
"grunt-contrib-copy": "1.0.0",
// Loop through all the dom cells of the thead
$tableRows.each( function ( rowIndex, row ) {
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( row.cells, function ( columnIndex, cell ) {
var matrixRowIndex,
matrixColumnIndex;
function convertSortList( sortObjects ) {
var sortList = [];
sortObjects.forEach( function ( sortObject ) {
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( sortObject, function ( columnIndex, order ) {
var orderIndex = ( order === 'desc' ) ? 1 : 0;
sortList.push( [ parseInt( columnIndex, 10 ), orderIndex ] );
*
* Set options:
*
- * $( '#textbox' ).suggestions( { option1: value1, option2: value2 } );
- * $( '#textbox' ).suggestions( option, value );
+ * $( '#textbox' ).suggestions( { option1: value1, option2: value2 } );
+ * $( '#textbox' ).suggestions( option, value );
*
* Initialize:
*
- * $( '#textbox' ).suggestions();
+ * $( '#textbox' ).suggestions();
*
* Uses jQuery.suggestions singleton internally.
*
*/
getQueryString: function () {
var args = [];
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.query, function ( key, val ) {
var k = Uri.encode( key ),
vals = Array.isArray( val ) ? val : [ val ];
}
newList = [];
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( response.parse.indicators, function ( name, indicator ) {
newList.push(
$( '<div>' )
* JavaScript for History action
*/
$( function () {
- var $historyCompareForm = $( '#mw-history-compare' ),
+ var $historyCompareForm = $( '#mw-history-compare' ),
$historySubmitter,
$lis = $( '#pagehistory > li' );
// the page look broken for a second in slow browsers and might show the form broken
// again when coming back from a "next" page.
$historyCompareForm.submit( function ( e ) {
- var $copyForm, $copyRadios, $copyAction;
+ var $copyForm, $copyRadios, $copyAction;
if ( $historySubmitter ) {
$copyForm = $historyCompareForm.clone();
// Pre-populate with fake ajax promises to save http requests for tokens
// we already have on the page via the user.tokens module (T36733).
promises[ defaultOptions.ajax.url ] = {};
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( mw.user.tokens.get(), function ( key, value ) {
// This requires #getToken to use the same key as user.tokens.
// Format: token-type + "Token" (eg. csrfToken, patrolToken, watchToken).
file.name = 'file';
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( data, function ( key, val ) {
$form.append( getHiddenInput( key, val ) );
} );
// opposite way than normal event handlers (returning true will prevent the default
// action, returning false will let the browser handle the error normally, by e.g.
// logging to the console), so our fallback old handler needs to return false.
- var oldHandler = window.onerror || function () { return false; };
+ var oldHandler = window.onerror || function () {
+ return false;
+ };
/**
* Dumb window.onerror handler which forwards the errors via mw.track.
var i,
units = [ '', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB' ];
- if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
+ if ( !$.isNumeric( bytes ) || bytes === 0 ) {
+ return bytes;
+ }
- for ( i = 0; bytes >= 1024; bytes /= 1024 ) { i++; }
+ for ( i = 0; bytes >= 1024; bytes /= 1024 ) {
+ i++;
+ }
// Maintain one decimal for kB and above, but don't
// add ".0" for bytes.
return bytes.toFixed( i > 0 ? 1 : 0 ) + units[ i ];
style.textContent = css;
document.body.appendChild( style );
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( style.sheet.cssRules, function ( index, rule ) {
selectors.total++;
// document.querySelector() on prefixed pseudo-elements can throw exceptions
mw.jqueryMsg.HtmlEmitter = function ( language, magic ) {
var jmsg = this;
this.language = language;
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( magic, function ( key, val ) {
jmsg[ key.toLowerCase() ] = function () {
return val;
// typeof returns object for arrays
case 'object':
// node is an array of nodes
+ // eslint-disable-next-line jquery/no-map-util
subnodes = $.map( node.slice( 1 ), function ( n ) {
return jmsg.emit( n, replacements );
} );
*/
concat: function ( nodes ) {
var $span = $( '<span>' ).addClass( 'mediaWiki_htmlEmitter' );
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( nodes, function ( i, node ) {
// Let jQuery append nodes, arrays of nodes and jQuery objects
// other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
}
// Remove explicit plural forms from the forms. They were set undefined in the above loop.
+ // eslint-disable-next-line jquery/no-map-util
forms = $.map( forms, function ( form ) {
return form;
} );
* @return {boolean}
*/
matchAttribute: function ( objects, attrName ) {
+ // eslint-disable-next-line jquery/no-map-util
return $.map( objects, function ( object ) {
return object[ attrName ];
} ).filter( function ( item, index, a ) {
* @param {boolean} val Enable?
*/
toggleUnchainedInputs: function ( val ) {
- var setDisabled = function () { this.disabled = !val; };
+ var setDisabled = function () {
+ this.disabled = !val;
+ };
this.getLevelSelectors().slice( 1 ).each( setDisabled );
this.getExpiryInputs().slice( 1 ).each( setDisabled );
this.getExpirySelectors().slice( 1 ).each( setDisabled );
* @deprecated since 1.17 Use jQuery instead
*/
mw.log.deprecate( window, 'addOnloadHook', function ( fn ) {
- $( function () { fn(); } );
+ $( function () {
+ fn();
+ } );
}, 'Use jQuery instead.' );
/**
* Draws the carousel and the interface around it.
*/
mw.GallerySlideshow.prototype.drawCarousel = function () {
- var next, prev, toggle, interfaceElements, carouselStack;
+ var next, prev, toggle, interfaceElements, carouselStack;
this.$carousel = $( '<li>' ).addClass( 'gallerycarousel' );
*
* @param {Object} $img
* @return {jQuery.Promise} Resolves with the images URL and original
- * element once the image has loaded.
+ * element once the image has loaded.
*/
mw.GallerySlideshow.prototype.loadImage = function ( $img ) {
var img, d = $.Deferred();
// Check for filters that should be initially selected by their default value
if ( this.isSticky() ) {
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.defaultFilters, function ( filterName, filterValue ) {
model.getItemByName( filterName ).toggleSelected( filterValue );
} );
* Conflict object is set up by filter name keys and conflict
* definition. For example:
* [
- * {
- * filterName: {
- * filter: filterName,
- * group: group1
- * }
- * },
- * {
- * filterName2: {
- * filter: filterName2,
- * group: group2
- * }
- * }
+ * {
+ * filterName: {
+ * filter: filterName,
+ * group: group1
+ * }
+ * },
+ * {
+ * filterName2: {
+ * filter: filterName2,
+ * group: group2
+ * }
+ * }
* ]
* @return {Object} Conflict definition
*/
selected = [];
// Find if any are selected
+ // eslint-disable-next-line jquery/no-each-util
$.each( filters, function ( name, value ) {
if ( value ) {
selected.push( name );
// all false
// Go over the items and define the correct values
+ // eslint-disable-next-line jquery/no-each-util
$.each( filterRepresentation, function ( name, value ) {
// We must store all parameter values as strings '0' or '1'
if ( model.getType() === 'send_unselected_if_any' ) {
} else if ( this.getType() === 'string_options' ) {
values = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( filterRepresentation, function ( name, value ) {
// Collect values
if ( value ) {
}
} );
+ // eslint-disable-next-line jquery/no-each-util
$.each( expandedParams, function ( paramName, paramValue ) {
var filterItem = paramToFilterMap[ paramName ];
key = key || 'contextDescription';
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( conflicts, function ( filterName, conflict ) {
if ( !conflict.item.isSelected() ) {
return;
*
* Conflict object is set up by filter name keys and conflict
* definition. For example:
- * {
- * filterName: {
- * filter: filterName,
- * group: group1,
- * label: itemLabel,
- * item: itemModel
- * }
- * filterName2: {
- * filter: filterName2,
- * group: group2
- * label: itemLabel2,
- * item: itemModel2
- * }
- * }
+ *
+ * {
+ * filterName: {
+ * filter: filterName,
+ * group: group1,
+ * label: itemLabel,
+ * item: itemModel
+ * }
+ * filterName2: {
+ * filter: filterName2,
+ * group: group2
+ * label: itemLabel2,
+ * item: itemModel2
+ * }
+ * }
*
* @return {Object} Filter conflicts
*/
filterItemGroup = filterItem.getGroupModel();
// For each item, see if that item is still conflicting
+ // eslint-disable-next-line jquery/no-each-util
$.each( model.groups, function ( groupName, groupModel ) {
if ( filterItem.getGroupName() === groupName ) {
// Check inside the group
expandConflictDefinitions = function ( obj ) {
var result = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( obj, function ( key, conflicts ) {
var filterName,
adjustedConflicts = {};
}, views );
// Go over all views
+ // eslint-disable-next-line jquery/no-each-util
$.each( allViews, function ( viewName, viewData ) {
// Define the view
model.views[ viewName ] = {
filterConflictResult = expandConflictDefinitions( filterConflictMap );
// Set conflicts for groups
+ // eslint-disable-next-line jquery/no-each-util
$.each( groupConflictResult, function ( group, conflicts ) {
model.groups[ group ].setConflicts( conflicts );
} );
// Set conflicts for items
+ // eslint-disable-next-line jquery/no-each-util
$.each( filterConflictResult, function ( filterName, conflicts ) {
var filterItem = model.getItemByName( filterName );
// set conflicts for items in the group
} );
// Create a map between known parameters and their models
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( group, groupModel ) {
if (
groupModel.getType() === 'send_unselected_if_any' ||
var filtersValue;
// For arbitrary numeric single_option values make sure the values
// are normalized to fit within the limits
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.getFilterGroups(), function ( groupName, groupModel ) {
params[ groupName ] = groupModel.normalizeArbitraryValue( params[ groupName ] );
} );
parameters = parameters ? $.extend( true, {}, parameters ) : this.getCurrentParameterState();
// Params
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.getEmptyParameterState(), function ( param, value ) {
if ( parameters[ param ] !== undefined && parameters[ param ] !== value ) {
result[ param ] = parameters[ param ];
view = view || this.getCurrentView();
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( groupName, groupModel ) {
if ( groupModel.getView() === view ) {
result[ groupName ] = groupModel;
groups = this.getFilterGroupsByView( view );
+ // eslint-disable-next-line jquery/no-each-util
$.each( groups, function ( groupName, groupModel ) {
result = result.concat( groupModel.getItems() );
} );
var result = {};
// Get default filter state
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( name, model ) {
if ( !model.isSticky() ) {
$.extend( true, result, model.getDefaultParams() );
mw.rcfilters.dm.FiltersViewModel.prototype.getStickyParams = function () {
var result = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( name, model ) {
if ( model.isSticky() ) {
if ( model.isPerGroupRequestParameter() ) {
mw.rcfilters.dm.FiltersViewModel.prototype.getStickyParamsValues = function () {
var result = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( name, model ) {
if ( model.isSticky() ) {
$.extend( true, result, model.getParamRepresentation() );
} );
}
+ // eslint-disable-next-line jquery/no-each-util
$.each( groupItems, function ( group, model ) {
$.extend(
result,
// },
// group2: "param4|param5"
// }
+ // eslint-disable-next-line jquery/no-each-util
$.each( params, function ( paramName, paramValue ) {
var groupName,
itemOrGroup = model.parameterMap[ paramName ];
// Go over all groups, so we make sure we get the complete output
// even if the parameters don't include a certain group
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.groups, function ( groupName, groupModel ) {
result = $.extend( true, {}, result, groupModel.getFilterRepresentation( groupMap[ groupName ] ) );
} );
mw.rcfilters.dm.FiltersViewModel.prototype.findSelectedItems = function () {
var allSelected = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.getFilterGroups(), function ( groupName, groupModel ) {
allSelected = allSelected.concat( groupModel.findSelectedItems() );
} );
mw.rcfilters.dm.FiltersViewModel.prototype.getViewByTrigger = function ( trigger ) {
var result = 'default';
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.views, function ( name, data ) {
if ( data.trigger === trigger ) {
result = name;
visibleGroupNames = Object.keys( visibleGroups );
// Update visibility of items and groups
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.getFilterGroups(), function ( groupName, groupModel ) {
// Check if the group is visible at all
groupModel.toggleVisible( visibleGroupNames.indexOf( groupName ) !== -1 );
// }
// }
// }
+ // eslint-disable-next-line jquery/no-each-util
$.each( savedQueries.queries || {}, function ( id, obj ) {
if ( obj.data && obj.data.filters ) {
obj.data = model.convertToParameters( obj.data );
}
// Initialize the query items
+ // eslint-disable-next-line jquery/no-each-util
$.each( savedQueries.queries || {}, function ( id, obj ) {
var normalizedData = obj.data,
isDefault = String( savedQueries.default ) === String( id );
// Highlights: appending _color to keys
newData.highlights = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( data.highlights, function ( highlightedFilterName, value ) {
if ( value ) {
newData.highlights[ highlightedFilterName + '_color' ] = data.highlights[ highlightedFilterName ];
data = this.filtersModel.getMinimizedParamRepresentation( fulldata );
// Split highlight/params
+ // eslint-disable-next-line jquery/no-each-util
$.each( data, function ( param, value ) {
if ( param !== 'highlight' && highlightParamNames.indexOf( param ) > -1 ) {
normalizedData.highlights[ param ] = value;
// Prepare views
if ( namespaceStructure ) {
items = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( namespaceStructure, function ( namespaceID, label ) {
// Build and clean up the individual namespace items definition
items.push( {
// Before we do anything, we need to see if we require additional items in the
// groups that have 'AllowArbitrary'. For the moment, those are only single_option
// groups; if we ever expand it, this might need further generalization:
+ // eslint-disable-next-line jquery/no-each-util
$.each( views, function ( viewName, viewData ) {
viewData.groups.forEach( function ( groupData ) {
var extraValues = [];
* Check if new changes, newer than those currently shown, are available
*
* @return {jQuery.Promise} Promise object that resolves with a bool
- * specifying if there are new changes or not
+ * specifying if there are new changes or not
*
* @private
*/
* Map a reason for having no results to its message key
*
* @param {string} reason One of the NO_RESULTS_* "constant" that represent
- * a reason for having no results
+ * a reason for having no results
* @return {string} Key for the message that explains why there is no results in this case
*/
mw.rcfilters.ui.ChangesListWrapperWidget.prototype.getMsgKeyForNoResults = function ( reason ) {
// This lives inside a MenuOptionWidget, which intercepts mousedown
// to select the item. We want to prevent that when we click the highlight
// button
- this.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+ this.$element.on( 'mousedown', function ( e ) {
+ e.stopPropagation();
+ } );
this.updateUiBasedOnModel();
}
);
- this.saveQueryButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+ this.saveQueryButton.$element.on( 'mousedown', function ( e ) {
+ e.stopPropagation();
+ } );
this.saveQueryButton.connect( this, {
click: 'onSaveQueryButtonClick',
this.hideShowButton.connect( this, { click: 'onHideShowButtonClick' } );
// Stop propagation for mousedown, so that the widget doesn't
// trigger the focus on the input and scrolls up when we click the reset button
- this.resetButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
- this.hideShowButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+ this.resetButton.$element.on( 'mousedown', function ( e ) {
+ e.stopPropagation();
+ } );
+ this.hideShowButton.$element.on( 'mousedown', function ( e ) {
+ e.stopPropagation();
+ } );
this.model.connect( this, {
initialize: 'onModelInitialize',
update: 'onModelUpdate',
// If there are no selected items, scroll menu to top
// This has to be in a setTimeout so the menu has time
// to be positioned and fixed
- setTimeout( function () { this.getMenu().scrollToTop(); }.bind( this ), 0 );
+ setTimeout(
+ function () {
+ this.getMenu().scrollToTop();
+ }.bind( this )
+ );
}
} else {
// Clear selection
if ( config.events ) {
// Aggregate events
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( config.events, function ( eventName, eventEmit ) {
aggregate[ eventName ] = eventEmit;
} );
this.$overlay.append( this.highlightPopup.$element );
// Count groups per view
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( groups, function ( groupName, groupModel ) {
if ( !groupModel.isHidden() ) {
viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0;
}
} );
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( groups, function ( groupName, groupModel ) {
var currentItems = [],
view = groupModel.getView();
this.$icon.on( { click: this.onDefaultIconClick.bind( this ) } );
// Prevent propagation on mousedown for the save button
// so the menu doesn't close
- this.saveButton.$element.on( { mousedown: function () { return false; } } );
+ this.saveButton.$element.on( { mousedown: function () {
+ return false;
+ } } );
// Initialize
this.toggleDefault( !!this.model.isDefault() );
OO.ui.mixin.LabelElement.call( this, config );
this.model = model;
- this.itemFilter = config.itemFilter || function () { return true; };
+ this.itemFilter = config.itemFilter || function () {
+ return true;
+ };
// Build the selection from the item models
this.selectWidget = new OO.ui.ButtonSelectWidget();
* Add search suggestions to the search form.
*/
( function () {
+ // eslint-disable-next-line jquery/no-map-util
var searchNS = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( nsName, nsID ) {
if ( nsID >= 0 && mw.user.options.get( 'searchNs' + nsID ) ) {
// Cast string key to number
this.text( text );
// wrap only as link, if the config doesn't disallow it
- if ( textboxConfig.wrapAsLink !== false ) {
+ if ( textboxConfig.wrapAsLink !== false ) {
this.wrap(
$( '<a>' )
.attr( 'href', formData.baseHref + $.param( formData.linkParams ) )
// Forward most methods for convenience
for ( k in this.widget ) {
- if ( $.isFunction( this.widget[ k ] ) && !this[ k ] ) {
+ if ( typeof this.widget[ k ] === 'function' && !this[ k ] ) {
this[ k ] = this.widget[ k ].bind( this.widget );
}
}
};
OptionalWidget.prototype.onOverlayClick = function () {
this.setDisabled( false );
- if ( $.isFunction( this.widget.focus ) ) {
+ if ( typeof this.widget.focus === 'function' ) {
this.widget.focus();
}
};
break;
case 'namespace':
+ // eslint-disable-next-line jquery/no-map-util
items = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) {
if ( ns === '0' ) {
name = mw.message( 'blanknamespace' ).text();
$.extend( finalWidget, WidgetMethods.optionalWidget );
if ( widget.getSubmodules ) {
finalWidget.getSubmodules = widget.getSubmodules.bind( widget );
- finalWidget.on( 'disable', function () { setTimeout( ApiSandbox.updateUI ); } );
+ finalWidget.on( 'disable', function () {
+ setTimeout( ApiSandbox.updateUI );
+ } );
}
if ( widget.getApiValueForTemplates ) {
finalWidget.getApiValueForTemplates = widget.getApiValueForTemplates.bind( widget );
function widgetLabelOnClick() {
var f = this.getField();
- if ( $.isFunction( f.setDisabled ) ) {
+ if ( typeof f.setDisabled === 'function' ) {
f.setDisabled( false );
}
- if ( $.isFunction( f.focus ) ) {
+ if ( typeof f.focus === 'function' ) {
f.focus();
}
}
}
toRemove = {};
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.templatedItemsCache, function ( k, el ) {
if ( el.widget.isElementAttached() ) {
toRemove[ k ] = el;
done = $.isEmptyObject( p.vars );
if ( done ) {
container = Util.apiBool( p.info.deprecated ) ? that.deprecatedItemsFieldset : that.itemsFieldset;
+ // FIXME: ES6-ism
+ // eslint-disable-next-line jquery/no-each-util
index = container.getItems().findIndex( function ( el ) {
return el.apiParamIndex !== undefined && el.apiParamIndex > p.info.index;
} );
}
} else {
newVars = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( p.vars, function ( k, v ) {
newVars[ k ] = v.replace( placeholder, value );
} );
};
while ( toProcess.length ) {
p = toProcess.shift();
+ // eslint-disable-next-line jquery/no-each-util
$.each( p.vars, doProcess );
}
+ // eslint-disable-next-line jquery/no-map-util
toRemove = $.map( toRemove, function ( el, name ) {
delete that.widgets[ name ];
return [ el.widgetField, el.helpField ];
if ( this.paramInfo === null ) {
return [];
} else {
+ // eslint-disable-next-line jquery/no-map-util
promises = $.map( this.widgets, function ( widget ) {
return widget.apiCheckValid();
} );
if ( this.paramInfo === null ) {
this.loadFromQueryParams = params;
} else {
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.widgets, function ( name, widget ) {
var v = Object.prototype.hasOwnProperty.call( params, name ) ? params[ name ] : undefined;
widget.setApiValue( v );
* @param {Object} displayParams Write query parameters for display into this object
*/
ApiSandbox.PageLayout.prototype.getQueryParams = function ( params, displayParams ) {
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.widgets, function ( name, widget ) {
var value = widget.getApiValue();
if ( value !== undefined ) {
params[ name ] = value;
- if ( $.isFunction( widget.getApiValueForDisplay ) ) {
+ if ( typeof widget.getApiValueForDisplay === 'function' ) {
value = widget.getApiValueForDisplay();
}
displayParams[ name ] = value;
*/
ApiSandbox.PageLayout.prototype.getSubpages = function () {
var ret = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.widgets, function ( name, widget ) {
var submodules, i;
- if ( $.isFunction( widget.getSubmodules ) ) {
+ if ( typeof widget.getSubmodules === 'function' ) {
submodules = widget.getSubmodules();
for ( i = 0; i < submodules.length; i++ ) {
ret.push( {
render: function ( data, partialTemplates ) {
var partials = {};
if ( partialTemplates ) {
- /* eslint-disable-next-line no-restricted-properties */
+ // eslint-disable-next-line jquery/no-each-util
$.each( partialTemplates, function ( name, template ) {
partials[ name ] = template.getSource();
} );
*/
getParamValue: function ( param, url ) {
// Get last match, stop at hash
- var re = new RegExp( '^[^#]*[&?]' + mw.RegExp.escape( param ) + '=([^&#]*)' ),
+ var re = new RegExp( '^[^#]*[&?]' + mw.RegExp.escape( param ) + '=([^&#]*)' ),
m = re.exec( url !== undefined ? url : location.href );
if ( m ) {
* @param {HTMLElement} el Element that's being tested
* @param {Object} [rectangle] Viewport to test against; structured as such:
*
- * var rectangle = {
- * top: topEdge,
- * left: leftEdge,
- * right: rightEdge,
- * bottom: bottomEdge
- * }
- * Defaults to viewport made from `window`.
+ * var rectangle = {
+ * top: topEdge,
+ * left: leftEdge,
+ * right: rightEdge,
+ * bottom: bottomEdge
+ * }
+ *
+ * Defaults to viewport made from `window`.
*
* @return {boolean}
*/
if ( dates instanceof Date ) {
dates = [ dates ];
} else if ( Array.isArray( dates ) ) {
- dates = dates.filter( function ( dt ) { return dt instanceof Date; } );
+ dates = dates.filter( function ( dt ) {
+ return dt instanceof Date;
+ } );
dates.sort();
} else {
dates = [];
parseValue: this.parseSpecValue
};
spec.size = Math.max.apply(
+ // eslint-disable-next-line jquery/no-map-util
null, $.map( spec.values, function ( v ) { return v.length; } )
);
return spec;
}
}
+ // eslint-disable-next-line jquery/no-each-util
if ( v.normalize ) {
+ // eslint-disable-next-line jquery/no-each-util
v = v.normalize();
}
re = new RegExp( '^\\s*' + v.replace( /([\\{}()|.?*+\-^$\[\]])/g, '\\$1' ), 'i' ); // eslint-disable-line no-useless-escape
} else {
maxlength = spec.size;
if ( spec.intercalarySize ) {
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( spec.intercalarySize, reduceFunc );
}
$field = $( '<input>' ).attr( 'type', 'text' )
}
if ( spec.values ) {
spec.size = Math.max.apply(
+ // eslint-disable-next-line jquery/no-map-util
null, $.map( spec.values, function ( v ) { return v.length; } )
);
}
if ( config.fullMonthNames && !config.shortMonthNames ) {
config.shortMonthNames = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( config.fullMonthNames, function ( k, v ) {
config.shortMonthNames[ k ] = v.substr( 0, 3 );
} );
}
if ( config.shortDayNames && !config.dayLetters ) {
config.dayLetters = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( config.shortDayNames, function ( k, v ) {
config.dayLetters[ k ] = v.substr( 0, 1 );
} );
}
if ( config.fullDayNames && !config.dayLetters ) {
config.dayLetters = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( config.fullDayNames, function ( k, v ) {
config.dayLetters[ k ] = v.substr( 0, 1 );
} );
}
if ( config.fullDayNames && !config.shortDayNames ) {
config.shortDayNames = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( config.fullDayNames, function ( k, v ) {
config.shortDayNames[ k ] = v.substr( 0, 3 );
} );
if ( this.fullMonthNames && !this.shortMonthNames ) {
this.shortMonthNames = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.fullMonthNames, function ( k, v ) {
this.shortMonthNames[ k ] = v.substr( 0, 3 );
}.bind( this ) );
}
if ( this.shortDayNames && !this.dayLetters ) {
this.dayLetters = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.shortDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
}.bind( this ) );
}
if ( this.fullDayNames && !this.dayLetters ) {
this.dayLetters = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.fullDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
}.bind( this ) );
}
if ( this.fullDayNames && !this.shortDayNames ) {
this.shortDayNames = {};
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.fullDayNames, function ( k, v ) {
this.shortDayNames[ k ] = v.substr( 0, 3 );
}.bind( this ) );
}
if ( !this.dayLetters ) {
this.dayLetters = [];
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.shortDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
}.bind( this ) );
spec.parseValue = this.parseSpecValue;
if ( spec.values ) {
spec.size = Math.max.apply(
+ // eslint-disable-next-line jquery/no-map-util
null, $.map( spec.values, function ( v ) { return v.length; } )
);
}
$headRow.append( $( '<td>' ).text( '\u00A0' ) );
// Iterate over the columns object (ignore the value)
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.columns, function ( columnLabel ) {
$headRow.append( $( '<th>' ).html( columnLabel ) );
} );
$thead.append( $headRow );
// Build table
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.rows, function ( rowLabel, rowTag ) {
var $row = $( '<tr>' ),
labelField = new OO.ui.FieldLayout(
$row.append( $( '<td>' ).append( labelField.$element ) );
// Columns
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( widget.columns, function ( columnLabel, columnTag ) {
var thisTag = columnTag + '-' + rowTag,
checkbox = new OO.ui.CheckboxInputWidget( {
// setDisabled sometimes gets called before the widget is ready
if ( this.checkboxes && Object.keys( this.checkboxes ).length > 0 ) {
// Propagate to all checkboxes and update their disabled state
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( this.checkboxes, function ( name, checkbox ) {
checkbox.setDisabled( widget.isTagDisabled( name ) );
} );
exclude = config.exclude || [],
mainNamespace = mw.config.get( 'wgNamespaceIds' )[ '' ];
+ // eslint-disable-next-line jquery/no-map-util
options = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) {
if ( ns < mainNamespace || exclude.indexOf( Number( ns ) ) !== -1 ) {
return null; // skip
urls = data.data[ 3 ],
self = this;
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( titles, function ( i, result ) {
items.push( new mw.widgets.TitleOptionWidget(
self.getOptionWidgetData(
{
"root": true,
- "extends": "wikimedia",
- "env": {
- "browser": true
- },
+ "extends": "wikimedia/client",
"rules": {
"max-len": 0
}
// Check for incomplete animations/requests/etc and throw if there are any.
if ( $.timers && $.timers.length !== 0 ) {
timers = $.timers.length;
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( $.timers, function ( i, timer ) {
var node = timer.elem;
mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' +
var altPromises = [];
// When we have ES6 support we'll be able to use Array.from here
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( arguments, function ( i, arg ) {
var alt = $.Deferred();
altPromises.push( alt );
* @param {string} msg text to pass on to qunit describing the test case
* @param {string[]} parserId of the parser that will be tested
* @param {string[][]} data Array of testcases. Each testcase, array of
- * inputValue: The string value that we want to test the parser for
- * recognized: If we expect that this value's type is detectable by the parser
- * outputValue: The value the parser has converted the input to
- * msg: describing the testcase
+ * inputValue: The string value that we want to test the parser for
+ * recognized: If we expect that this value's type is detectable by the parser
+ * outputValue: The value the parser has converted the input to
+ * msg: describing the testcase
* @param {function($table)} callback something to do before we start the testcase
*/
function parserTest( msg, parserId, data, callback ) {
parserTest( 'IPv4', 'IPAddress', ipv4 );
simpleMDYDatesInMDY = [
- [ 'January 17, 2010', true, 20100117, 'Long middle endian date' ],
- [ 'Jan 17, 2010', true, 20100117, 'Short middle endian date' ],
- [ '1/17/2010', true, 20100117, 'Numeric middle endian date' ],
- [ '01/17/2010', true, 20100117, 'Numeric middle endian date with padding on month' ],
- [ '01/07/2010', true, 20100107, 'Numeric middle endian date with padding on day' ],
- [ '01/07/0010', true, 20100107, 'Numeric middle endian date with padding on year' ],
- [ '5.12.1990', true, 19900512, 'Numeric middle endian date with . separator' ]
+ [ 'January 17, 2010', true, 20100117, 'Long middle endian date' ],
+ [ 'Jan 17, 2010', true, 20100117, 'Short middle endian date' ],
+ [ '1/17/2010', true, 20100117, 'Numeric middle endian date' ],
+ [ '01/17/2010', true, 20100117, 'Numeric middle endian date with padding on month' ],
+ [ '01/07/2010', true, 20100107, 'Numeric middle endian date with padding on day' ],
+ [ '01/07/0010', true, 20100107, 'Numeric middle endian date with padding on year' ],
+ [ '5.12.1990', true, 19900512, 'Numeric middle endian date with . separator' ]
];
parserTest( 'MDY Dates using mdy content language', 'date', simpleMDYDatesInMDY );
simpleMDYDatesInDMY = [
- [ 'January 17, 2010', true, 20100117, 'Long middle endian date' ],
- [ 'Jan 17, 2010', true, 20100117, 'Short middle endian date' ],
- [ '1/17/2010', true, 20101701, 'Numeric middle endian date' ],
- [ '01/17/2010', true, 20101701, 'Numeric middle endian date with padding on month' ],
- [ '01/07/2010', true, 20100701, 'Numeric middle endian date with padding on day' ],
- [ '01/07/0010', true, 20100701, 'Numeric middle endian date with padding on year' ],
- [ '5.12.1990', true, 19901205, 'Numeric middle endian date with . separator' ]
+ [ 'January 17, 2010', true, 20100117, 'Long middle endian date' ],
+ [ 'Jan 17, 2010', true, 20100117, 'Short middle endian date' ],
+ [ '1/17/2010', true, 20101701, 'Numeric middle endian date' ],
+ [ '01/17/2010', true, 20101701, 'Numeric middle endian date with padding on month' ],
+ [ '01/07/2010', true, 20100701, 'Numeric middle endian date with padding on day' ],
+ [ '01/07/0010', true, 20100701, 'Numeric middle endian date with padding on year' ],
+ [ '5.12.1990', true, 19901205, 'Numeric middle endian date with . separator' ]
];
parserTest( 'MDY Dates using dmy content language', 'date', simpleMDYDatesInDMY, function () {
mw.config.set( {
} );
oldMDYDates = [
- [ 'January 19, 1400 BC', false, '99999999', 'BC' ],
- [ 'January 19, 1400BC', false, '99999999', 'Connected BC' ],
- [ 'January, 19 1400 B.C.', false, '99999999', 'B.C.' ],
- [ 'January 19, 1400 AD', false, '99999999', 'AD' ],
- [ 'January, 19 10', true, 20100119, 'AD' ],
- [ 'January, 19 1', false, '99999999', 'AD' ]
+ [ 'January 19, 1400 BC', false, '99999999', 'BC' ],
+ [ 'January 19, 1400BC', false, '99999999', 'Connected BC' ],
+ [ 'January, 19 1400 B.C.', false, '99999999', 'B.C.' ],
+ [ 'January 19, 1400 AD', false, '99999999', 'AD' ],
+ [ 'January, 19 10', true, 20100119, 'AD' ],
+ [ 'January, 19 1', false, '99999999', 'AD' ]
];
parserTest( 'Very old MDY dates', 'date', oldMDYDates );
complexMDYDates = [
- [ 'January, 19 2010', true, 20100119, 'Comma after month' ],
- [ 'January 19, 2010', true, 20100119, 'Comma after day' ],
- [ 'January/19/2010', true, 20100119, 'Forward slash separator' ],
- [ '04 22 1991', true, 19910422, 'Month with 0 padding' ],
- [ 'April 21 1991', true, 19910421, 'Space separation' ],
- [ '04 22 1991', true, 19910422, 'Month with 0 padding' ],
- [ 'December 12 \'10', true, 20101212, '' ],
- [ 'Dec 12 \'10', true, 20101212, '' ],
- [ 'Dec. 12 \'10', true, 20101212, '' ]
+ [ 'January, 19 2010', true, 20100119, 'Comma after month' ],
+ [ 'January 19, 2010', true, 20100119, 'Comma after day' ],
+ [ 'January/19/2010', true, 20100119, 'Forward slash separator' ],
+ [ '04 22 1991', true, 19910422, 'Month with 0 padding' ],
+ [ 'April 21 1991', true, 19910421, 'Space separation' ],
+ [ '04 22 1991', true, 19910422, 'Month with 0 padding' ],
+ [ 'December 12 \'10', true, 20101212, '' ],
+ [ 'Dec 12 \'10', true, 20101212, '' ],
+ [ 'Dec. 12 \'10', true, 20101212, '' ]
];
parserTest( 'MDY Dates', 'date', complexMDYDates );
clobberedDates = [
- [ 'January, 19 2010 - January, 20 2010', false, '99999999', 'Date range with hyphen' ],
- [ 'January, 19 2010 — January, 20 2010', false, '99999999', 'Date range with mdash' ],
- [ 'prefixJanuary, 19 2010', false, '99999999', 'Connected prefix' ],
- [ 'prefix January, 19 2010', false, '99999999', 'Prefix' ],
- [ 'December 12 2010postfix', false, '99999999', 'ConnectedPostfix' ],
- [ 'December 12 2010 postfix', false, '99999999', 'Postfix' ],
- [ 'A simple text', false, '99999999', 'Plain text in date sort' ],
- [ '04l22l1991', false, '99999999', 'l char as separator' ],
- [ 'January\\19\\2010', false, '99999999', 'backslash as date separator' ]
+ [ 'January, 19 2010 - January, 20 2010', false, '99999999', 'Date range with hyphen' ],
+ [ 'January, 19 2010 — January, 20 2010', false, '99999999', 'Date range with mdash' ],
+ [ 'prefixJanuary, 19 2010', false, '99999999', 'Connected prefix' ],
+ [ 'prefix January, 19 2010', false, '99999999', 'Prefix' ],
+ [ 'December 12 2010postfix', false, '99999999', 'ConnectedPostfix' ],
+ [ 'December 12 2010 postfix', false, '99999999', 'Postfix' ],
+ [ 'A simple text', false, '99999999', 'Plain text in date sort' ],
+ [ '04l22l1991', false, '99999999', 'l char as separator' ],
+ [ 'January\\19\\2010', false, '99999999', 'backslash as date separator' ]
];
parserTest( 'Clobbered Dates', 'date', clobberedDates );
MYDates = [
- [ 'December 2010', false, '99999999', 'Plain month year' ],
- [ 'Dec 2010', false, '99999999', 'Abreviated month year' ],
- [ '12 2010', false, '99999999', 'Numeric month year' ]
+ [ 'December 2010', false, '99999999', 'Plain month year' ],
+ [ 'Dec 2010', false, '99999999', 'Abreviated month year' ],
+ [ '12 2010', false, '99999999', 'Numeric month year' ]
];
parserTest( 'MY Dates', 'date', MYDates );
YDates = [
- [ '2010', false, '99999999', 'Plain 4-digit year' ],
- [ '876', false, '99999999', '3-digit year' ],
- [ '76', false, '99999999', '2-digit year' ],
- [ '\'76', false, '99999999', '2-digit millenium bug year' ],
- [ '2010 BC', false, '99999999', '4-digit year BC' ]
+ [ '2010', false, '99999999', 'Plain 4-digit year' ],
+ [ '876', false, '99999999', '3-digit year' ],
+ [ '76', false, '99999999', '2-digit year' ],
+ [ '\'76', false, '99999999', '2-digit millenium bug year' ],
+ [ '2010 BC', false, '99999999', '4-digit year BC' ]
];
parserTest( 'Y Dates', 'date', YDates );
ISODates = [
- [ '', false, -Infinity, 'Not a date' ],
- [ '2000', false, 946684800000, 'Plain 4-digit year' ],
- [ '2000-01', true, 946684800000, 'Year with month' ],
- [ '2000-01-01', true, 946684800000, 'Year with month and day' ],
- [ '2000-13-01', false, 978307200000, 'Non existant month' ],
- [ '2000-01-32', true, 949363200000, 'Non existant day' ],
- [ '2000-01-01T12:30:30', true, 946729830000, 'Date with a time' ],
- [ '2000-01-01T12:30:30Z', true, 946729830000, 'Date with a UTC+0 time' ],
- [ '2000-01-01T24:30:30Z', true, 946773030000, 'Date with invalid hours' ],
- [ '2000-01-01T12:60:30Z', true, 946728000000, 'Date with invalid minutes' ],
- [ '2000-01-01T12:30:61Z', true, 946729800000, 'Date with invalid amount of seconds, drops seconds' ],
- [ '2000-01-01T23:59:59Z', true, 946771199000, 'Edges of time' ],
- [ '2000-01-01T12:30:30.111Z', true, 946729830111, 'Date with milliseconds' ],
- [ '2000-01-01T12:30:30.11111Z', true, 946729830111, 'Date with too high precision' ],
- [ '2000-01-01T12:30:30,111Z', true, 946729830111, 'Date with milliseconds and , separator' ],
- [ '2000-01-01T12:30:30+01:00', true, 946726230000, 'Date time in UTC+1' ],
- [ '2000-01-01T12:30:30+01:30', true, 946724430000, 'Date time in UTC+1:30' ],
- [ '2000-01-01T12:30:30-01:00', true, 946733430000, 'Date time in UTC-1' ],
- [ '2000-01-01T12:30:30-01:30', true, 946735230000, 'Date time in UTC-1:30' ],
+ [ '', false, -Infinity, 'Not a date' ],
+ [ '2000', false, 946684800000, 'Plain 4-digit year' ],
+ [ '2000-01', true, 946684800000, 'Year with month' ],
+ [ '2000-01-01', true, 946684800000, 'Year with month and day' ],
+ [ '2000-13-01', false, 978307200000, 'Non existant month' ],
+ [ '2000-01-32', true, 949363200000, 'Non existant day' ],
+ [ '2000-01-01T12:30:30', true, 946729830000, 'Date with a time' ],
+ [ '2000-01-01T12:30:30Z', true, 946729830000, 'Date with a UTC+0 time' ],
+ [ '2000-01-01T24:30:30Z', true, 946773030000, 'Date with invalid hours' ],
+ [ '2000-01-01T12:60:30Z', true, 946728000000, 'Date with invalid minutes' ],
+ [ '2000-01-01T12:30:61Z', true, 946729800000, 'Date with invalid amount of seconds, drops seconds' ],
+ [ '2000-01-01T23:59:59Z', true, 946771199000, 'Edges of time' ],
+ [ '2000-01-01T12:30:30.111Z', true, 946729830111, 'Date with milliseconds' ],
+ [ '2000-01-01T12:30:30.11111Z', true, 946729830111, 'Date with too high precision' ],
+ [ '2000-01-01T12:30:30,111Z', true, 946729830111, 'Date with milliseconds and , separator' ],
+ [ '2000-01-01T12:30:30+01:00', true, 946726230000, 'Date time in UTC+1' ],
+ [ '2000-01-01T12:30:30+01:30', true, 946724430000, 'Date time in UTC+1:30' ],
+ [ '2000-01-01T12:30:30-01:00', true, 946733430000, 'Date time in UTC-1' ],
+ [ '2000-01-01T12:30:30-01:30', true, 946735230000, 'Date time in UTC-1:30' ],
[ '2000-01-01T12:30:30.111+01:00', true, 946726230111, 'Date time and milliseconds in UTC+1' ],
[ '2000-01-01Postfix', true, 946684800000, 'Date with appended postfix' ],
[ '2000-01-01 Postfix', true, 946684800000, 'Date with separate postfix' ],
- [ '2 Postfix', false, -62104060800000, 'One digit with separate postfix' ],
- [ 'ca. 2', false, -62104060800000, 'Three digit with separate prefix' ],
- [ '~200', false, -55855785600000, 'Three digit with appended prefix' ],
- [ 'ca. 200[1]', false, -55855785600000, 'Three digit with separate prefix and postfix' ],
- [ '2000-11-31', true, 975628800000, '31 days in 30 day month' ],
- [ '50-01-01', true, -60589296000000, 'Year with just two digits' ],
- [ '2', false, -62104060800000, 'Year with one digit' ],
- [ '02-01', true, -62104060800000, 'Year with one digit and leading zero' ],
- [ ' 2-01', true, -62104060800000, 'Year with one digit and leading space' ],
- [ '-2-10', true, -62206704000000, 'Year BC with month' ],
- [ '-9999', false, -377705116800000, 'max. Year BC' ],
- [ '+9999-12', true, 253399622400000, 'max. Date with +sign' ],
- [ '2000-01-01 12:30:30Z', true, 946729830000, 'Date and time with no T marker' ],
- [ '2000-01-01T12:30:60Z', true, 946729860000, 'Date with leap second' ],
- [ '2000-01-01T12:30:30-23:59', true, 946816170000, 'Date time in UTC-23:59' ],
- [ '2000-01-01T12:30:30+23:59', true, 946643490000, 'Date time in UTC+23:59' ],
- [ '2000-01-01T123030+0100', true, 946726230000, 'Time without separators' ],
- [ '20000101T123030+0100', false, 946726230000, 'All without separators' ]
+ [ '2 Postfix', false, -62104060800000, 'One digit with separate postfix' ],
+ [ 'ca. 2', false, -62104060800000, 'Three digit with separate prefix' ],
+ [ '~200', false, -55855785600000, 'Three digit with appended prefix' ],
+ [ 'ca. 200[1]', false, -55855785600000, 'Three digit with separate prefix and postfix' ],
+ [ '2000-11-31', true, 975628800000, '31 days in 30 day month' ],
+ [ '50-01-01', true, -60589296000000, 'Year with just two digits' ],
+ [ '2', false, -62104060800000, 'Year with one digit' ],
+ [ '02-01', true, -62104060800000, 'Year with one digit and leading zero' ],
+ [ ' 2-01', true, -62104060800000, 'Year with one digit and leading space' ],
+ [ '-2-10', true, -62206704000000, 'Year BC with month' ],
+ [ '-9999', false, -377705116800000, 'max. Year BC' ],
+ [ '+9999-12', true, 253399622400000, 'max. Date with +sign' ],
+ [ '2000-01-01 12:30:30Z', true, 946729830000, 'Date and time with no T marker' ],
+ [ '2000-01-01T12:30:60Z', true, 946729860000, 'Date with leap second' ],
+ [ '2000-01-01T12:30:30-23:59', true, 946816170000, 'Date time in UTC-23:59' ],
+ [ '2000-01-01T12:30:30+23:59', true, 946643490000, 'Date time in UTC+23:59' ],
+ [ '2000-01-01T123030+0100', true, 946726230000, 'Time without separators' ],
+ [ '20000101T123030+0100', false, 946726230000, 'All without separators' ]
];
parserTest( 'ISO Dates', 'isoDate', ISODates );
currencyData = [
- [ '1.02 $', true, 1.02, '' ],
- [ '$ 3.00', true, 3, '' ],
- [ '€ 2,99', true, 299, '' ],
- [ '$ 1.00', true, 1, '' ],
- [ '$3.50', true, 3.50, '' ],
- [ '$ 1.50', true, 1.50, '' ],
- [ '€ 0.99', true, 0.99, '' ],
- [ '$ 299.99', true, 299.99, '' ],
- [ '$ 2,299.99', true, 2299.99, '' ],
- [ '$ 2,989', true, 2989, '' ],
- [ '$ 2 299.99', true, 2299.99, '' ],
- [ '$ 2 989', true, 2989, '' ],
- [ '$ 2.989', true, 2.989, '' ]
+ [ '1.02 $', true, 1.02, '' ],
+ [ '$ 3.00', true, 3, '' ],
+ [ '€ 2,99', true, 299, '' ],
+ [ '$ 1.00', true, 1, '' ],
+ [ '$3.50', true, 3.50, '' ],
+ [ '$ 1.50', true, 1.50, '' ],
+ [ '€ 0.99', true, 0.99, '' ],
+ [ '$ 299.99', true, 299.99, '' ],
+ [ '$ 2,299.99', true, 2299.99, '' ],
+ [ '$ 2,989', true, 2989, '' ],
+ [ '$ 2 299.99', true, 2299.99, '' ],
+ [ '$ 2 989', true, 2989, '' ],
+ [ '$ 2.989', true, 2.989, '' ]
];
parserTest( 'Currency', 'currency', currencyData );
transformedCurrencyData = [
- [ '1.02 $', true, 102, '' ],
- [ '$ 3.00', true, 300, '' ],
- [ '€ 2,99', true, 2.99, '' ],
- [ '$ 1.00', true, 100, '' ],
- [ '$3.50', true, 350, '' ],
- [ '$ 1.50', true, 150, '' ],
- [ '€ 0.99', true, 99, '' ],
- [ '$ 299.99', true, 29999, '' ],
- [ '$ 2\'299,99', true, 2299.99, '' ],
- [ '$ 2,989', true, 2.989, '' ],
- [ '$ 2 299.99', true, 229999, '' ],
- [ '2 989 $', true, 2989, '' ],
- [ '299.99 $', true, 29999, '' ],
- [ '2\'299,99 $', true, 2299.99, '' ],
- [ '2,989 $', true, 2.989, '' ],
- [ '2 299.99 $', true, 229999, '' ],
- [ '2 989 $', true, 2989, '' ]
+ [ '1.02 $', true, 102, '' ],
+ [ '$ 3.00', true, 300, '' ],
+ [ '€ 2,99', true, 2.99, '' ],
+ [ '$ 1.00', true, 100, '' ],
+ [ '$3.50', true, 350, '' ],
+ [ '$ 1.50', true, 150, '' ],
+ [ '€ 0.99', true, 99, '' ],
+ [ '$ 299.99', true, 29999, '' ],
+ [ '$ 2\'299,99', true, 2299.99, '' ],
+ [ '$ 2,989', true, 2.989, '' ],
+ [ '$ 2 299.99', true, 229999, '' ],
+ [ '2 989 $', true, 2989, '' ],
+ [ '299.99 $', true, 29999, '' ],
+ [ '2\'299,99 $', true, 2299.99, '' ],
+ [ '2,989 $', true, 2.989, '' ],
+ [ '2 299.99 $', true, 229999, '' ],
+ [ '2 989 $', true, 2989, '' ]
];
parserTest( 'Currency with european separators', 'currency', transformedCurrencyData, function () {
mw.config.set( {
// We expect 22'234.444,22
// Map from ascii separators => localized separators
- wgSeparatorTransformTable: [ ', . ,', '\' , .' ],
+ wgSeparatorTransformTable: [ ',\t.\t,', '\'\t,\t.' ],
wgDigitTransformTable: [ '', '' ]
} );
} );
},
this.responseDelay );
- return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
+ return deferred.promise( { abort: function () {
+ clearTimeout( timer );
+ } } );
};
EmptyResourceProvider.prototype.getResults = function () {
},
this.responseDelay );
- return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
+ return deferred.promise( { abort: function () {
+ clearTimeout( timer );
+ } } );
};
SingleResultResourceProvider.prototype.getResults = function ( howMany ) {
},
this.responseDelay );
- return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
+ return deferred.promise( { abort: function () {
+ clearTimeout( timer );
+ } } );
};
/* Tests */
assert.expect( 1 );
// Make the delay higher
- providers.forEach( function ( provider ) { provider.responseDelay = 3; } );
+ providers.forEach( function ( provider ) {
+ provider.responseDelay = 3;
+ } );
// Add providers to queue
biggerQueue.setProviders( providers );
} );
// Make the delay higher
- providers.forEach( function ( provider ) { provider.responseDelay = 5; } );
+ providers.forEach( function ( provider ) {
+ provider.responseDelay = 5;
+ } );
biggerQueue.setParams( { foo: 'baz' } );
biggerQueue.get( 10 )
} );
}
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( pluralTestcases, function ( langCode, tests ) {
if ( langCode === mw.config.get( 'wgUserLanguage' ) ) {
pluralTest( langCode, tests );
]
};
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( grammarTests, function ( langCode, test ) {
if ( langCode === mw.config.get( 'wgUserLanguage' ) ) {
grammarTest( langCode, test );
assert.strictEqual( conf.get( 'constructor' ), null, 'Map.get does not look at Object.prototype of internal storage (constructor)' );
assert.strictEqual( conf.get( 'hasOwnProperty' ), null, 'Map.get does not look at Object.prototype of internal storage (hasOwnProperty)' );
- conf.set( 'hasOwnProperty', function () { return true; } );
+ conf.set( 'hasOwnProperty', function () {
+ return true;
+ } );
assert.strictEqual( conf.get( 'example', 'missing' ), 'missing', 'Map.get uses neutral hasOwnProperty method (positive)' );
conf.set( 'example', 'Foo' );
- conf.set( 'hasOwnProperty', function () { return false; } );
+ conf.set( 'hasOwnProperty', function () {
+ return false;
+ } );
assert.strictEqual( conf.get( 'example' ), 'Foo', 'Map.get uses neutral hasOwnProperty method (negative)' );
assert.strictEqual( conf.set( 'constructor', 42 ), true, 'Map.set for key "constructor"' );
assertMultipleFormats( [ 'int-msg' ], [ 'text', 'parse', 'escaped' ], 'Some Other Message', 'int is resolved' );
assert.strictEqual( mw.message( 'int-msg' ).plain(), mw.messages.get( 'int-msg' ), 'int is not resolved in plain mode' );
- assert.ok( mw.messages.set( 'mediawiki-italics-msg', '<i>Very</i> important' ), 'mw.messages.set: Register' );
+ assert.ok( mw.messages.set( 'mediawiki-italics-msg', '<i>Very</i> important' ), 'mw.messages.set: Register' );
assertMultipleFormats( [ 'mediawiki-italics-msg' ], [ 'plain', 'text', 'parse' ], mw.messages.get( 'mediawiki-italics-msg' ), 'Simple italics unchanged' );
assert.htmlEqual(
mw.message( 'mediawiki-italics-msg' ).escaped(),
'<i>Very</i> important',
- 'Italics are escaped in escaped mode'
+ 'Italics are escaped in escaped mode'
);
assert.ok( mw.messages.set( 'mediawiki-italics-with-link', 'An <i>italicized [[link|wiki-link]]</i>' ), 'mw.messages.set: Register' );
QUnit.test( 'wikiUrlencode', function ( assert ) {
assert.strictEqual( util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
// See also wfUrlencodeTest.php#provideURLS
- // eslint-disable-next-line no-restricted-properties
+ // eslint-disable-next-line jquery/no-each-util
$.each( {
'+': '%2B',
'&': '%26',
{
- "extends": "../../.eslintrc.json",
+ "root": true,
+ "extends": [
+ "wikimedia/server"
+ ],
"env": {
- "es6": true,
- "mocha": true,
- "node": true
+ "mocha": true
},
"globals": {
"browser": false
},
- "rules":{
- "no-console": 0,
- "no-restricted-properties": 0
+ "rules": {
+ "no-console": 0
}
}
+++ /dev/null
-{
- "extends": "wikimedia",
- "env": {
- "es6": true,
- "node": true
- },
- "globals": {
- "browser": false
- }
-}