Current File : /home/jvzmxxx/wiki1/extensions/MobileFrontend/resources/mobile.startup/Page.js
( function ( HTML, M, $ ) {

	var time = M.require( 'mobile.startup/time' ),
		View = M.require( 'mobile.startup/View' ),
		Section = M.require( 'mobile.startup/Section' ),
		Thumbnail = M.require( 'mobile.startup/Thumbnail' );

	/**
	 * Mobile page view object
	 *
	 * @class Page
	 * @uses Section
	 * @extends View
	 *
	 * @constructor
	 * @param {Object} options Configuration options
	 */
	function Page( options ) {
		var thumb;
		this.options = options;
		options.languageUrl = mw.util.getUrl( 'Special:MobileLanguages/' + options.title );
		View.call( this, options );
		// Fallback if no displayTitle provided
		options.displayTitle = this.getDisplayTitle();
		// allow usage in templates.
		// FIXME: Should View map all options to properties?
		this.title = options.title;
		this.displayTitle = options.displayTitle;
		this.thumbnail = options.thumbnail;
		this.url = options.url || mw.util.getUrl( options.title );
		this.id = options.id;
		this.isMissing = options.isMissing;
		thumb = this.thumbnail;
		if ( thumb && thumb.width ) {
			this.thumbnail.isLandscape = thumb.width > thumb.height;
		}
		this.wikidataDescription = options.wikidataDescription;
	}

	OO.mfExtend( Page, View, {
		/**
		 * @cfg {Object} defaults Default options hash.
		 * @cfg {number} defaults.id Page ID. The default value of 0 represents a new page.
		 * Be sure to override it to avoid side effects.
		 * @cfg {string} defaults.title Title of the page. It includes prefix where needed and
		 * is human readable, e.g. Talk:The man who lived.
		 * @cfg {string} defaults.displayTitle HTML title of the page for display. Falls back
		 * to defaults.title (escaped) if no value is provided. Must be safe HTML!
		 * @cfg {number} defaults.namespaceNumber the number of the namespace the page belongs to
		 * @cfg {Object} defaults.protection List of permissions as returned by API,
		 * e.g. [{ edit: ['*'] }]
		 * @cfg {Array} defaults.sections Array of {Section} objects.
		 * @cfg {boolean} defaults.isMainPage Whether the page is the Main Page.
		 * @cfg {boolean} defaults.isMissing Whether the page exists in the wiki.
		 * @cfg {string} defaults.hash Window location hash.
		 * @cfg {Object} defaults.thumbnail thumbnail definition corresponding to page image
		 * @cfg {boolean} defaults.thumbnail.isLandscape whether the image is in landscape format
		 * @cfg {number} defaults.thumbnail.width of image in pixels.
		 * @cfg {number} defaults.thumbnail.height of image in pixels.
		 * @cfg {string} defaults.thumbnail.source url for image
		 */
		defaults: {
			id: 0,
			title: '',
			displayTitle: '',
			namespaceNumber: 0,
			protection: {
				edit: [ '*' ]
			},
			sections: [],
			isMissing: false,
			isMainPage: false,
			hash: window.location.hash,
			url: undefined,
			thumbnail: {
				isLandscape: undefined,
				source: undefined,
				width: undefined,
				height: undefined
			}
		},
		/**
		 * @inheritdoc
		 */
		isBorderBox: false,
		/**
		 * Retrieve the title that should be displayed to the user
		 * @method
		 * @return {string} HTML
		 */
		getDisplayTitle: function () {
			return this.options.displayTitle || HTML.escape( this.options.title );
		},
		/**
		 * Determine if current page is in a specified namespace
		 * @method
		 * @param {string} namespace Name of namespace
		 * @return {boolean}
		 */
		inNamespace: function ( namespace ) {
			return this.options.namespaceNumber === mw.config.get( 'wgNamespaceIds' )[namespace];
		},

		/**
		 * Get the lead section of the page view.
		 * @method
		 * @return {jQuery.Object|null}
		 */
		getLeadSectionElement: function () {
			/*
			 * The page is formatted as follows:
			 * <div id="bodyContent">
			 *   <!-- content of the page.. -->
			 *   <div id="mw-content-text">
			 *     <div class="mf-section-0">lead section</div>
			 *     <h2></h2>
			 *     <div class="mf-section-1">second section</div>
			 *   </div>
			 * </div>
			 */
			if ( $( '.mf-section-0' ).length ) {
				return $( '.mf-section-0' );
			}
			// for cached pages that are still using mw-mobilefrontend-leadsection
			if ( $( '.mw-mobilefrontend-leadsection' ).length ) {
				return $( '.mw-mobilefrontend-leadsection' );
			}
			// no lead section found
			return null;
		},

		/**
		 * Determines if content model is wikitext
		 * @method
		 * @return {boolean}
		 */
		isWikiText: function () {
			return mw.config.get( 'wgPageContentModel' ) === 'wikitext';
		},

		/**
		 * Checks whether the current page is the main page
		 * @method
		 * @return {boolean}
		 */
		isMainPage: function () {
			return this.options.isMainPage;
		},
		/**
		 * Checks whether the current page is watched
		 * @method
		 * @return {boolean}
		 */
		isWatched: function () {
			return this.options.isWatched;
		},

		/**
		 * Return the latest revision id for this page
		 * @method
		 * @return {number}
		 */
		getRevisionId: function () {
			return this.options.revId;
		},

		/**
		 * Return prefixed page title
		 * @method
		 * @return {string}
		 */
		getTitle: function () {
			return this.options.title;
		},

		/**
		 * Return page id
		 * @method
		 * @return {number}
		 */
		getId: function () {
			return this.options.id;
		},

		/**
		 * return namespace id
		 * @method
		 * @return {number} namespace Number
		 */
		getNamespaceId: function () {
			var nsId,
				args = this.options.title.split( ':' );

			if ( args[1] ) {
				nsId = mw.config.get( 'wgNamespaceIds' )[ args[0].toLowerCase().replace( ' ', '_' ) ] || 0;
			} else {
				nsId = 0;
			}
			return nsId;
		},

		/**
		 * Determines if current page is a talk page
		 * @method
		 * @return {boolean} Whether the page is a talk page or not
		 */
		isTalkPage: function () {
			var ns = this.getNamespaceId();
			// all talk pages are odd Numbers (except the case of special pages)
			return ns > 0 && ns % 2 === 1;
		},

		/**
		 * @inheritdoc
		 */
		preRender: function () {
			this.sections = [];
			this._sectionLookup = {};
			this.title = this.options.title;

			this.options.sections.forEach( function ( sectionData ) {
				var section = new Section( sectionData );
				this.sections.push( section );
				this._sectionLookup[section.id] = section;
			}.bind( this ) );
		},

		/**
		 * @inheritdoc
		 */
		postRender: function () {
			var self = this;
			// Restore anchor position after everything on page has been loaded.
			// Otherwise, images that load after a while will push the anchor
			// from the top of the viewport.
			if ( this.options.hash ) {
				$( window ).on( 'load', function () {
					window.location.hash = self.options.hash;
				} );
			}
		},

		/**
		 * Return all the thumbnails in the article
		 * @method
		 * @return {Thumbnail[]}
		 */
		getThumbnails: function () {
			var thumbs = [];

			if ( !this._thumbs ) {
				this.$el.find( 'a.image, a.thumbimage' ).each( function () {
					var $a = $( this ),
						legacyMatch = $a.attr( 'href' ).match( /title=([^\/&]+)/ ),
						match = $a.attr( 'href' ).match( /[^\/]+$/ );

					if ( legacyMatch || match ) {
						thumbs.push(
							new Thumbnail( {
								el: $a,
								filename: decodeURIComponent( legacyMatch ? legacyMatch[1] : match[0] )
							} )
						);
					}
				} );
				this._thumbs = thumbs;
			}
			return this._thumbs;
		},

		/**
		 * FIXME: Change function signature to take the anchor of the heading
		 * @method
		 * @param {string} id of the section
		 * @return {Section}
		 */
		getSection: function ( id ) {
			return this._sectionLookup[ id ];
		},

		/**
		 * @method
		 * @return {Array}
		 */
		getSections: function () {
			return this.sections;
		},

		/**
		 * Returns a jQuery object representing all redlinks on the page.
		 * @return {jQuery.Object}
		 */
		getRedLinks: function () {
			return this.$( '.new' );
		}
	} );

	/**
	 * Create a Page object from an API response.
	 *
	 * @static
	 * @param {Object} resp as representing a page in the API
	 * @return {Page}
	 */
	Page.newFromJSON = function ( resp ) {
		var revision, displayTitle,
			thumb = resp.thumbnail,
			pageprops = resp.pageprops || {
				displaytitle: HTML.escape( resp.title )
			},
			terms = resp.terms;

		if ( pageprops || terms ) {
			// The label is either the display title or the label pageprop (the latter used by Wikidata)
			// Long term we want to consolidate these. Note that pageprops.displaytitle is HTML, while
			// terms.label[0] is plain text.
			displayTitle = terms && terms.label ? HTML.escape( terms.label[0] ) : pageprops.displaytitle;
		}
		// Add Wikidata descriptions if available (T101719)
		if ( terms && terms.description && terms.description.length ) {
			resp.wikidataDescription = terms.description[0];
		}

		if ( thumb ) {
			resp.thumbnail.isLandscape = thumb.width > thumb.height;
		}

		// page may or may not exist.
		if ( resp.revisions && resp.revisions[0] ) {
			revision = resp.revisions[0];
			resp.lastModified = time.getLastModifiedMessage( new Date( revision.timestamp ).getTime() / 1000,
				revision.user );
		}

		return new Page(
			$.extend( resp, {
				id: resp.pageid,
				isMissing: !!resp.missing,
				url: mw.util.getUrl( resp.title ),
				displayTitle: displayTitle // this is HTML!
			} )
		);
	};
	M.define( 'mobile.startup/Page', Page );

}( mw.html, mw.mobileFrontend, jQuery ) );