wikimedia/mediawiki-extensions-MobileFrontend

View on GitHub
src/mobile.startup/icons.js

Summary

Maintainability
A
3 hrs
Test Coverage
const
    CANCEL_GLYPH = 'close',
    Icon = require( './Icon' ),
    IconButton = require( './IconButton' );

/**
 * A set of shared icons.
 *
 * Factory methods are used to keep separate features that use the same icons
 * from accidentally manipulating one another's DOM when calling methods like
 * `remove`.
 *
 * @class icons
 * @singleton
 * @uses Icon
 */
const icons = {
    CANCEL_GLYPH,
    // Exported to support testing and stubbing
    Icon,
    IconButton,
    /**
     * Gets a back icon
     *
     * The icon should be used to inform the user that the front-end is
     * communicating with the back-end.
     *
     * @memberof icons
     * @instance
     * @return {IconButton}
     */
    back() {
        return new icons.IconButton( {
            tagName: 'button',
            icon: 'previous',
            additionalClassNames: 'back',
            label: mw.msg( 'mobile-frontend-overlay-close' )
        } );
    },
    /**
     * Gets a cancel icon
     *
     * The icon should be used to inform the user that the front-end is
     * communicating with the back-end.
     *
     * @memberof icons
     * @instance
     * @param {string} [variant]
     * @param {Object} [props] to extend
     * @return {IconButton}
     */
    cancel( variant, props = {} ) {
        const glyph = variant ? `${ CANCEL_GLYPH }-${ variant }` : `${ CANCEL_GLYPH }`;
        props.additionalClassNames = props.additionalClassNames || '';
        props.additionalClassNames += ' cancel';

        return new icons.IconButton( Object.assign( {
            tagName: 'button',
            icon: glyph,
            label: mw.msg( 'mobile-frontend-overlay-close' )
        }, props ) );
    },
    /**
     * Gets a spinner icon. This uses IconButton but should never actually
     * be a button or have full button styles, as its purely presentational
     *
     * The icon should be used to inform the user that the front-end is
     * communicating with the back-end.
     *
     * @memberof icons
     * @instance
     * @param {Object} [props] See `Icon` for more details
     * @return {IconButton}
     */
    spinner( props = {} ) {
        if ( props.additionalClassNames === undefined ) {
            props.additionalClassNames = 'spinner loading';
        }

        const spinner = new icons.IconButton( Object.assign( {
            tagName: 'span',
            icon: 'spinner',
            label: mw.msg( 'mobile-frontend-loading-message' )
        }, props ) );

        // Update the element to not use button classes or attributes
        spinner.$el.removeClass();
        // eslint-disable-next-line mediawiki/class-doc
        spinner.$el.addClass( props.additionalClassNames );
        spinner.$el.attr( 'type', '' );
        if ( spinner.options.isIconOnly ) {
            spinner.$el.addClass( 'mf-spinner-icon-element' );
        }
        return spinner;
    },
    /**
     * Gets a failure (error) icon
     *
     * @memberof icons
     * @instance
     * @return {IconButton}
     */
    error() {
        return new icons.IconButton( {
            icon: 'alert-invert',
            additionalClassNames: 'load-fail-msg-icon'
        } );
    },
    /**
     * Gets a non-filled watch star icon.
     *
     * @memberof icons
     * @instance
     * @param {Object} props
     * @return {IconButton}
     */
    watch( props = {} ) {
        props.additionalClassNames = props.additionalClassNames || '';
        props.additionalClassNames += ' watch-this-article';

        return new icons.IconButton( Object.assign( {
            icon: 'star-subtle'
        }, props ) );
    },
    /**
     * Gets a filled watch star icon.
     *
     * @memberof icons
     * @instance
     * @param {Object} props
     * @return {IconButton}
     */
    watched( props = {} ) {
        props.additionalClassNames = props.additionalClassNames || '';
        props.additionalClassNames += ' watch-this-article watched';

        return new icons.IconButton( Object.assign( {
            icon: 'unStar-progressive'
        }, props ) );
    }
};

module.exports = icons;