Current File : /home/jvzmxxx/wiki1/extensions/MobileFrontend/resources/mobile.search.api/SearchGateway.js
( function ( M, $ ) {
	var Page = M.require( 'mobile.startup/Page' ),
		extendSearchParams = M.require( 'mobile.search.util/extendSearchParams' );

	/**
	 * @class SearchGateway
	 * @uses mw.Api
	 * @param {mw.Api} api
	 */
	function SearchGateway( api ) {
		this.api = api;
		this.searchCache = {};
		this.generator = mw.config.get( 'wgMFSearchGenerator' );
	}

	SearchGateway.prototype = {
		/**
		 * The namespace to search in.
		 * @type {number}
		 */
		searchNamespace: 0,

		/**
		 * Get the data used to do the search query api call.
		 * @method
		 * @param {string} query to search for
		 * @return {Object}
		 */
		getApiData: function ( query ) {
			var prefix = this.generator.prefix,
				data = extendSearchParams( 'search', {
					generator: this.generator.name
				} );

			data.redirects = '';

			data['g' + prefix + 'search'] = query;
			data['g' + prefix + 'namespace'] = this.searchNamespace;
			data['g' + prefix + 'limit'] = 15;

			// If PageImages is being used configure further.
			if ( data.pilimit ) {
				data.pilimit = 15;
				data.pithumbsize = mw.config.get( 'wgMFThumbnailSizes' ).tiny;
			}
			return data;
		},

		/**
		 * Escapes regular expression wildcards (metacharacters) by adding a \\ prefix
		 * @param {string} str a string
		 * @return {Object} a regular expression that can be used to search for that str
		 * @private
		 */
		_createSearchRegEx: function ( str ) {
			str = str.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&' );
			return new RegExp( '^(' + str + ')', 'ig' );
		},

		/**
		 * Takes a label potentially beginning with term
		 * and highlights term if it is present with strong
		 * @param {string} label a piece of text
		 * @param {string} term a string to search for from the start
		 * @return {string} safe html string with matched terms encapsulated in strong tags
		 * @private
		 */
		_highlightSearchTerm: function ( label, term ) {
			label = $( '<span>' ).text( label ).html();
			term = $( '<span>' ).text( term ).html();

			return label.replace( this._createSearchRegEx( term ), '<strong>$1</strong>' );
		},

		/**
		 * Return data used for creating {Page} objects
		 * @param {string} query to search for
		 * @param {Object} pageInfo from the API
		 * @return {Object} data needed to create a {Page}
		 * @private
		 */
		_getPage: function ( query, pageInfo ) {
			var page = Page.newFromJSON( pageInfo );

			// If displaytext is set in the generator result (eg. by Wikibase), use that as display title.
			// Otherwise default to the page's title.
			// FIXME: Given that displayTitle could have html in it be safe and just highlight text.
			// Note that highlightSearchTerm does full HTML escaping before highlighting.
			page.displayTitle = this._highlightSearchTerm(
				pageInfo.displaytext ? pageInfo.displaytext : page.title,
				query
			);
			page.index = pageInfo.index;

			return page;
		},

		/**
		 * Process the data returned by the api call.
		 * @param {string} query to search for
		 * @param {Object} data from api
		 * @return {Array}
		 * @private
		 */
		_processData: function ( query, data ) {
			var self = this,
				results = [];

			if ( data.query ) {

				results = data.query.pages || {};
				results = Object.keys( results ).map( function ( id ) {
					return self._getPage( query, results[ id ] );
				} );
				// sort in order of index
				results.sort( function ( a, b ) {
					return a.index < b.index ? -1 : 1;
				} );
			}

			return results;
		},

		/**
		 * Perform a search for the given query.
		 * @method
		 * @param {string} query to search for
		 * @return {jQuery.Deferred}
		 */
		search: function ( query ) {
			var result = $.Deferred(),
				request,
				self = this;

			if ( !this.isCached( query ) ) {
				request = this.api.get( this.getApiData( query ) )
					.done( function ( data ) {
						// resolve the Deferred object
						result.resolve( {
							query: query,
							results: self._processData( query, data )
						} );
					} )
					.fail( function () {
						// reset cached result, it maybe contains no value
						self.searchCache[query] = undefined;
						// reject
						result.reject();
					} );

				// cache the result to prevent the execution of one search query twice in one session
				this.searchCache[query] = result.promise( {
					abort: request.abort
				} );
			}

			return this.searchCache[query];
		},

		/**
		 * Check if the search has already been performed in given session.
		 * @method
		 * @param {string} query
		 * @return {boolean}
		 */
		isCached: function ( query ) {
			return Boolean( this.searchCache[ query ] );
		}
	};

	M.define( 'mobile.search.api/SearchGateway', SearchGateway );

}( mw.mobileFrontend, jQuery ) );