mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/MinervaNeue
synced 2024-11-28 16:10:55 +00:00
874d9c9e3b
From TypeScript's do's and don'ts:[0] Don’t ever use the types Number, String, Boolean, or Object. These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code. Although Minerva only uses JSDocs at this time which seemingly doesn't care about casing[1], we should endeavor to use the proper return types. This patch lowercases typing to indicate primitive / boxed type as appropriate.[2] As a special case, function types are uppercased for compatibility with TypeScript type checking. Also, JQuery types are of type "JQuery". The global JQuery object's identifier is "jQuery". This patch uppercases J's where appropriate. Lastly, replace unsupported type "Integer" with "number" and a comment. [0] https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#general-types [1] https://github.com/jsdoc3/jsdoc/issues/1046#issuecomment-126477791 [2] find resources tests -iname \*.js| xargs -rd\\n sed -ri ' s%\{\s*(number|string|boolean|object|null|undefined)%{\L\1%gi; s%\{\s*function%{Function%g; s%\{\s*jquery%{JQuery%gi; s%\{\s*integer\s*\}%{number} An integer.%gi ' Change-Id: I6cbac15940e4501aee7ede8f421b77ffd027170d
137 lines
4.1 KiB
JavaScript
137 lines
4.1 KiB
JavaScript
( function ( M, $ ) {
|
|
var msg = mw.msg,
|
|
template = mw.template,
|
|
Overlay = M.require( 'mobile.startup/Overlay' );
|
|
|
|
/**
|
|
* Page overlay prompting a user for given action
|
|
* @class PointerOverlay
|
|
* @module skins.minerva.newusers/PointerOverlay
|
|
*/
|
|
function PointerOverlay() {
|
|
Overlay.apply( this, arguments );
|
|
}
|
|
|
|
OO.mfExtend( PointerOverlay, Overlay, {
|
|
className: 'overlay pointer-overlay tutorial-overlay',
|
|
isBorderBox: false,
|
|
fullScreen: false,
|
|
closeOnContentTap: true,
|
|
template: template.get( 'skins.minerva.newusers', 'PointerOverlay.hogan' ),
|
|
/**
|
|
* @cfg {object} defaults Default options hash.
|
|
* @cfg {string} defaults.isCompact whether the pointer overlay should be compact
|
|
* @cfg {number} defaults.timeout in milliseconds. If not zero the pointer overlay will
|
|
* hide after this duration of time.
|
|
* @cfg {string} defaults.isTutorial whether the pointer overlay contains tutorial like instructions
|
|
* @cfg {string} defaults.summary Message describing thing being pointed to.
|
|
* @cfg {string} defaults.cancelMsg Cancel message.
|
|
* @cfg {string} defaults.appendToElement Where pointer overlay should be appended to.
|
|
* @cfg {string} defaults.target jQuery selector to point tutorial at
|
|
* @cfg {string} [defaults.alignment] Determines where the pointer should point to. Valid values 'left' or 'center'
|
|
* @cfg {string} [defaults.confirmMsg] Label for a confirm message.
|
|
*/
|
|
defaults: $.extend( {}, Overlay.prototype.defaults, {
|
|
summary: undefined,
|
|
isCompact: false,
|
|
isTutorial: false,
|
|
timeout: 0,
|
|
cancelMsg: msg( 'minerva-pointer-dismiss' ),
|
|
appendToElement: undefined,
|
|
target: undefined,
|
|
alignment: 'center',
|
|
confirmMsg: undefined
|
|
} ),
|
|
events: {
|
|
'click .cancel': 'hide'
|
|
},
|
|
postRender: function () {
|
|
var $target,
|
|
self = this;
|
|
|
|
Overlay.prototype.postRender.apply( this );
|
|
|
|
if ( this.options.isCompact ) {
|
|
this.$el.addClass( 'pointer-overlay-compact' );
|
|
}
|
|
if ( this.options.isTutorial ) {
|
|
this.$el.addClass( 'pointer-overlay-tutorial' );
|
|
}
|
|
if ( this.options.timeout ) {
|
|
setTimeout( function () {
|
|
self.hide();
|
|
}, this.options.timeout );
|
|
}
|
|
if ( self.options.target ) {
|
|
// FIXME: this option should be a jQuery object already. Avoid use of global $.
|
|
$target = $( self.options.target );
|
|
// Ensure we position the overlay correctly but do not show the arrow
|
|
self._position( $target );
|
|
this.addPointerArrow( $target );
|
|
}
|
|
},
|
|
/**
|
|
* Refreshes the pointer arrow.
|
|
* @method
|
|
* @param {string} target jQuery selector
|
|
*/
|
|
refreshPointerArrow: function ( target ) {
|
|
this.$pointer.remove();
|
|
this.addPointerArrow( $( target ) );
|
|
},
|
|
/**
|
|
* Position the overlay under a specified element
|
|
* @private
|
|
* @param {JQuery.Object} $pa An element that should be pointed at by the overlay
|
|
*/
|
|
_position: function ( $pa ) {
|
|
var left,
|
|
paOffset = $pa.offset(),
|
|
h = $pa.outerHeight( true ),
|
|
y = paOffset.top + h;
|
|
|
|
this.$el.css( 'top', y );
|
|
if ( this.options.autoHide ) {
|
|
left = paOffset.left;
|
|
this.$el.css( 'left', left );
|
|
}
|
|
},
|
|
/**
|
|
* Position overlay and add pointer arrow that points at specified element
|
|
* @method
|
|
* @param {JQuery.Object} $pa An element that should be pointed at by the overlay
|
|
*/
|
|
addPointerArrow: function ( $pa ) {
|
|
var left,
|
|
paOffset = $pa.offset(),
|
|
overlayOffset = this.$el.offset(),
|
|
center = $pa.width() / 2;
|
|
|
|
this._position( $pa );
|
|
// add the entire width of the pointer
|
|
left = 24;
|
|
if ( !this.options.autoHide ) {
|
|
left += paOffset.left - overlayOffset.left;
|
|
}
|
|
if ( this.alignment === 'center' ) {
|
|
left -= center;
|
|
}
|
|
|
|
this.$pointer = $( '<div class="tutorial-pointer"></div>' ).css( {
|
|
top: -6,
|
|
left: left
|
|
} ).appendTo( this.$el );
|
|
|
|
// Since the positioning of this overlay is dependent on the current viewport it makes sense to
|
|
// use a global window event so that on resizes it is correctly positioned.
|
|
M.on(
|
|
'resize',
|
|
$.proxy( this, 'refreshPointerArrow', this.options.target )
|
|
);
|
|
}
|
|
} );
|
|
|
|
M.define( 'skins.minerva.newusers/PointerOverlay', PointerOverlay );
|
|
|
|
}( mw.mobileFrontend, jQuery ) );
|