User:Novusistic/API-Demo-using-OOUI.js

From mediawiki.org

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
$( document ).ready( function () {
	mw.loader.using( 'oojs-ui-core' ).done( function () {
		var str = '',
			count1 = 0,
			count2 = 0;

		// A custom widget which facilitates the searching of "recently added articles"
		// And "nearby pages" as per the user's location using MediaWiki Action API.
		var CustomWidget = function ( config ) {
			config = config || {};

			CustomWidget.parent.call( this, config );

			this.label1 = new OO.ui.LabelWidget( {
				label: 'Get the articles most recently added to a category.'
			} );

			this.label2 = new OO.ui.LabelWidget( {
				label: 'Search for pages nearby.'
			} );

			this.button1 = new OO.ui.ButtonWidget( {
				label: 'Click here',
				flags: [ 'primary', 'progressive' ]
			} );

			this.button2 = new OO.ui.ButtonWidget( {
				label: 'Click here',
				flags: [ 'primary', 'progressive' ]
			} );

			this.button1.connect( this, { click: 'btnClick1' } );
			this.button2.connect( this, { click: 'btnClick2' } );

			// NOTE: Ideally, the styling of DOM elements should be done in a separate
			// Css/less file. Thus, the following embedded CSS is for demonstration
			// Purpose only.
			this.$element.append(
				this.label1.$element
					.css( { display: 'block' } ),
				this.button1.$element
					.css( { margin: '5px 0 20px 0' } ),
				this.label2.$element
					.css( { display: 'block' } ),
				this.button2.$element
					.css( { margin: '5px 0 20px 0' } )
			);
		};

		OO.inheritClass( CustomWidget, OO.ui.Widget );

		// Defines the behaviour of the application on clicking the first button.
		CustomWidget.prototype.btnClick1 = function () {
			count1++;

			// This ensures that in case the top button is clicked for the first time,
			// An input field and a back button is generated. The obvious behaviour that
			// If the top button is clicked continuously, it shouldn't lead to the
			// Creation of new input field again, is also defined.
			if ( count1 === 1 ) {
				this.button2.setDisabled( true );

				this.input = new OO.ui.SearchInputWidget( {
					placeholder: 'Enter category here...',
					classes: [ 'input-field' ]
				} );

				this.result = new OO.ui.LabelWidget( {
					classes: [ 'result' ]
				} );

				this.backButton = new OO.ui.ButtonWidget( {
					label: 'Go back',
					flags: [ 'progressive' ],
					classes: [ 'backBtn' ]
				} );

				this.input.connect( this, { enter: 'searchRecentlyAddedArticles' } );
				this.backButton.connect( this, { click: 'backBtnClick' } );

				this.$element.append(
					this.input.$element,
					this.result.$element
						.css( {
							display: 'block',
							margin: '10px 0',
							padding: '15px',
							backgroundColor: '#addfad',
							borderRadius: '10px'
						} ),
					this.backButton.$element
				);
			}
		};

		/**
		 * Fetches the response of the MediaWiki Action API containing the recently
		 * Added articles in the specified category.
		 *
		 * This method uses the Query module of the API to fetch the desired page details
		 * In the JSON format. The default number of return entries is 10. If the response
		 * Is empty, the corresponding message is shown to the user, else the titles
		 * Of the 10 recently added articles are shown.
		 *
		 * @return 10 recently added articles in a specified category
		 */
		CustomWidget.prototype.searchRecentlyAddedArticles = function () {
			var myCategory = this.input.getValue();

			if ( myCategory !== '' ) {
				var url = 'https://en.wikipedia.org/w/api.php';
				var params = {
					action: 'query',
					list: 'categorymembers',
					cmtitle: 'Category:' + myCategory,
					cmsort: 'timestamp',
					cmdir: 'desc',
					format: 'json'
				};

				url = url + '?origin=*';
				Object.keys( params ).forEach( function ( key ) {
					url += '&' + key + '=' + params[ key ];
				} );

				fetch( url )
					.then( function ( response ) {
						return response.json();
					} )
					.then( function ( response ) {
						var pages = response.query.categorymembers;
						if ( pages.length === 0 ) {
							myCustomWidget.result.setLabel( 'No result found!' );
						} else {
							str = '';
							for ( var page in pages ) {
								str += pages[ page ].title + ' || ';
							}
							myCustomWidget.result.setLabel( str );
						}
					} )
					.catch( function ( error ) {
						console.log( error );
					} );
			}
			this.input.setValue( '' );
		};

		/**
		 * Fetches the response of the MediaWiki Action API containing the pages
		 * Nearby the user location.
		 *
		 * This method uses the Query module of the API to fetch the pages nearby the
		 * User's location in the JSON format. The number of return entries is 10.
		 * The hard coded location below is of Mumbai.
		 *
		 * @return 10 wikipedia pages (if they exist) near the location specified below.
		 */
		CustomWidget.prototype.btnClick2 = function () {
			count2++;
			if ( count2 === 1 ) {
				this.button1.setDisabled( true );

				var url = 'https://en.wikipedia.org/w/api.php';

				var params = {
					action: 'query',
					list: 'geosearch',
					// Latitude and Longitude of Mumbai
					gscoord: '19.075984|72.877656',
					gsradius: '10000',
					gslimit: '10',
					format: 'json'
				};

				url = url + '?origin=*';
				Object.keys( params ).forEach( function ( key ) {
					url += '&' + key + '=' + params[ key ];
				} );

				fetch( url )
					.then( function ( response ) {
						return response.json();
					} )
					.then( function ( response ) {
						var pages = response.query.geosearch;
						str = '';
						for ( var place in pages ) {
							str += pages[ place ].title + ' || ';
						}
						myCustomWidget.result.setLabel( str );
					} )
					.catch( function ( error ) {
						console.log( error );
					} );

				this.result = new OO.ui.LabelWidget( {
					classes: [ 'result' ]
				} );

				this.backButton = new OO.ui.ButtonWidget( {
					label: 'Go back',
					flags: [ 'progressive' ],
					classes: [ 'backBtn' ]
				} );

				this.backButton.connect( this, { click: 'backBtnClick' } );

				this.$element.append(
					this.result.$element
						.css( {
							display: 'block',
							margin: '10px 0',
							padding: '15px',
							backgroundColor: '#addfad',
							borderRadius: '10px'
						} ),
					this.backButton.$element
				);
			}
		};

		// Defines the action/behaviour when the back button is clicked.
		CustomWidget.prototype.backBtnClick = function () {
			this.button1.setDisabled( false );
			this.button2.setDisabled( false );

			$( '.input-field' ).remove();
			$( '.result' ).remove();
			$( '.backBtn' ).remove();

			count1 = 0;
			count2 = 0;
		};

		// The following creates a custom widget and a pop up button object.
		var myCustomWidget = new CustomWidget();

		var myPopUpButton = new OO.ui.PopupButtonWidget( {
			label: 'API operations',
			popup: {
				$content: myCustomWidget.$element,
				padded: true
			}
		} );

		// Shows the pop up button on the personal navigation bar of the user at the
		// Top right corner.
		$( '#p-personal ul' )
			.append( $( '<li>' ).append( myPopUpButton.$element ) );
	} );
} );