File: src/device/Orientation.js
/**
* license inazumatv.com
* author (at)taikiken / http://inazumatv.com
* date 2015/04/10 - 19:33
*
* Copyright (c) 2011-2015 inazumatv.com, inc.
*
* Distributed under the terms of the MIT license.
* http://www.opensource.org/licenses/mit-license.html
*
* This notice shall be included in all copies or substantial portions of the Software.
*
*/
/**
* orientation 監視
*
* @module Sagen
* @submodule Orientation
* */
( function ( window ){
'use strict';
var
document = window.document,
Sagen = window.Sagen;
Sagen.Orientation = ( function (){
var
EventDispatcher = Sagen.EventDispatcher,
Browser = Sagen.Browser,
Css3 = Browser.Css3,
iOS = Browser.iOS,
Android = Browser.Android,
_abs = Math.abs,
_int = parseInt,
/**
* @property _orientation
* @static
* @type {boolean}
* @private
*/
_orientation,
/**
* @property _eventType
* @static
* @type {string}
* @private
*/
_eventType,
/**
* @property _handler
* @static
* @type {Function}
* @private
*/
_handler,
/**
* @property _mediaQuery
* @static
* @type {MediaQueryList}
* @private
*/
_mediaQuery,
_start;
/**
* portrait / landscape 切替を監視
* @class Orientation
* @uses EventDispatcher
* @static
* @constructor
*/
function Orientation () {
throw new Error( 'Orientation can\'t create instance.' );
}
var p = Orientation.prototype;
p.constructor = Orientation;
/**
* @event CHANGE_ORIENTATION
* @static
* @type {string}
*/
Orientation.CHANGE_ORIENTATION = 'changeOrientation';
EventDispatcher.initialize( Orientation );
/**
* @method init
* @static
*/
Orientation.init = function () {
Orientation.listen().fire();
};
/**
* @method canOrientation
* @static
* @return {boolean}
*/
Orientation.canOrientation = function () {
if ( typeof _orientation === 'undefined' ) {
_orientation = Css3.orientation();
}
return _orientation;
};
/**
* @method eventType
* @static
* @return {string}
*/
Orientation.eventType = function () {
if ( typeof _eventType === 'undefined' ) {
_eventType = Css3.orientationChange() ? 'orientationchange' : 'resize';
}
return _eventType;
};
/**
* Orientation.CHANGE_ORIENTATIONをdispatchし directionを "portrait" にします
* @method portrait
* @static
*/
Orientation.portrait = function () {
Orientation.dispatchEvent( { type: Orientation.CHANGE_ORIENTATION, direction: 'portrait', scope: Orientation } );
};
/**
* Orientation.CHANGE_ORIENTATIONをdispatchし directionを "landscape" にします
* @method landscape
* @static
*/
Orientation.landscape = function () {
Orientation.dispatchEvent( { type: Orientation.CHANGE_ORIENTATION, direction: 'landscape', scope: Orientation } );
};
/**
* @method listen
* @static
* @return {Orientation}
*/
Orientation.listen = function () {
var
handler;
if ( !_start ) {
_start = true;
if ( typeof window.addEventListener !== 'undefined' ) {
if ( Css3.matchMedia() ) {
// can use matchMedia
//handler = Orientation._listenMatchMedia;
Orientation._listenMatchMedia();
} else {
// matchMediaが使えないので代わりに window.orientationあるいは window 縦横比を使い判定します
handler = Orientation._listenOrientation;
_handler = handler;
window.addEventListener( Orientation.eventType(), handler, false );
}
}
}
return Orientation;
};
/**
* @method abort
* @static
*/
Orientation.abort = function () {
if ( !!_handler && typeof window.addEventListener !== 'undefined' ) {
window.removeEventListener( Orientation.eventType(), _handler );
}
};
/**
* イベントを強制的に発火させます
* @method fire
* @static
*/
Orientation.fire = function () {
if ( !!_handler ) {
_handler();
} else if ( !!_mediaQuery ) {
Orientation._onRotate( _mediaQuery );
}
};
/**
* @method _listenOrientation
* @static
* @private
*/
Orientation._listenOrientation = function () {
if ( Orientation.canOrientation() ) {
// window.orientation が使える
// degree check
if ( Orientation._checkDegree() ) {
// portrait
Orientation.portrait();
} else {
Orientation.landscape();
}
} else {
// window 幅,高さを使う
// aspect check
if ( Orientation._checkAspect() ) {
// portrait
Orientation.portrait();
} else {
Orientation.landscape();
}
}
};
/**
* @method _checkDegree
* @static
* @return {boolean}
* @private
*/
Orientation._checkDegree = function () {
return _abs( window.orientation ) !== 90;
};
/**
* @method _checkAspect
* @static
* @return {boolean}
* @private
*/
Orientation._checkAspect = function () {
var
w = _int( window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, 10 ),
h = _int( window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight, 10 );
return h > w;
};
/**
* Experia Z(Sony Tablet), portrait / landscape 表示が逆なのでwindow比率で判定する
* @method _experiaZ
* @private
*/
Orientation._experiaZ = function () {
// window 幅,高さを使う
// aspect check
if ( Orientation._checkAspect() ) {
// portrait
Orientation.portrait();
} else {
Orientation.landscape();
}
};
/**
* window.matchMedia listener handler
* @method _onRotate
* @static
* @param {MediaQueryList} mediaQuery
* @private
*/
Orientation._onRotate = function ( mediaQuery ) {
// use matchMediaå
if ( mediaQuery.matches ) {
// portrait
//Orientation.portrait();
Orientation.dispatchEvent( { type: Orientation.CHANGE_ORIENTATION, direction: 'portrait', scope: Orientation } );
} else {
// landscape
//Orientation.landscape();
Orientation.dispatchEvent( { type: Orientation.CHANGE_ORIENTATION, direction: 'landscape', scope: Orientation } );
}
};
/**
* @method _onOrientationChange
* @static
* @private
*/
Orientation._onOrientationChange = function () {
if ( Orientation._checkDegree() ) {
// portrait
Orientation.portrait();
} else {
// landscape
Orientation.landscape();
}
};
/**
* @method _listenMatchMedia
* @static
* @private
*/
Orientation._listenMatchMedia = function () {
var
mql = window.matchMedia( '(orientation: portrait)' ),
sgp312 = !!navigator.userAgent.match(/sgp312/i);
_mediaQuery = mql;
//if ( ( iOS.is() && iOS.version() < 6 ) || ( Android.is() && Android.version() < 4.2 ) ) {
if ( sgp312 ) {
// experia z
window.addEventListener( Orientation.eventType(), Orientation._experiaZ, false );
}
//else if ( iOS.is() && iOS.version() < 6 ) {
else if ( (iOS.is() && iOS.version() < 6) || Android.standard() ) {
// iOS 5 以下だと mql.addListener が作動しないのでorientationchangeを使用します
window.addEventListener( Orientation.eventType(), Orientation._onOrientationChange, false );
} else {
mql.addListener( Orientation._onRotate );
}
};
return Orientation;
}() );
}( window ) );