aboutsummaryrefslogtreecommitdiffstats
path: root/resources/src/jquery.spinner/spinner.js
blob: 843c94e48773774d856122379479469e6f3d2bf2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
 * Provides a {@link jQuery} plugins that manage spinners.
 *
 * To use these jQuery plugins, load the `jquery.spinner` module with {@link mw.loader}.
 *
 * @example
 * mw.loader.using( 'jquery.spinner' ).then( () => {
 *       $( '#bodyContent' ).injectSpinner();
 * } );
 *
 * @module jquery.spinner
 */
( function () {

	/**
	 * Default options for new spinners,
	 * stored outside the function to share between calls.
	 *
	 * @type {module:jquery.spinner~SpinnerOpts}
	 */
	const defaults = {
		id: undefined,
		size: 'small',
		type: 'inline'
	};

	/**
	 * @typedef {Object} module:jquery.spinner~SpinnerOpts Options for {@link module:jquery.spinner.$.fn.injectSpinner injectSpinner}.
	 * @property {string} [id] If given, spinner will be given an id of "mw-spinner-{id}".
	 * @property {'small'|'large'} [size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
	 * @property {'inline'|'block'} [type='inline'] 'inline' or 'block'. Inline creates an inline-block with
	 *   width and height equal to spinner size. Block is a block-level element with width 100%,
	 *   height equal to spinner size.
	 */

	$.extend( {
		/**
		 * Create a spinner element
		 *
		 * The argument is an object with options used to construct the spinner (see below).
		 *
		 * It is a good practice to keep a reference to the created spinner to be able to remove it later.
		 * Alternatively, one can use the 'id' option and {@link module:jquery.spinner.removeSpinner removeSpinner}
		 * (but make sure to choose an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
		 *
		 * CSS classes used:
		 *
		 * - .mw-spinner for every spinner
		 * - .mw-spinner-small / .mw-spinner-large for size
		 * - .mw-spinner-block / .mw-spinner-inline for display types
		 *
		 * @example
		 * // Create a large spinner reserving all available horizontal space.
		 * const $spinner = $.createSpinner( { size: 'large', type: 'block' } );
		 * // Insert above page content.
		 * $( '#mw-content-text' ).prepend( $spinner );
		 *
		 * // Place a small inline spinner next to the "Save" button
		 * const $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
		 * // Alternatively, just `$.createSpinner();` as these are the default options.
		 * $( '#wpSave' ).after( $spinner );
		 *
		 * // The following two are equivalent:
		 * $.createSpinner( 'magic' );
		 * $.createSpinner( { id: 'magic' } );
		 *
		 * @memberof module:jquery.spinner
		 * @static
		 * @inheritable
		 * @param {module:jquery.spinner~SpinnerOpts|string} [opts] Options. If a string is given, it will be treated as the value
		 *   of the {@link module:mediawiki.jqueryMsg~SpinnerOpts#id} option.
		 * @return {jQuery}
		 */
		createSpinner: ( opts ) => {
			if ( typeof opts === 'string' ) {
				opts = {
					id: opts
				};
			}

			opts = Object.assign( {}, defaults, opts );

			const $spinner = $( '<div>' ).addClass( 'mw-spinner' );
			if ( opts.id !== undefined ) {
				$spinner.attr( 'id', 'mw-spinner-' + opts.id );
			}

			$spinner
				.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' )
				.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );

			const $container = $( '<div>' ).addClass( 'mw-spinner-container' ).appendTo( $spinner );
			for ( let i = 0; i < 12; i++ ) {
				$container.append( $( '<div>' ) );
			}

			return $spinner;
		},

		/**
		 * Remove a spinner element
		 *
		 * @memberof module:jquery.spinner
		 * @inheritable
		 * @param {string} id Id of the spinner, as passed to {@link module:jquery.spinner.createSpinner createSpinner}
		 * @return {jQuery} The (now detached) spinner element
		 */
		removeSpinner: ( id ) => $( '#mw-spinner-' + id ).remove()
	} );

	/**
	 * Inject a spinner after each element in the collection.
	 *
	 * Inserts spinner as siblings (not children) of the target elements.
	 * Collection contents remain unchanged.
	 *
	 * @memberof module:jquery.spinner
	 * @param {module:jquery.spinner~SpinnerOpts|string} [opts] Options. If a string is given, it will be treated as the value
	 *   of the {@link module:jquery.spinner~SpinnerOpts SpinnerOpts id} option.
	 * @return {jQuery}
	 */
	$.fn.injectSpinner = function ( opts ) {
		return this.after( $.createSpinner( opts ) );
	};

	/**
	 * @class jQuery
	 * @mixes jQuery.plugin.spinner
	 */

}() );