mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/MinervaNeue
synced 2024-11-15 10:27:31 +00:00
864a1766a7
This patch refactors the markup and JS associated with the page actions menu in order to achieve greater flexibility in its presentation. The menu items are now positioned via flexbox and rendered using a mustache template in PHP. The goal of this refactor is to accommodate both AMC mode and default mode with the same markup. No changes should be visible for non-AMC users with this refactor. No changes to AMC mode have been made in this patch either. This patch includes temporary workarounds to avoid problems caused by HTML caching. Changes include: - Changing the data structure of the page_actions property in SkinMinerva.php - Passing that modified data structure into a new mustache template, PageActionMenu.mustache - Adding new CSS for the new page actions menu HTML - changing the query selectors in JS to match the new markup - Making the JS-modified page-actions compatible with the new markup - Keeping existing CSS and JS to avoid breaking cached HTML Bug: T213352 Depends-On: I95cf726c4b6d8c3895a26aa6e07f4b1747ee30fe Change-Id: I5a7d73b20617cb3c6d6379084ac4bea23ec3bc74
164 lines
4.9 KiB
JavaScript
164 lines
4.9 KiB
JavaScript
( function ( M, track, msg ) {
|
|
var MAX_PRINT_TIMEOUT = 3000,
|
|
mobile = M.require( 'mobile.startup' ),
|
|
Icon = mobile.Icon,
|
|
icons = mobile.icons,
|
|
lazyImageLoader = mobile.lazyImages.lazyImageLoader,
|
|
browser = mobile.Browser.getSingleton(),
|
|
GLYPH = 'download';
|
|
|
|
/**
|
|
* Helper function to retrieve the Android version
|
|
* @ignore
|
|
* @param {string} userAgent User Agent
|
|
* @return {number|false} An integer.
|
|
*/
|
|
function getAndroidVersion( userAgent ) {
|
|
var match = userAgent.toLowerCase().match( /android\s(\d\.]*)/ );
|
|
return match ? parseInt( match[ 1 ] ) : false;
|
|
}
|
|
|
|
/**
|
|
* Helper function to retrieve the Chrome/Chromium version
|
|
* @ignore
|
|
* @param {string} userAgent User Agent
|
|
* @return {number|false} An integer.
|
|
*/
|
|
function getChromeVersion( userAgent ) {
|
|
var match = userAgent.toLowerCase().match( /chrom(e|ium)\/(\d+)\./ );
|
|
return match ? parseInt( match[ 2 ] ) : false;
|
|
}
|
|
|
|
/**
|
|
* Checks whether DownloadIcon is available for given user agent
|
|
*
|
|
* @memberof DownloadIcon
|
|
* @instance
|
|
* @param {Window} windowObj
|
|
* @param {Page} page to download
|
|
* @param {string} userAgent User agent
|
|
* @param {number[]} supportedNamespaces where printing is possible
|
|
* @return {boolean}
|
|
*/
|
|
function isAvailable( windowObj, page, userAgent, supportedNamespaces ) {
|
|
var androidVersion = getAndroidVersion( userAgent ),
|
|
chromeVersion = getChromeVersion( userAgent );
|
|
|
|
// Download button is restricted to certain namespaces T181152.
|
|
// Defaults to 0, in case cached JS has been served.
|
|
if ( supportedNamespaces.indexOf( page.getNamespaceId() ) === -1 ||
|
|
page.isMainPage() ) {
|
|
// namespace is not supported or it's a main page
|
|
return false;
|
|
}
|
|
|
|
if ( browser.isIos() || chromeVersion === false ||
|
|
windowObj.chrome === undefined
|
|
) {
|
|
// we support only chrome/chromium on desktop/android
|
|
return false;
|
|
}
|
|
if ( ( androidVersion && androidVersion < 5 ) || chromeVersion < 41 ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* onClick handler for button that invokes print function
|
|
* @param {Skin} skin
|
|
* @param {Icon} icon
|
|
* @param {Icon} spinner
|
|
*/
|
|
function onClick( skin, icon, spinner ) {
|
|
function doPrint() {
|
|
icon.timeout = clearTimeout( icon.timeout );
|
|
track( 'minerva.downloadAsPDF', {
|
|
action: 'callPrint'
|
|
} );
|
|
window.print();
|
|
icon.$el.show();
|
|
spinner.$el.hide();
|
|
}
|
|
|
|
function doPrintBeforeTimeout() {
|
|
if ( icon.timeout ) {
|
|
doPrint();
|
|
}
|
|
}
|
|
// The click handler may be invoked multiple times so if a pending print is occurring
|
|
// do nothing.
|
|
if ( !icon.timeout ) {
|
|
track( 'minerva.downloadAsPDF', {
|
|
action: 'fetchImages'
|
|
} );
|
|
icon.$el.hide();
|
|
spinner.$el.show();
|
|
// If all image downloads are taking longer to load then the MAX_PRINT_TIMEOUT
|
|
// abort the spinner and print regardless.
|
|
icon.timeout = setTimeout( doPrint, MAX_PRINT_TIMEOUT );
|
|
lazyImageLoader.loadImages( lazyImageLoader.queryPlaceholders( document.getElementById( 'content' ) ) )
|
|
.then( doPrintBeforeTimeout, doPrintBeforeTimeout );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets a click handler for the download icon
|
|
* Expects to be run in the context of an icon using `Function.bind`
|
|
*
|
|
* @param {Skin} skin
|
|
* @param {Icon} spinner
|
|
* @returns {function}
|
|
*/
|
|
function getOnClickHandler( skin, spinner ) {
|
|
return function () {
|
|
onClick( skin, this, spinner );
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generate a download icon for triggering print functionality if
|
|
* printing is available
|
|
*
|
|
* @param {Skin} skin
|
|
* @param {number[]} supportedNamespaces
|
|
* @param {Window} [windowObj] window object
|
|
* @returns {jQuery.Object|null}
|
|
*/
|
|
function downloadPageAction( skin, supportedNamespaces, windowObj ) {
|
|
var icon, spinner = icons.spinner(),
|
|
// TODO: T213352 Temporary cache compatibility - to be deleted.
|
|
// Any conditionals using this boolean should be DELETED when the
|
|
// old page action menu is no longer being served to users.
|
|
// eslint-disable-next-line jquery/no-global-selector
|
|
oldPageActionsDOM = $( '#page-actions.hlist' ).length > 0;
|
|
if (
|
|
isAvailable(
|
|
windowObj, skin.page, navigator.userAgent,
|
|
supportedNamespaces
|
|
)
|
|
) {
|
|
icon = new Icon( {
|
|
glyphPrefix: 'minerva',
|
|
title: msg( 'minerva-download' ),
|
|
name: GLYPH,
|
|
tagName: oldPageActionsDOM ? 'div' : 'button',
|
|
events: {
|
|
// will be bound to `this`
|
|
click: getOnClickHandler( skin, spinner )
|
|
}
|
|
} );
|
|
if ( oldPageActionsDOM ) {
|
|
return $( '<li>' ).append( icon.$el ).append( spinner.$el.hide() );
|
|
} else {
|
|
return $( '<li>' ).addClass( 'page-actions-menu__list-item' ).append( icon.$el ).append( spinner.$el.hide() );
|
|
}
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
M.define( 'skins.minerva.scripts/test/getOnClickHandler', getOnClickHandler );
|
|
M.define( 'skins.minerva.scripts/test/isAvailable', isAvailable );
|
|
M.define( 'skins.minerva.scripts/downloadPageAction', downloadPageAction );
|
|
}( mw.mobileFrontend, mw.track, mw.msg ) );
|