};\r
})(); */\r
\r
-/*\r
- * Safari の JavaScript の不備 \r
- * http://nanto.asablo.jp/blog/2006/01/13/209495\r
- * \r
- * web.paulownia.jp - JavaScriptとクロージャ\r
- * https://web.archive.org/web/20070526063400/http://web.paulownia.jp/script/oop/closure.html\r
- * MacOSX 10.3のsafariにはhasOwnPropertyが実装されていないので、独自に追加する必要があります。\r
- * \r
- * prototype汚染問題でhasOwnPropertyを使わないクロスブラウザな方法\r
- * http://os0x.hatenablog.com/entry/20080901/1220272509\r
- */\r
-/*\r
-Object.prototype.hasOwnProperty || (Object.prototype.hasOwnProperty = function( p ){\r
- var proto = this.constructor && this.constructor.prototype,\r
- __p__ = proto && proto.__proto__,\r
- v = this[ p ],\r
- r = false;\r
- \r
- if( __p__ ) proto.__proto__ = null;\r
- \r
- if( p in this ){\r
- if( v !== v ){\r
- if( proto && ( p in proto ) && proto[ p ] !== proto[ p ] ){ // proto[ p ] is NaN\r
- proto[ p ] = 0; // different value\r
- r = this[ p ] !== this[ p ]; // isNaN?\r
- proto[ p ] = v; // set NaN\r
- } else {\r
- r = true;\r
- };\r
- } else\r
- if( proto && p in proto && proto[ p ] === v ){\r
- // this と proto に同名で同値が書かれている可能性あり\r
- proto[ p ] = v + ' '; // different value\r
- r = v === this[ p ];\r
- proto[ p ] = v;\r
- } else {\r
- r = true;\r
- };\r
- };\r
- \r
- if( __p__ ) proto.__proto__ = __p__;\r
- \r
- return r;\r
- }); */\r
-/*\r
-Object.prototype.hasOwnProperty || (Object.prototype.hasOwnProperty = function( p ){\r
- var proto = this.constructor && this.constructor.prototype,\r
- __p__ = proto && proto.__proto__,\r
- r = false,//!!( __p__ && ( proto.__proto__ = null ) )\r
- _pro_, v, isNaN;\r
- \r
- if( __p__ ) proto.__proto__ = null;\r
- if( this.__proto__ ){\r
- _pro_ = this.__proto__;\r
- this.__proto__ = null;\r
- };\r
- \r
- if( p === '__proto__' ){\r
- r = !!_pro_;\r
- } else {\r
- v = this[ p ];\r
- isNaN = v !== v; \r
- \r
- if( p in this ){\r
- if( proto && p in proto && ( proto[ p ] === v ) ^ isNaN ){ //true + false, false + true\r
- // this と proto に同名で同値が書かれている可能性あり\r
- proto[ p ] = v + ' '; // different value\r
- r = ( v === this[ p ] ) ^ isNaN; // true + false, false + true\r
- proto[ p ] = v;\r
- } else {\r
- r = true;\r
- };\r
- }; \r
- };\r
-\r
- if( __p__ ) proto.__proto__ = __p__;\r
- if( _p_ ) this.__proto__ = _pro_;\r
- return r;\r
- }); */
\ No newline at end of file
*/\r
X_UA[ 'Android' ] = X_UA[ 'AndroidMajor' ] + X_UA[ 'AndroidMinor' ] / 10;\r
console.log( '>> Android : ' + X_UA[ 'Android' ] );\r
+ } else\r
+ if( dua.indexOf( 'Android;' ) !== -1 ){\r
+ // Fennec 用\r
+ X_UA[ 'Android' ] = 2;\r
};\r
};\r
\r
X_UA[ 'Trident' ] = parseFloat(dav.split('Trident/')[1]) || 0;\r
\r
tridentToVer = X_UA[ 'Trident' ] ? ( X_UA[ 'Trident' ] + 4 | 0 ) : X_UA[ '_IE' ];\r
- /**\r
- * IE10 以上の互換モードを使用している場合、そのバージョン\r
- * @alias X.UA.IEHost\r
- * @type {number}\r
- */\r
- if( tridentToVer !== X_UA[ '_IE' ] ) X_UA[ 'IEHost' ] = tridentToVer;\r
+\r
+ if( tridentToVer !== X_UA[ '_IE' ] ){\r
+ /**\r
+ * IE10 以上の互換モードを使用している場合、そのバージョン\r
+ * @alias X.UA.IEHost\r
+ * @type {number}\r
+ */ \r
+ X_UA[ 'IEHost' ] = tridentToVer;\r
+ };\r
/**\r
* documentモードを考慮したIEのバージョン\r
* @alias X.UA.IE\r
};\r
\r
console.log( '>> Gecko : ' + X_UA[ 'Gecko' ] );\r
- };\r
+ } else\r
\r
// Android 標準ブラウザ AOSP と ChromeWeb View, Sブラウザがある\r
if( ( v = X_UA[ 'Android' ] ) &&\r
\r
console.log( 'HTML5? ' + X_UA_ATagWrapDiv ); */\r
\r
-var X_Script_VBS_ENABLED = X_UA[ 'Windows' ] && !X_UA[ 'WinCE' ] && !X_UA[ 'WinPhone' ] && X_UA[ 'IE' ] < 11;\r
+var X_Script_VBS_ENABLED = X_UA[ 'Windows' ] && !X_UA[ 'WinCE' ] && !X_UA[ 'WinPhone' ] && X_UA[ 'IE' ] < 11,\r
+ // 構文のサポート instanceof, in(for-in ではない), try-catch. JS version 1.5以上\r
+ X_Script_gte15 = !( X_UA[ 'IE' ] < 5.5 ) && ( new Function( 'f,a', 'try{return f.apply({},a)}catch(e){}' ) );\r
\r
/**\r
* js バージョン間の際を吸収\r
'tryCatch' : X_Script_try\r
};\r
\r
-if( X_UA[ 'IE' ] < 9 && X_Script_VBS_ENABLED ){\r
- (function( lines ){\r
- var s = document.createElement( 'script' );\r
- X_elmHead.appendChild( s );\r
- s.type = 'text/vbscript';\r
- s.text = lines.join( '\n' );\r
- \r
- })( [\r
- 'Function vba_testAXO(v)',\r
- 'On Error Resume Next',\r
- 'Set ax = CreateObject(v)',\r
- 'If Err.Number Then',\r
- 'ax = 1',\r
- 'End If',\r
- 'Err.Clear',\r
- 'vba_testAXO = ax',\r
- 'End Function' /*,\r
- \r
- 'Function vba_try(jsFunc,a1,a2,a3,a4)',\r
- 'On Error Resume Next',\r
- 'Set rs = jsFunc(a1,a2,a3,a4)',\r
- 'If Err.Number != 0 Then',\r
- 'rs = 0',\r
- 'End If',\r
- 'Err.Clear',\r
- 'vba_try = rs',\r
- 'End Function' */\r
- ] );\r
- \r
+if( X_Script_VBS_ENABLED ){\r
+ X_Script_gte15 || document.write( '<script type=text/vbscript>' +\r
+ [\r
+ 'Function vbs_testAXO(v)',\r
+ 'On Error Resume Next',\r
+ 'Set ax = CreateObject(v)',\r
+ 'If Err.Number Then',\r
+ 'ax = 1',\r
+ 'End If',\r
+ 'Err.Clear',\r
+ 'vbs_testAXO = ax',\r
+ 'End Function' /*,\r
+ \r
+ 'Function vbs_try(jsFunc,a1,a2,a3,a4)',\r
+ 'On Error Resume Next',\r
+ 'Set rs = jsFunc(a1,a2,a3,a4)',\r
+ 'If Err.Number != 0 Then',\r
+ 'rs = 0',\r
+ 'End If',\r
+ 'Err.Clear',\r
+ 'vbs_try = rs',\r
+ 'End Function'\r
+ \r
+ // elementID .SRC = v\r
+ 'Function vbs_setValue(id,k,v)',\r
+ 'On Error Resume Next',\r
+ 'Set rs = 1',\r
+ 'Document.all[id][k]=v',\r
+ 'If Err.Number != 0 Then',\r
+ 'rs = 0',\r
+ 'End If',\r
+ 'Err.Clear',\r
+ 'vbs_try = rs',\r
+ 'End Function'\r
+\r
+ * \r
+ * \r
+ * */\r
+ ].join( '\n' ) + '</script>' );\r
+\r
// TODO Object のメンバを辿る vba\r
+ // byte Array を扱う vba\r
};\r
\r
function X_Script_try( func, args ){\r
- if( X_UA[ 'IE' ] < 5.5 ){\r
+ if( !X_Script_gte15 ){\r
//return func.apply( {}, args );\r
return;\r
};\r
- return ( new Function( 'f,a', 'try{return f.apply({},a)}catch(e){}' ) )( func, args || [] );\r
+ return X_Script_gte15( func, args || [] );\r
};\r
\r
function X_Script_createActiveXObjectSafty( name ){\r
- if( X_UA[ 'IE' ] < 9 ){\r
+ if( !X_Script_gte15 ){\r
if( X_Script_VBS_ENABLED ){\r
- console.log( window[ 'vba_testAXO' ]( name ) + ' ' + name );\r
- return !window[ 'vba_testAXO' ]( name ) && X_Script_createActiveXObject( name );\r
+ // console.log( window[ 'vbs_testAXO' ]( name ) + ' ' + name );\r
+ return !window[ 'vbs_testAXO' ]( name ) && X_Script_createActiveXObject( name );\r
};\r
return X_Script_createActiveXObject( name );\r
};\r
return new ActiveXObject( name );\r
};\r
\r
-// TODO 構文のサポート instanceof, in, try catch\r
-\r
-if( X_UA[ 'IE' ] < 7 ){ // error @ NN7.2\r
- X_UA[ 'IE4' ] || X_UA[ 'IE5' ] || X_UA[ 'MacIE' ] ?\r
- document.execCommand && document.execCommand( 'BackgroundImageCache', false, true ) :\r
- (\r
- X_Script_try( function(){ document.execCommand( 'BackgroundImageCache', false, true ); return 1; } ) &&\r
- /**\r
- * ie7 以下で実行する document.execCommand( 'BackgroundImageCache', false, true ) の失敗。\r
- * bonus: hotfix for IE6 SP1 (bug KB823727)\r
- * multipleIEs IE6 standalone 版では不可, IE5.5 は可,,,\r
- * @alias X.UA.ieExeComError */ \r
- ( X_UA[ 'ieExeComError' ] = true )\r
- );\r
+/*\r
+ * http://archiva.jp/web/html-css/ie6_background_flickr.html\r
+ * hover時の背景画像ちらつきに対処する\r
+ * この問題はIE6固有の問題であり、他のモダンブラウザやIE5等では発現しない。\r
+ */\r
+if( X_UA[ 'IE6' ] && // error @ NN7.2\r
+ !X_Script_try( function(){ document.execCommand( 'BackgroundImageCache', false, true ); return 1; } ) ){\r
+ /**\r
+ * ie6 のみで実行する document.execCommand( 'BackgroundImageCache', false, true ) の失敗。\r
+ * bonus: hotfix for IE6 SP1 (bug KB823727)\r
+ * multipleIEs IE6 standalone 版では不可, IE5.5 は可,,,\r
+ * @alias X.UA.ieExeComError */\r
+ X_UA[ 'ieExeComError' ] = true;\r
};\r
+\r
* @param {object} obj \r
* @return {boolean} name が定義されている(値が undefined や null でも) -> true\r
*/\r
-var X_Object_inObject = X_UA[ 'IE' ] < 5.5 ? // TODO JScript で判定\r
- (function( name, obj, p ){\r
- if( obj[ name ] ) return true; // quick\r
+var X_Object_inObject = !X_Script_gte15 ? // TODO JScript で判定\r
+ (function( name, obj, _ ){\r
name += ''; // 数値も許可\r
- for( p in obj ){\r
- if( p === name ) return true;\r
+ if( obj[ name ] ) return true; // quick\r
+ for( _ in obj ){\r
+ if( _ === name ) return true;\r
};\r
return false;\r
}) :\r
return obj;\r
};\r
\r
+// TODO X.Object.own( obj, name )\r
+/*\r
+ * Safari の JavaScript の不備 \r
+ * http://nanto.asablo.jp/blog/2006/01/13/209495\r
+ * \r
+ * web.paulownia.jp - JavaScriptとクロージャ\r
+ * https://web.archive.org/web/20070526063400/http://web.paulownia.jp/script/oop/closure.html\r
+ * MacOSX 10.3のsafariにはhasOwnPropertyが実装されていないので、独自に追加する必要があります。\r
+ * \r
+ * prototype汚染問題でhasOwnPropertyを使わないクロスブラウザな方法\r
+ * http://os0x.hatenablog.com/entry/20080901/1220272509\r
+ */\r
+/*\r
+Object.prototype.hasOwnProperty || (Object.prototype.hasOwnProperty = function( p ){\r
+ var proto = this.constructor && this.constructor.prototype,\r
+ __p__ = proto && proto.__proto__,\r
+ v = this[ p ],\r
+ r = false;\r
+ \r
+ if( __p__ ) proto.__proto__ = null;\r
+ \r
+ if( p in this ){\r
+ if( v !== v ){\r
+ if( proto && ( p in proto ) && proto[ p ] !== proto[ p ] ){ // proto[ p ] is NaN\r
+ proto[ p ] = 0; // different value\r
+ r = this[ p ] !== this[ p ]; // isNaN?\r
+ proto[ p ] = v; // set NaN\r
+ } else {\r
+ r = true;\r
+ };\r
+ } else\r
+ if( proto && p in proto && proto[ p ] === v ){\r
+ // this と proto に同名で同値が書かれている可能性あり\r
+ proto[ p ] = v + ' '; // different value\r
+ r = v === this[ p ];\r
+ proto[ p ] = v;\r
+ } else {\r
+ r = true;\r
+ };\r
+ };\r
+ \r
+ if( __p__ ) proto.__proto__ = __p__;\r
+ \r
+ return r;\r
+ }); */\r
+/*\r
+Object.prototype.hasOwnProperty || (Object.prototype.hasOwnProperty = function( p ){\r
+ var proto = this.constructor && this.constructor.prototype,\r
+ __p__ = proto && proto.__proto__,\r
+ r = false,//!!( __p__ && ( proto.__proto__ = null ) )\r
+ _pro_, v, isNaN;\r
+ \r
+ if( __p__ ) proto.__proto__ = null;\r
+ if( this.__proto__ ){\r
+ _pro_ = this.__proto__;\r
+ this.__proto__ = null;\r
+ };\r
+ \r
+ if( p === '__proto__' ){\r
+ r = !!_pro_;\r
+ } else {\r
+ v = this[ p ];\r
+ isNaN = v !== v; \r
+ \r
+ if( p in this ){\r
+ if( proto && p in proto && ( proto[ p ] === v ) ^ isNaN ){ //true + false, false + true\r
+ // this と proto に同名で同値が書かれている可能性あり\r
+ proto[ p ] = v + ' '; // different value\r
+ r = ( v === this[ p ] ) ^ isNaN; // true + false, false + true\r
+ proto[ p ] = v;\r
+ } else {\r
+ r = true;\r
+ };\r
+ }; \r
+ };\r
+\r
+ if( __p__ ) proto.__proto__ = __p__;\r
+ if( _p_ ) this.__proto__ = _pro_;\r
+ return r;\r
+ }); */\r
+ \r
+ \r
+\r
\r
def.live && def.live.push( instance );\r
\r
+ if( ( X_UA[ 'AOSP' ] < 3 || X_UA[ 'iOS' ] < 5 ) && instance.constructor !== klass ){\r
+ console.log( '------- constructor の不一致!' ); // Android2.3.7\r
+ instance.constructor = klass;\r
+ };\r
+\r
obj = def.Constructor ?\r
def.Constructor.apply( instance, args ) :\r
def.SuperConstructor &&\r
instance[ 'kill' ]();\r
return obj;\r
};\r
+ \r
return instance;\r
};\r
\r
\r
X_EVENT_NEED_AUTH = 49,\r
\r
- X_Event_last = 49;\r
+ X_EVENT_DEBUG = 50,\r
+ \r
+ X_Event_last = 50;\r
\r
// in_page_jump\r
// on_screen_keyboard_show\r
'MEDIA_WAITING' : X_EVENT_MEDIA_WAITING,\r
'MEDIA_SEEKING' : X_EVENT_MEDIA_SEEKING,\r
\r
- 'NEED_AUTH' : X_EVENT_NEED_AUTH\r
+ 'NEED_AUTH' : X_EVENT_NEED_AUTH,\r
+ \r
+ 'DEBUG' : X_EVENT_DEBUG\r
};\r
\r
X_TEMP.onSystemReady.push(\r
*/\r
X_Timer_now = Date.now || ( function(){ return +new Date; } ),\r
\r
- X_Timer_SET_TIMEOUT = window.setTimeout,\r
- X_Timer_CLEAR_TIMEOUT = window.clearTimeout,\r
-\r
+ // TODO X.AF.request, X.AF.cancel\r
// http://uupaa.hatenablog.com/entry/2012/02/01/083607\r
// Firefox 4 partial (request only), Mobile Firefox5 ready (request only), Firefox 11 ready (cancel impl) \r
X_Timer_REQ_ANIME_FRAME =\r
* @alias X.Timer\r
*/ \r
X[ 'Timer' ] = {\r
+ // TODO IE4 の resolution は 64ms\r
+ 'RESOLUTION' : X_Timer_INTERVAL_TIME,\r
\r
'now' : X_Timer_now,\r
\r
function X_Timer_add( time, opt_count, args1, args2, args3 ){\r
var list = X_Timer_TICKET_LIST,\r
hash, obj;\r
+\r
time = time < X_Timer_INTERVAL_TIME ? 1 : time / X_Timer_INTERVAL_TIME | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
\r
if( !X_Type_isNumber( opt_count ) ){\r
};\r
\r
if( X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ){\r
- X.Timer[ '_' ] = X_Timer_onTimeout;\r
+ X[ 'Timer' ][ '_' ] = X_Timer_onTimeout;\r
X_Timer_onTimeout = 'X.Timer._()';\r
};\r
\r
i = list.length,\r
n;\r
if( i === 0 ){\r
- X_Timer_timerId && X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+ X_Timer_timerId && clearTimeout( X_Timer_timerId );\r
X_Timer_timerId = 0;\r
return;\r
};\r
\r
if( n < X_Timer_waitTime || X_Timer_timerId === 0 ){\r
if( X_Timer_timerId ){\r
- X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
- n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0;\r
+ clearTimeout( X_Timer_timerId );\r
+ n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME;\r
0 <= n || ( n = 0 ); // 負の数は 0 に\r
};\r
X_Timer_timeStamp = X_Timer_now();\r
- X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
+ X_Timer_timerId = setTimeout( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n | 0 );\r
X_Timer_waitTime = n;\r
};\r
};\r
window.addEventListener( 'scroll', function(){\r
var last, now;\r
if( X_Timer_timerId ){\r
- X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+ clearTimeout( X_Timer_timerId );\r
now = X_Timer_now();\r
last = X_Timer_timeStamp + X_Timer_INTERVAL_TIME * X_Timer_waitTime - now;\r
- X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, 0 < last ? last : 0 );\r
+ X_Timer_timerId = setTimeout( X_Timer_onTimeout, 0 < last ? last : 0 );\r
// 更新\r
X_Timer_timeStamp = now;\r
X_Timer_waitTime = last / X_Timer_INTERVAL_TIME | 0;\r
X_ViewPort[ 'dispatch' ]( X_EVENT_UNLOAD );
//alert('unload');
X_ViewPort_document[ 'kill' ]();
- this[ 'kill' ]();
+ X_ViewPort[ 'kill' ]();
//X_System[ 'dispatch' ]( X_EVENT_SHUT_DOWN );
break;
};
X_TEMP.onDomContentLoaded = function(){
- var s, size, html, head, body;
+ var html, head, body;
console.log( '> X_TEMP.onDomContentLoaded rs:' + X_ViewPort_readyState );
console.log( '------------------->' );
if( document[ 'webkitHidden' ] !== undefined ){
- console.log( '--> has webkitvisibilitychange' );
X_EventDispatcher_systemListen( X_ViewPort_document, 'webkitvisibilitychange', X_ViewPort );
} else
if( document[ 'hidden' ] !== undefined ){// iOS 7+
- console.log( '--> has visibilitychange' );
X_EventDispatcher_systemListen( X_ViewPort_document, 'visibilitychange', X_ViewPort );
- document.onvisibilitychange = function(){ console.log( '!!!!!!!!!!!!!!!!' ) };
} else
if( document[ 'msHidden' ] !== undefined ){
X_EventDispatcher_systemListen( X_ViewPort_document, 'msvisibilitychange', X_ViewPort );
};
if( window[ 'onpageshow' ] !== undefined ){
- console.log( '-------------------> pageshow, pagehide' );
X_EventDispatcher_systemListen( X_ViewPort, [ 'pageshow', 'pagehide' ] );
};
if( document[ 'onfocusin' ] !== undefined ){
- console.log( '-------------------> focusin, focusout' );
// https://github.com/ai/visibilityjs/blob/master/lib/visibility.fallback.js
X_EventDispatcher_systemListen( X_ViewPort_document, [ 'focusin', 'focusout' ], X_ViewPort );
};
};\r
return 0;\r
})(),\r
+ \r
+ X_NodeFlags_SYSTEM_NODE = 2 << 27,\r
\r
X_Node_BITMASK_RESET_STYLE = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (\r
X_NodeFlags_STYLE_IS_DISPLAY_NONE |\r
X_TEMP.onSystemReady.push( function( sys ){\r
var target = X_NodeList.prototype,\r
src = Node.prototype,\r
- p, v, multi;\r
+ p, v;\r
for( p in src ){\r
//if( X_EMPTY_OBJECT[ p ] ) continue;\r
v = src[ p ];\r
if( X_Type_isFunction( v ) && !target[ p ] ){\r
- target[ p ] = multi = new Function( [\r
+ target[ p ] = new Function( [\r
'var a=arguments,f=X.Node.prototype.', p, ',t=this,i,l=t.length;',\r
'if(l)',\r
- 'for(i=0;i<l;++i)if(i===l-1)return f.apply(t[i],a);else f.apply(t[i],a);',\r
+ 'for(i=0;i<l;++i)',\r
+ 'if(i===l-1)return f.apply(t[i],a);',\r
+ 'else f.apply(t[i],a);',\r
'return f.apply(t,a)'\r
].join( '' ) );\r
};\r
return;\r
};\r
\r
- if( async && startTime + 15 <= X_Timer_now() && html ){\r
+ if( async && startTime + X_Timer_INTERVAL_TIME <= X_Timer_now() && html ){\r
handler.progress( 1 - html.length / async[ 0 ] );\r
X_Timer_once( 0, X_HTMLParser_exec, [ html, handler, async ] );\r
return;\r
};
if( name === 'inView' ){
- body = document.body;
+ body = X_elmBody;
child = raw;
visibleX = visibleY = visibleW = visibleH = 0;
while( child !== body ){
if( !elm ){
if( !that[ '_tag' ] ){
that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
- that[ '_rawObject' ] = elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
+ elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
if( !X_UA[ 'IE' ] ){
elm[ 'UID' ] = that[ '_uid' ];
};
if( X_Node_strictElmCreation ){
that[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??
- that[ '_rawObject' ] = elm =
+ elm =
document.createElement( [
'<', that[ '_tag' ],
' UID="', that[ '_uid' ], '"',
X_Node_Attr_objToAttrText( that, true ),
that[ '_cssText' ] ? ' style="' + that[ '_cssText' ] + '"' : '',
'>' ].join( '' ) );
+ } else
+ if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
+ elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
} else {
- if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
- that[ '_rawObject' ] = elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
- } else {
- that[ '_rawObject' ] = elm = document.createElement( that[ '_tag' ] );
- };
+ elm = document.createElement( that[ '_tag' ] );
};
+ that[ '_rawObject' ] = elm;
+
// IE には要素追加のタイミングで起こるメモリリークがありここで追加
if( !X_Node_addTreeAfterChildren ){
nextElement ?
e.appendChild( node );\r
parent.removeChild( e );\r
node.parentNode = null;\r
- document.body.appendChild( node );\r
+ X_elmBody.appendChild( node );\r
parent.replaceChild( document.createComment( '' ), node ); */\r
- document.body.appendChild( node );\r
+ X_elmBody.appendChild( node );\r
return;\r
/*\r
- if( parent.parentNode !== document.body ){\r
+ if( parent.parentNode !== X_elmBody ){\r
var clone = parent.cloneNode( true );\r
for( var i = 0, l = parent.childNodes.length; i < l; ++i ){\r
if( parent.childNodes[ i ] !== node ){\r
X_UA_DOM.W3C ?\r
(function(){\r
var r = X_Node_body,\r
- body = r[ '_rawObject' ],\r
+ body = X_elmBody,\r
copy, i, l, node, html,\r
elmProgress;\r
\r
// textarea の内容を控えて、消す。xnode tree 構築後に復帰。でないと、html パースでこける\r
//X_UA[ 'MacIE' ] && alert( body.innerHTML );\r
// cleanup tree \r
- function cleanUpTree( elm, skip, head ){\r
+ function cleanUpTree( elm, skip ){\r
var nodes = X_Array_copy( elm.childNodes ),\r
i = 0,\r
l = nodes.length,\r
case 1 :\r
tag = node.tagName.toUpperCase();\r
if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){\r
- head = head || document.getElementsByTagName( 'head' )[ 0 ];\r
- head.appendChild( node );\r
+ X_elmHead.appendChild( node );\r
continue;\r
} else\r
if( X_TEMP._isCleanupTarget( node ) ){\r
continue;\r
} else {\r
// pre タグ以下はスペースの置換は行わない\r
- node.childNodes && node.childNodes.length && cleanUpTree( node, skip || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ], head );\r
+ node.childNodes && node.childNodes.length && cleanUpTree( node, skip || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ] );\r
};\r
textNode = null;\r
break;\r
elmProgress.style.cssText = 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;';\r
elmProgress.setAttribute( 'style', 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;' );\r
\r
- X_TEMP._body = body;\r
- \r
X_HTMLParser_asyncParse( html, true )\r
[ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )\r
[ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );\r
body.insertAdjacentHTML( 'BeforeEnd', '<div id="' + elmProgress + '" style="position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;"></div>' );\r
X_TEMP.elmProgress = document.all[ elmProgress ];\r
\r
- X_TEMP._body = body;\r
- \r
X_HTMLParser_asyncParse( html, true )\r
[ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )\r
[ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );\r
xnodes.push.apply( xnodes, e.xnodes );\r
elmProgress.style.width = '100%';\r
\r
- X_TEMP.asyncCreateTree( X_Node_body, X_TEMP._body.childNodes || X_TEMP._body.children, elmProgress );\r
+ X_TEMP.asyncCreateTree( X_Node_body, X_elmBody.childNodes || X_elmBody.children, elmProgress );\r
\r
delete X_TEMP._onPreInit;\r
- delete X_TEMP._body;\r
delete X_TEMP.elmProgress;\r
break;\r
};\r
continue;\r
};\r
\r
- if( startTime + 16 <= X_Timer_now() ){\r
+ if( startTime + X_Timer_INTERVAL_TIME <= X_Timer_now() ){\r
current.i = i;\r
if( async ){\r
async.current = i < l && current;\r
})() :
0,
- X_Pulgin_FLASH_ENABLED =
- X_UA[ 'ActiveX' ] ? !!X_Pulgin_FLASH_VERSION :
- X_Object_find( navigator, 'mimeTypes>application/x-shockwave-flash>enabledPlugin' ),
-
/*
* ie11 の 互換モード(8,7)では、Silverlight が動作しない?
*/
!X_UA[ 'IE' ] || !X_UA[ 'ActiveX' ] ? parseFloat( X_Object_find( navigator, 'plugins>Silverlight Plug-In>version' ) || 0 ) :
X_UA[ 'ActiveX' ] && 6 <= X_UA[ 'IE' ] ? (function(){
var obj = X_Script_createActiveXObjectSafty( 'AgControl.AgControl' ),
- i = obj ? 5 : 0, f;
+ i = obj ? 5 : 0;
for( ; i; --i ){
if( obj[ 'IsVersionSupported' ]( i + '.0' ) ) return i;
})() :
0,
- X_Pulgin_SILVER_LIGHT_ENABLED =
- X_UA[ 'ActiveX' ] ? !!X_Pulgin_SILVER_LIGHT_VERSION :
- X_Object_find( navigator, 'mimeTypes>application/x-silverlight>enabledPlugin' ),
-
//http://docs.unity3d.ru/Manual/Detecting%20the%20Unity%20Web%20Player%20using%20browser%20scripting.html
X_Pulgin_UNITY_VERSION =
!X_UA[ 'IE' ] || !X_UA[ 'ActiveX' ] ?
!X_UA[ 'IE4' ] && !X_UA[ 'IE5' ] && X_UA[ 'ActiveX' ] ? (function(){
var obj = X_Script_createActiveXObjectSafty( 'UnityWebPlayer.UnityWebPlayer.1' );
- console.log( obj && obj[ 'GetPluginVersion' ]() );
+ //console.log( obj && obj[ 'GetPluginVersion' ]() );
return obj ? parseFloat( obj[ 'GetPluginVersion' ]() ) : 0;
})() :
0,
- X_Pulgin_UNITY_ENABLED =
- X_UA[ 'ActiveX' ] ? !!X_Pulgin_UNITY_VERSION :
- X_Object_find( navigator, 'mimeTypes>application/vnd.unity>enabledPlugin' ),
-
X_Pulgin_GEARS_ENABLED =
window.GearsFactory ||
( X_UA[ 'ActiveX' ] && 6 <= X_UA[ 'IE' ] ?
*/
X[ 'Pulgin' ] = {
- 'Flash' : X_Pulgin_FLASH_VERSION,
+ 'Flash' : X_Pulgin_FLASH_VERSION,
- 'FlashEnabled' : X_Pulgin_FLASH_ENABLED,
-
- 'Silverlight' : X_Pulgin_SILVER_LIGHT_VERSION,
-
- 'SilverlightEnabled' : X_Pulgin_SILVER_LIGHT_ENABLED,
-
- 'Unity' : X_Pulgin_UNITY_VERSION,
+ 'Silverlight' : X_Pulgin_SILVER_LIGHT_VERSION,
- 'UnityEnabled' : X_Pulgin_UNITY_ENABLED,
+ 'Unity' : X_Pulgin_UNITY_VERSION,
//'QuickTime' : X_Pulgin_QUICKTIME_VERSION,
- 'GearsEnabled' : !!X_Pulgin_GEARS_ENABLED
+ 'Gears' : !!X_Pulgin_GEARS_ENABLED
};
* @alias X.JSON.parse\r
*/\r
function X_JSON_parseTrustableString( jsonString ){\r
+ if( !jsonString ) return jsonString; // '' の場合エラ-になる\r
return window.JSON ? JSON.parse( jsonString ) : eval( '(' + jsonString + ')' );\r
};\r
\r
/*\r
* XMLWrapper_find 周りの オリジナルコードに関する情報\r
* Original code by pettanR team\r
- * - http://sourceforge.jp/projects/pettanr/scm/git/clientJs/blobs/master/0.6.x/js/01_dom/18_XDomQuery.js\r
+ * - https://osdn.jp/projects/pettanr/scm/git/clientJs/blobs/master/0.6.x/js/02_dom/08_XNodeSelector.js\r
* and\r
* Original code by ofk ( kQuery, ksk )\r
* - http://d.hatena.ne.jp/ofk/comment/20090106/1231258010\r
this._rawXML = xml;\r
};\r
\r
-XMLWrapper.prototype.length = 1;\r
-XMLWrapper.prototype[ 'has' ] = XMLWrapper_has;\r
-XMLWrapper.prototype[ 'get' ] = XMLWrapper_get;\r
-XMLWrapper.prototype[ 'val' ] = XMLWrapper_val;\r
-XMLWrapper.prototype[ 'find' ] = XMLWrapper_find;\r
+XMLWrapper.prototype.length = 1;\r
+XMLWrapper.prototype[ 'parent' ] = XMLWrapper_parent;\r
+XMLWrapper.prototype[ 'has' ] = XMLWrapper_has;\r
+XMLWrapper.prototype[ 'get' ] = XMLWrapper_get;\r
+XMLWrapper.prototype[ 'val' ] = XMLWrapper_val;\r
+XMLWrapper.prototype[ 'find' ] = XMLWrapper_find;\r
+\r
+function XMLWrapper_parent(){\r
+ if( this.length === 1 ) return this._rawXML && this._rawXML.parentNode ? new XMLWrapper( this._rawXML.parentNode ) : null;\r
+ if( this.length === 0 ) return null;\r
+ \r
+ return this[ 0 ].parentNode ? ( new XMLWrapper( this[ 0 ].parentNode ) ) : null;\r
+};\r
\r
function XMLWrapper_has( queryString ){\r
return !!this.find( queryString ).length;\r
};\r
\r
function XMLWrapper_val( queryString, type ){\r
- var attr_textContent = X_UA[ 'IE' ] < 9 || X_UA[ 'Opera' ] ? 'innerText' : X_UA[ 'IE9' ] ? 'text' : 'textContent',\r
+ var //attr_textContent = X_UA[ 'IE' ] < 9 || X_UA[ 'Opera' ] ? 'innerText' : X_UA[ 'IE9' ] ? 'text' : 'textContent',\r
wrapper, xml, v;\r
\r
switch( queryString ){\r
case 'string' :\r
case undefined :\r
type = queryString;\r
- queryString = undefined;\r
+ queryString = 0;\r
};\r
\r
wrapper = queryString ? this.find( queryString ) : this;\r
case 'int' :\r
return parseFloat( v ) | 0;\r
case 'boolean' :\r
- return v && v !== '0' && v !== 'false' && v !== 'null' && v !== 'undefined' && v !== 'NaN';\r
+ return !!X_String_parse( v );\r
//case 'string' :\r
//default : \r
};\r
for( ; xnode = xmlList[ i ]; ++i ){\r
uid = xnode._uid;\r
tmp = checked[ uid ];\r
- if( tmp === void 0 ){\r
+ if( tmp === undefined ){\r
for( c = 0, node = xnode.parentNode[ pointer ], tagName = flag_all || xnode.tagName; node; node = node[ sibling ] ){\r
if( node.nodeType === 1 && ( flag_all || tagName === node.tagName ) ){\r
++c;\r
\r
var XMLListWrapper_0 = new XMLListWrapper();\r
\r
-XMLListWrapper.prototype.length = 0;\r
-XMLListWrapper.prototype._wraps = null;\r
-XMLListWrapper.prototype[ 'has' ] = XMLWrapper_has;\r
-XMLListWrapper.prototype[ 'get' ] = XMLWrapper_get;\r
-XMLListWrapper.prototype[ 'val' ] = XMLWrapper_val;\r
-XMLListWrapper.prototype[ 'find' ] = XMLWrapper_find;\r
+XMLListWrapper.prototype.length = 0;\r
+XMLListWrapper.prototype._wraps = null;\r
+XMLListWrapper.prototype[ 'parent' ] = XMLWrapper_parent;\r
+XMLListWrapper.prototype[ 'has' ] = XMLWrapper_has;\r
+XMLListWrapper.prototype[ 'get' ] = XMLWrapper_get;\r
+XMLListWrapper.prototype[ 'val' ] = XMLWrapper_val;\r
+XMLListWrapper.prototype[ 'find' ] = XMLWrapper_find;\r
http://tkengo-totoro.blogspot.jp/2011/11/iexmlhttprequest.html\r
TODO クライアント側にもリトライ機構を入れてみる\r
\r
+\r
+TODO xml の取得には XMLDOM を使用する\r
+var activex = JKL.ParseXML.HTTP.ACTIVEX_XMLHTTP; // IXMLHttpRequest\r
+if ( this.method == "GET" && ! this.textmode ) {\r
+ // use IXMLDOMElement to accept any mime types\r
+ // because overrideMimeType() is not available on IE6\r
+ activex = JKL.ParseXML.HTTP.ACTIVEX_XMLDOM; // IXMLDOMElement\r
+};\r
+// debug.print( "new ActiveXObject( '"+activex+"' )" );\r
+this.req = new ActiveXObject( activex );\r
+\r
*/\r
var // Opera7.6+, Safari1.2+, khtml3.?+, Gecko0.9.7+\r
// ie9- ではローカルリソースには MSXML を使う\r
* http://hakuhin.jp/as/javascript.html\r
* Flash から JavaScript にアクセスする(3+)\r
*/\r
- 'FLASH' : X_Pulgin_FLASH_ENABLED && 4 <= X_Pulgin_FLASH_VERSION ? 8 : 0,\r
+ 'FLASH' : 4 <= X_Pulgin_FLASH_VERSION ? 8 : 0,\r
\r
'GADGET' : 5.5 <= X_UA[ 'IE' ] || !X_UA[ 'IE' ] ? 16 : 0,\r
\r
headers = { 'Content-Type' : raw.contentType };\r
} else\r
if( ( X_XHR._isMsXML ? 3 <= X_XHR_msXMLVer : raw.setRequestHeader ) && ( headers = raw.getAllResponseHeaders() ) ){\r
- headers = X_NET_XHR_parseResponseHeaders( headers );\r
+ headers = X_XHR_parseResponseHeaders( headers );\r
};\r
\r
// https://code.google.com/p/fakeworker-js/source/browse/src/javascript/fakeworker.js\r
break;\r
};\r
},\r
- \r
+\r
+/*\r
+ * http://www.kawa.net/works/js/jkl/parsexml.html\r
+ * \r
+// ================================================================\r
+// method: documentElement()\r
+// return: XML DOM in response body\r
+\r
+JKL.ParseXML.HTTP.prototype.documentElement = function() {\r
+ // debug.print( "documentElement: "+this.req );\r
+ if ( ! this.req ) return;\r
+ if ( this.req.responseXML ) {\r
+ return this.req.responseXML.documentElement; // XMLHTTPRequest\r
+ } else {\r
+ return this.req.documentElement; // IXMLDOMDocument\r
+ }\r
+};\r
+\r
+// ================================================================\r
+// method: responseText()\r
+// return: text string in response body\r
+\r
+JKL.ParseXML.HTTP.prototype.responseText = function() {\r
+ // debug.print( "responseText: "+this.req );\r
+ if ( ! this.req ) return;\r
+\r
+ // Safari and Konqueror cannot understand the encoding of text files.\r
+ if ( navigator.appVersion.match( "KHTML" ) ) {\r
+ var esc = escape( this.req.responseText );\r
+// debug.print( "escape: "+esc );\r
+ if ( ! esc.match("%u") && esc.match("%") ) {\r
+ return decodeURIComponent(esc);\r
+ }\r
+ }\r
+\r
+ return this.req.responseText;\r
+};\r
+ */\r
+ \r
onTimeout : function(){\r
var raw = X_XHR[ '_rawObject' ],\r
live = !X_XHR._canceled || !X_XHR._busy;\r
* 複数の情報が存在する場合、改行で区切られています。\r
*/\r
\r
-function X_NET_XHR_parseResponseHeaders( headerStr ){\r
+function X_XHR_parseResponseHeaders( headerStr ){\r
var headers = {}, headerPairs, i = 0, l, headerPair, index, key, val;\r
\r
if( !headerStr ) return headers;\r
};
-var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
- // TODO なんで fennec を禁止?
+var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
+ // Android2 + Gecko で WebAudio が極めて不安定
!( X_UA[ 'Gecko' ] && X_UA[ 'Android' ] ) &&
// Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
// Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
!( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) &&
( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ),
- X_WebAudio_BUFFER_LIST = [],
+ X_WebAudio_BUFFER_LIST = [],
+ X_WebAudio_need1stTouch = X_UA[ 'iOS' ],
X_WebAudio,
X_WebAudio_BufferLoader,
X_WebAudio_fpsFix;
* 8. BlinkOpera32 Win8 は HTMLAudio が壊れている、WebAudio は mp3 がデコードに失敗、ogg が動作\r
* \r
* memo\r
- * 1. Android4.1 iframe 内の Audio は親に focus が移っても再生を継続する\r
+ * 1. AOSP4.1 iframe 内の Audio は親に focus が移っても再生を継続する\r
+ * 2. AOSP4.2(Genymotion) どこかのタイミングでタッチによる play を行う\r
+ * 3. AOSP oggはシークが乱れる m4a, mp3 は優秀\r
*/\r
+ /*\r
+ * durationFix\r
+ * duration が取得できるタイミングが遅くそれまでは infinity(PC Opera12), NaN(WP9), 0(Android 標準ブラウザ ChromeWebView) が入っている\r
+ * \r
+ * 1. touch が不要の場合、自動で再生を開始して duration を取得するまで再生する\r
+ * -> 取得後に pause or 通常再生\r
+ * 2. touch が必要な場合、タッチイベント内の audio.play() で duration 取得\r
+ * \r
+ * PC Opera12\r
+ * 1. loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する\r
+ * 2. duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。\r
+ * 3. Opera12.17 Win32(XP) portable apps は勝手に再生が始まる、、、Win8+Opera では発生しない\r
+ * -> その際には timeupdate が発行されない、、、 iframe+image+audio で使わないときは破棄する、とか。\r
+ * -> opera11、10.54 WinXP はまとも、、、 portable が怪しい??\r
+ */\r
\r
var X_HTMLAudio_playTrigger =\r
- 6 <= X_UA[ 'iOS' ] ? 'loadeddata' :\r
- X_UA[ 'iOS' ] < 5 ? 'stalled' :\r
- X_UA[ 'iOS' ] ? 'suspend' :\r
+ X_UA[ 'iOS' ] < 5 ? 'stalled' :\r
+ X_UA[ 'iOS' ] < 6 ? 'suspend' :\r
+ X_UA[ 'iOS' ] < 7 ? 'suspend' :\r
+ X_UA[ 'iOS' ] ? 'loadeddata' :\r
X_UA[ 'Safari' ] < 4 ? 'canplaythrough' :\r
X_UA[ 'ChromeWV' ] ? 'canplaythrough' :\r
// Android 2.3.5(SBM101SH) では stalled は発生しない,,, ので必ず loadeddata もチェックする\r
- X_UA[ 'AOSP' ] ? 'stalled' :\r
+ //X_UA[ 'AOSP' ] < 3 ? 'stalled' :\r
+ //X_UA[ 'AOSP' ] ? 'playing' :\r
X_UA[ 'OperaMobile' ] || X_UA[ 'OperaTablet' ] ? 'loadeddata' :\r
'loadeddata', //'canplay',\r
X_HTMLAudio,\r
// Android 3.1 で ended 時に src='';src=src を実施。\r
X_HTMLAudio_endedFixAOSP3 = !X_HTMLAudio_endedFixAOSP2 && X_UA[ 'AOSP' ] < 4,\r
// ended 時に play() を実施, currentTime が duration に張り付き更新されなければ src='';src=src を実施。\r
- X_HTMLAudio_endedFixAOSP4 = 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ],\r
+ X_HTMLAudio_endedFixAOSP4 = 4 <= X_UA[ 'AOSP' ],\r
+ // ended 時に play() を実施\r
+ X_HTMLAudio_endedFixCWV = X_UA[ 'ChromeWV' ],\r
\r
// Opera Mobile 12 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する\r
X_HTMLAudio_currentTimeFix = !!X_UA[ 'OperaMobile' ] || !!X_UA[ 'OperaTablet' ],\r
X_HTMLAudio_needPlayForSeek = X_UA[ 'Gecko' ],\r
// \r
X_HTMLAudio_pauseFix = ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ) ), // XP + Opera12 のみ?\r
- /*\r
- * durationFix\r
- * duration が取得できるタイミングが遅くそれまでは infinity(PC Opera12), NaN(WP9), 0(Android 標準ブラウザ ChromeWebView) が入っている\r
- * \r
- * 1. touch が不要の場合、自動で再生を開始して duration を取得するまで再生する\r
- * -> 取得後に pause or 通常再生\r
- * 2. touch が必要な場合、タッチイベント内の audio.play() で duration 取得\r
- * \r
- * PC Opera12\r
- * 1. loadeddata 等では duration が infinity で、再生後の durationchange 時に duration が判明する\r
- * 2. duration 判明後には currentTime によるシークと、現在時間の取得が可能になる。\r
- * 3. Opera12.17 Win32(XP) portable apps は勝手に再生が始まる、、、Win8+Opera では発生しない\r
- * -> その際には timeupdate が発行されない、、、 iframe+image+audio で使わないときは破棄する、とか。\r
- * -> opera11、10.54 WinXP はまとも、、、 portable が怪しい??\r
- */\r
- X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ), \r
- X_HTMLAudio_durationFix = ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ),\r
+\r
+ X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ], \r
+ X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ),\r
\r
- X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇(ただしm4a, mp3は優秀, oggはシークが乱れる)\r
+ X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇\r
\r
\r
\r
_currentFixBegin : 0,\r
\r
_durationFixPhase : X_HTMLAudio_durationFix ? 1 : 0,\r
- _durationFixSkip : X_HTMLAudio_durationFix && !X_HTMLAudio_need1stTouch, \r
+ _durationFixSkip : X_HTMLAudio_durationFix && !X_HTMLAudio_need1stTouch,\r
_lastCurrentTime : 0,\r
\r
_shortPlayFixON : false,\r
\r
_endedFixON : false,\r
\r
- _kickTimerID : false, // 処理が混み入ると AOSP で音声が再生されない\r
- _lastKickTime : 0,\r
- \r
'Constructor' : function( disatcher, source, option ){\r
var raw;\r
\r
'playing', 'waiting', 'seeking',\r
'durationchange', 'timeupdate', 'ended' ] );\r
\r
+\r
+ this[ 'listen' ]( [\r
+ 'loadstart', 'load',\r
+ 'progress', 'error',\r
+ 'suspend', 'abort', 'emptied', 'stalled',\r
+ 'play', 'pause', 'seeked', 'ratechange', 'volumechange',\r
+ 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough',\r
+ 'playing', 'waiting', 'seeking',\r
+ 'durationchange', 'timeupdate', 'ended' ], this.onDebug );\r
+\r
if( X_TEMP.rawAudio ){\r
raw.src = source;\r
- raw.load(); // AOSP2 で必要\r
+ X_UA[ 'AOSP' ] < 3 && raw.load();\r
delete X_TEMP.rawAudio;\r
};\r
},\r
\r
+ onDebug : function( e ){\r
+ this.disatcher[ 'dispatch' ]( {\r
+ type : X_EVENT_DEBUG,\r
+ 'rawEvent' : e.type,\r
+ current : this.getActualCurrentTime() | 0,\r
+ duration : this.duration | 0 } );\r
+ },\r
+ \r
handleEvent : function( e ){\r
var raw = this[ '_rawObject' ],\r
actualEnded = e.type === 'ended',\r
if( this._durationFixPhase & 3 ){ // 1 or 2\r
duration = raw.duration;\r
} else\r
- if( raw.currentTime === this._lastCurrentTime ){\r
+ if( this.getActualCurrentTime() === this._lastCurrentTime ){\r
eventType = X_EVENT_MEDIA_WAITING;\r
} else {\r
- this._lastCurrentTime = raw.currentTime;\r
+ this._lastCurrentTime = this.getActualCurrentTime();\r
\r
if( this.playing ){\r
end = X_Audio_getEndTime( this ) + this._shortPlayFixTime;\r
if( X_HTMLAudio_volumeFix ){\r
raw.volume = this.gain;\r
};\r
- if( X_HTMLAudio_currentTimeFix ){\r
- this._currentFixStart = X_Timer_now(); // 正確な再生開始時間に補正\r
+ if( X_HTMLAudio_currentTimeFix && !this._currentFixStart ){\r
+ //this._currentFixStart = X_Timer_now(); // 正確な再生開始時間に補正\r
};\r
eventType = !this._durationFixSkip && !this._endedFixON ? X_EVENT_MEDIA_PLAYING : X_EVENT_MEDIA_WAITING;\r
//case 'play' : // 再生が開始された。play()メソッドからの復帰後に発生する場合に発生\r
if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
this.looped = true;\r
this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );\r
- ( X_HTMLAudio_endedFixAOSP3 || X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixIOS ) && actualEnded && console.log( '☆★☆ 音声の継続用の play() @ended' );\r
+ ( X_HTMLAudio_endedFixAOSP3 || X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixCWV || X_HTMLAudio_endedFixIOS ) && actualEnded && console.log( '☆★☆ 音声の継続用の play() @ended' );\r
this.actualPlay(\r
- ( X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixIOS ) && actualEnded,\r
+ ( X_HTMLAudio_endedFixAOSP4 || X_HTMLAudio_endedFixCWV || X_HTMLAudio_endedFixIOS ) && actualEnded,\r
( X_HTMLAudio_endedFixAOSP3 || X_HTMLAudio_endedFixAOSP2 ) && actualEnded );\r
};\r
} else {\r
} else\r
if( this._loaded && this.duration && !this._ready ){\r
this._ready = true;\r
- this.autoplay && X_Timer_once( 16, this, this.play );\r
this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
+ this.autoplay && !X_WebAudio_need1stTouch && X_Timer_once( 16, this, this.play );\r
console.log( '> Audio Loaded!! ' + e.type + ' d:' + ( this.duration | 0 ) );\r
} else\r
if( eventType ){\r
};\r
raw.play();\r
this.playing = true;\r
- \r
- if( X_UA[ 'AOSP' ] && !this._kickTimerID ){\r
- this._kickTimerID = X_Timer_add( 100, 0, this, this._kick );\r
- };\r
} else\r
if( X_HTMLAudio_needPlayForSeek || forcePlay ){\r
raw.play();\r
//http://himaxoff.blog111.fc2.com/blog-entry-97.html\r
//Firefox3.6では一度も play() していない状態で currentTime = 0 を実行するとエラーになる。\r
//また、GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。(少なくとも自分の環境では) \r
- raw.currentTime = this._lastKickTime = this._lastCurrentTime;\r
+ raw.currentTime = this._lastCurrentTime;\r
console.log( '[HTMLAudio] play ' + begin + ' -> ' + end + ' crt:' + ( raw.currentTime | 0 ) + ' last:' + this._lastCurrentTime );\r
- \r
- // Android4.0.5 で ended イベント時に currentTime が duration に張り付いたまま変更できない\r
+\r
if( forceReload || ( X_HTMLAudio_endedFixAOSP4 && raw.duration && raw.currentTime === raw.duration ) ){\r
raw.src = '';\r
raw.src = this._src;\r
raw.currentTime = this._lastCurrentTime;\r
this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
X_HTMLAudio_endedFixAOSP2 && raw.load();\r
- }; \r
+ };\r
};\r
\r
if( X_HTMLAudio_currentTimeFix ){\r
};\r
},\r
\r
- _kick : function(){\r
- var raw = this[ '_rawObject' ];\r
- \r
- console.log( ' >> KICK ? ct:' + ( raw.currentTime ) + ' lkt:' + this._lastKickTime );\r
- if( this.playing && raw.currentTime === this._lastKickTime ){\r
- this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_WAITING );\r
- console.log( ' >> KICK !!' );\r
- raw.play();\r
- } else {\r
- delete this._kickTimerID;\r
- return X_CALLBACK_UN_LISTEN;\r
- };\r
- },\r
- \r
actualPause : function(){\r
console.log( '[HTMLAudio] pause' );\r
\r
X_AudioSprite_useVideoForMulti = //( 3.1 <= X_UA[ 'AOSP' ] < 4 ) || \r
//( ( 4.2 <= X_UA[ 'AOSP' ] ),\r
// ドスパラパッドはビデオのインライン再生が不可\r
- false, //X_UA[ 'ChromeWV' ],\r
- X_AudioSprite_needTouchAndroid = X_UA[ 'ChromeWV' ] && !X_WebAudio,\r
- X_AudioSprite_needTouchFirst = X_HTMLAudio_need1stTouch,\r
- X_AudioSprite_disableMultiTrack = ( X_UA[ 'iOS' ] && !X_WebAudio_context ) || ( X_UA[ 'AOSP4' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE' ] < 12 ),\r
+ false,\r
+ X_AudioSprite_disableMultiTrack = !X_WebAudio && ( X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ),\r
X_AudioSprite_enableVolume = X_HTMLAudio && ( !X_UA[ 'iOS' ] && !X_UA[ 'AOSP' ] && !X_UA[ 'OperaMobile' ] && !X_UA[ 'OperaTablet' ] ), // TODO fennec は 25以上\r
// http://tukumemo.com/html5-audio-sp/\r
// iOS6、Android4.1から同時再生が可能になりました。\r
};\r
\r
X[ 'AudioSprite' ][ 'shouldUse' ] = X_AudioSprite_shouldUse;\r
-X[ 'AudioSprite' ][ 'needTouchFirst' ] = X_AudioSprite_needTouchFirst;\r
X[ 'AudioSprite' ][ 'enableMultiTrack' ] = !X_AudioSprite_disableMultiTrack;\r
\r
// 再生が終わっているもの、終わりかけのものを探す\r
/**\r
* モバイル用タッチイベント中に呼び出す\r
*/\r
- 'load' : function(){\r
- var tracks = X_AudioSprite_TEMP.tracks,\r
- i = 0, l = tracks.length;\r
+ 'on1stTouch' : function(){\r
+ var i = 0, l = X_AudioSprite_TEMP.tracks.length;\r
\r
for( ; i < l; ++i ){\r
- if( X_AudioSprite_needTouchAndroid ){\r
- console.log( '[duration fix]開始 - ' + tracks[ i ][ '_rawObject' ].duration );\r
- tracks[ i ]._durationFixPhase = 1;\r
- tracks[ i ][ '_rawObject' ].play();\r
- } else\r
- if( X_UA[ 'WinPhone' ] ){\r
- console.log( 'WinPhone : touch -> play()' );\r
- //tracks[ i ].play( 0, X_AudioSprite_lengthSilence, true, 0, X_AudioSprite_lengthSilence ).seek( 0 );\r
- this[ 'pause' ]( i );\r
+ if( X_UA[ 'iOS' ] ){\r
+ X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load();\r
} else {\r
- tracks[ i ][ '_rawObject' ].load();\r
+ X_AudioSprite_instance[ 'pause' ]( i );\r
};\r
};\r
},\r
track = X_AudioSprite_TEMP.bgmTrack = tracks[ 0 ];\r
};\r
\r
- if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_AudioSprite_handleEvent ).playing ){\r
+ if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent ).playing ){\r
track.setState({\r
'loop' : true,\r
'looped' : X_AudioSprite_TEMP.bgmLooped,\r
if( 1 < tracks.length ){\r
track = X_AudioSprite_getTrackEnded( X_AudioSprite_TEMP.bgmPlaying );\r
track\r
- [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_AudioSprite_handleEvent )\r
+ [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent )\r
.setState( { 'looped' : false } );\r
track.play( preset[ 0 ], preset[ 1 ], true, 0, X_AudioSprite_lengthSilence );\r
} else {\r
};\r
track = tracks[ 0 ];\r
\r
- if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_AudioSprite_handleEvent ).playing ){\r
+ if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_instance, X_AudioSprite_handleEvent ).playing ){\r
track.setState({\r
'loop' : true,\r
'looped' : false,\r
};\r
track && track.play( 0, X_AudioSprite_lengthSilence, true, 0, X_AudioSprite_lengthSilence );\r
track && track.seek( 0 );\r
- this[ 'asyncDispatch' ]( X_EVENT_MEDIA_PAUSED );\r
- return this;\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_PAUSED );\r
+ return X_AudioSprite_instance;\r
},\r
\r
/**\r
start = X_Audio_getStartTime( track, end );\r
0 <= position && position <= ( end - start ) && track.seek( start + position );\r
};\r
- return this;\r
+ return X_AudioSprite_instance;\r
},\r
\r
/**\r
for( i = X_AudioSprite_TEMP.tracks.length; i; ){\r
X_AudioSprite_TEMP.tracks[ --i ].volume( opt_volume );\r
};\r
- return this;\r
+ return X_AudioSprite_instance;\r
};\r
track = X_AudioSprite_TEMP.tracks[ uid ];\r
if( opt_volume === undefined ){\r
return track ? track.gain : -1;\r
};\r
track && track.volume( opt_volume );\r
- return this;\r
+ return X_AudioSprite_instance;\r
},\r
\r
/**\r
return { 'volume' : X_AudioSprite_TEMP.volume, 'playing' : false };\r
};\r
track && track.setState( opt_obj );\r
- return this;\r
+ return X_AudioSprite_instance;\r
}\r
};\r
\r
function X_AudioSprite_backendHandler( e ){\r
- var i, backend, option, src, name, last, _e;\r
+ var i, backend, option, src, name, last, _e, touch;\r
\r
switch( e.type ){\r
case X_EVENT_BACKEND_READY :\r
backend = X_Audio_BACKENDS[ e[ 'backendID' ] ];\r
option = e[ 'option' ];\r
\r
- this[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_backendHandler );\r
- this[ 'source' ] = src = e[ 'source' ];\r
- this[ 'backendName' ] = name = backend.backendName;\r
+ X_AudioSprite_instance[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_backendHandler );\r
+ X_AudioSprite_instance[ 'source' ] = src = e[ 'source' ];\r
+ X_AudioSprite_instance[ 'backendName' ] = name = backend.backendName;\r
\r
//console.log( i + ' / ' + X_AudioSprite_numTracks );\r
\r
console.log( 'use video' );\r
};\r
// Audiobackend の owner として null を渡すとAudioBackend 自身へ dispatch する\r
- X_AudioSprite_TEMP.tracks.push( last = backend.klass( null, e[ 'source' ], option ) );\r
- \r
- \r
- //console.dir( backend );\r
- //console.dir( last );\r
+ X_AudioSprite_TEMP.tracks.push( last = backend.klass( null, e[ 'source' ], option )[ 'listen' ]( X_EVENT_DEBUG, X_AudioSprite_instance, X_AudioSprite_handleEvent ) );\r
};\r
\r
_e = {\r
'source' : src,\r
'backendName' : name\r
};\r
+ // touch 可能で backend ready\r
\r
- if( X_AudioSprite_needTouchFirst ){\r
- if( name === 'WebAudio' ){\r
- _e[ 'needTouchForPlay' ] = true;\r
- } else {\r
- _e[ 'needTouchForLoad' ] = true;\r
- };\r
+ if( name === 'WebAudio' ){\r
+ _e[ 'needTouchForPlay' ] = touch = X_WebAudio_need1stTouch;\r
+ } else\r
+ if( name === 'HTMLAudio' ){\r
+ _e[ 'needTouchForLoad' ] = touch = X_HTMLAudio_need1stTouch;\r
};\r
- this[ 'asyncDispatch' ]( _e );\r
+\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
\r
console.log( 'AudioSprite - X_EVENT_BACKEND_READY' );\r
\r
- last[ 'listenOnce' ]( X_EVENT_READY, this, X_AudioSprite_backendHandler );\r
+ last[ 'listenOnce' ]( touch && !X_HTMLAudio_durationFix ? X_EVENT_MEDIA_PLAYING : X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
\r
// READY, needTouchForPlay, needTouchForLoad\r
- if( X_HTMLAudio_durationFix && !X_AudioSprite_needTouchFirst ){\r
+ if( /* X_HTMLAudio_durationFix && */ !touch ){\r
for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
- this[ 'pause' ]( i );\r
+ X_AudioSprite_instance[ 'pause' ]( i );\r
};\r
};\r
\r
return X_CALLBACK_STOP_NOW;\r
\r
case X_EVENT_BACKEND_NONE :\r
- this[ 'unlisten' ]( X_EVENT_BACKEND_READY, this, X_AudioSprite_backendHandler )\r
+ X_AudioSprite_instance[ 'unlisten' ]( X_EVENT_BACKEND_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler )\r
[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE );\r
return X_CALLBACK_STOP_NOW;\r
\r
- case X_EVENT_READY :\r
- if( X_AudioSprite_needTouchAndroid ){\r
- for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
- this[ 'pause' ]( i );\r
- };\r
- e.target[ 'listenOnce' ]( X_EVENT_MEDIA_PLAYING, this, this[ 'asyncDispatch' ], [ X_EVENT_READY ] );\r
- return;\r
- };\r
- \r
+ case X_EVENT_READY : \r
+ case X_EVENT_MEDIA_PLAYING :\r
console.log( 'X.AudioSprite - Ready!' );\r
- this[ 'asyncDispatch' ]( X_EVENT_READY );\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_READY );\r
break;\r
};\r
};\r
\r
switch( e.type ){\r
case X_EVENT_MEDIA_PLAYING :\r
- ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && this[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
+ ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
break;\r
case X_EVENT_MEDIA_WAITING :\r
case X_EVENT_MEDIA_SEEKING :\r
- ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && this[ 'asyncDispatch' ]( e.type );\r
+ ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) && X_AudioSprite_instance[ 'asyncDispatch' ]( e.type );\r
break;\r
\r
case X_EVENT_MEDIA_BEFORE_LOOP :\r
if( e.target === X_AudioSprite_TEMP.bgmTrack ){\r
X_AudioSprite_TEMP.bgmLooped = true;\r
- this[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
} else {\r
if( e.target.looped ){\r
- //this[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
+ // X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
} else {\r
- this[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
};\r
\r
//console.log( '[AudioSprite] bgmPlaying:' + X_AudioSprite_TEMP.bgmPlaying + ' ' + !X_AudioSprite_TEMP.bgmTrack );\r
// single track | iOS\r
if( X_AudioSprite_TEMP.bgmPlaying && !X_AudioSprite_TEMP.bgmTrack ){\r
X_AudioSprite_TEMP.bgmTrack = e.target;\r
- this.play( X_AudioSprite_TEMP.bgmName );\r
+ X_AudioSprite_instance.play( X_AudioSprite_TEMP.bgmName );\r
return X_CALLBACK_PREVENT_DEFAULT;\r
};\r
};\r
break;\r
\r
+ \r
+ case X_EVENT_DEBUG :\r
+ i = X_AudioSprite_TEMP.tracks.indexOf( e.target );\r
+ if( 0 <= i ){\r
+ e[ 'trackID' ] = i;\r
+ X_AudioSprite_instance[ 'dispatch' ]( e );\r
+ };\r
+ break;\r
+ \r
// TODO Android Firefox で アクティブ検出できない!\r
case X_EVENT_VIEW_ACTIVATE :\r
console.log( '■ アクティブ' );\r
X_AudioSprite_TEMP.bgmLooped = false;\r
X_AudioSprite_TEMP.bgmPlaying = false;\r
\r
- X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], this, X_AudioSprite_handleEvent );\r
+ X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_AudioSprite_instance, X_AudioSprite_handleEvent );\r
break;\r
};\r
};\r