Current File : /home/jvzmxxx/wiki1/extensions/MobileFrontend/resources/mobile.browser/browser.js
( function ( M, $ ) {
	var browser;

	/**
	 * Memoize a class method. Caches the result of the method based on the
	 * arguments. Instances do not share a cache.
	 * @ignore
	 * @param {Function} method Method to be memoized
	 * @returns {Function}
	 */
	function memoize( method ) {
		/**
		 * Memoized version of the method
		 * @ignore
		 */
		var memoized = function () {
			var cache = this[ '__cache' + memoized.cacheId ] ||
				( this[ '__cache' + memoized.cacheId ] = {} ),
				key = [].join.call( arguments, '|' );
			if ( cache.hasOwnProperty( key ) ) {
				return cache[ key ];
			}
			return ( cache[ key ] = method.apply( this, arguments ) );
		};
		memoized.cacheId = Date.now().toString() + Math.random().toString();
		return memoized;
	}

	/**
	 * Representation of user's current browser
	 * @class Browser
	 * @param {String} ua the user agent of the current browser
	 * @param {jQuery.Object} $container an element to associate with the Browser object
	 */
	function Browser( ua, $container ) {
		this.userAgent  = ua;
		this.$el = $container;
		if ( this.isAndroid2() ) {
			this.lockViewport();
		}
		this._fixIosLandscapeBug();
	}

	Browser.prototype = {
		/**
		 * When rotating to landscape stop page zooming on ios 4 and 5.
		 * @private
		 */
		_fixIosLandscapeBug: function () {
			var self = this,
				viewport = this.$el.find( 'meta[name="viewport"]' )[0];

			// see http://adactio.com/journal/4470/ (fixed in ios 6)
			if ( viewport && ( this.isIos( 4 ) || this.isIos( 5 ) ) ) {
				this.lockViewport();
				document.addEventListener( 'gesturestart', function () {
					self.lockViewport();
				}, false );
			}
		},
		/**
		 * Returns whether the current browser is an ios device.
		 * FIXME: jquery.client does not support iPad detection so we cannot use it.
		 * @param {Number} [version] integer describing a specific version you want to test against.
		 * @return {Boolean}
		 */
		isIos: memoize( function ( version ) {
			var ua = this.userAgent,
				ios = /ipad|iphone|ipod/i.test( ua );

			if ( ios && version ) {
				switch ( version ) {
					case 8:
						// Test UA for iOS8. Or for simulator look for Version 8
						// In the iOS simulator the OS is the host machine OS version
						// This makes testing in iOS8 simulator work as expected
						return /OS 8_/.test( ua ) || /Version\/8/.test( ua );
					case 4:
						return /OS 4_/.test( ua );
					case 5:
						return /OS 5_/.test( ua );
					default:
						return false;
				}
			} else {
				return ios;
			}
		} ),
		/**
		 * Locks the viewport so that pinch zooming is disabled
		 */
		lockViewport: function () {
			if ( this.$el ) {
				this.$el.find( 'meta[name="viewport"]' )
					.attr( 'content', 'initial-scale=1.0, maximum-scale=1.0, user-scalable=no' );
			}
		},
		/**
		 * Determine if a device is Android 2.
		 * @method
		 * @return {Boolean}
		 */
		isAndroid2: memoize( function () {
			return /Android 2/.test( this.userAgent );
		} ),
		/**
		 * Determine if a device has a widescreen.
		 * @method
		 * @return {Boolean}
		 */
		isWideScreen: memoize( function () {
			var val = parseInt( mw.config.get( 'wgMFDeviceWidthTablet' ), 10 );
			// Check portrait and landscape mode to be consistent
			return window.innerWidth >= val || window.innerHeight >= val;
		} ),
		/**
		 * Checks browser support for a given CSS property
		 * @param {String} [property] the name of the property being tested
		 * @return {Boolean}
		 */
		supportsCSSProperty: memoize( function ( property ) {
			var elem = document.createElement( 'foo' );

			// We only test webkit because that's the only prefix needed at the moment by
			// supportsAnimations. If usage of supportsCSSProperty is expanded, the list of prefixes
			// will need to be as well
			return elem.style[ property ] !== undefined ||
				elem.style[ 'webkit' + property.charAt( 0 ).toUpperCase() + property.slice( 1 ) ] !== undefined;
		} ),
		/**
		 * Checks browser support for CSS transforms, transitions
		 * and CSS animation.
		 * Currently assumes support for the latter 2 in the case of the
		 * former.
		 * See http://stackoverflow.com/a/12621264/365238
		 *
		 * @returns {Boolean}
		 */
		supportsAnimations: memoize( function () {
			// don't trust Android 2.x, really
			// animations cause textareas to misbehave on it
			// (http://stackoverflow.com/a/5734984/365238)
			if ( this.isAndroid2() ) {
				return false;
			}

			return this.supportsCSSProperty( 'animationName' ) &&
				this.supportsCSSProperty( 'transform' ) &&
				this.supportsCSSProperty( 'transition' );
		} ),
		/**
		 * Whether touchstart and other touch events are supported by the current browser.
		 *
		 * @method
		 * @return {Boolean}
		 */
		supportsTouchEvents: memoize( function () {
			return 'ontouchstart' in window;
		} ),
		/**
		 * Detect if browser supports geolocation
		 * @method
		 * @return {Boolean}
		 */
		supportsGeoLocation: memoize( function () {
			return 'geolocation' in navigator;
		} ),
		/**
		 * Detect if we support file input uploads
		 * @return {Boolean}
		 */
		supportsFileUploads: memoize( function () {
			var browserSupported;
			// If already calculated, just return it
			if ( this._fileUploads !== undefined ) {
				return this._fileUploads;
			}

			// deal with known false positives which don't support file input (bug 47374)
			if ( this.userAgent.match( /Windows Phone (OS 7|8.0)/ ) ) {
				this._fileUploads = false;
			} else {
				browserSupported = (
					typeof FileReader !== 'undefined' &&
					typeof FormData !== 'undefined' &&
					// Firefox OS 1.0 turns <input type="file"> into <input type="text">
					( $( '<input type="file"/>' ).prop( 'type' ) === 'file' )
				);
				this._fileUploads = browserSupported &&
					!mw.config.get( 'wgImagesDisabled', false );
			}
			return this._fileUploads;
		} )
	};

	/**
	 * @static
	 * @returns {Browser}
	 */
	Browser.getSingleton = function () {
		if ( !browser ) {
			browser = new Browser( window.navigator.userAgent, $( 'html' ) );
		}
		return browser;
	};

	M.define( 'mobile.browser/Browser', Browser );
}( mw.mobileFrontend, jQuery ) );