OSDN Git Service

Version 0.6.88, add X.Audio & maybe speed up X.Dom.Parser.
authoritozyun <itozyun@user.sourceforge.jp>
Fri, 3 Oct 2014 11:09:47 +0000 (20:09 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Fri, 3 Oct 2014 11:09:47 +0000 (20:09 +0900)
0.6.x/js/00_core/00_X.js
0.6.x/js/00_core/00_builtin.js
0.6.x/js/01_dom/19_XDomParser.js
0.6.x/js/01_dom/22_XDomBuilder.js
0.6.x/js/06_audio/00_XAudio.js [new file with mode: 0644]
0.6.x/js/06_audio/01_XHTML5Audio.js [new file with mode: 0644]
0.6.x/js/import.js

index f1293b8..8fdf586 100644 (file)
@@ -104,8 +104,9 @@ X.copyArray = function( ary ){
 };\r
        \r
 X.isEmptyObject = function( v ){\r
-       if( v.length !== 0 ) return false;\r
-       for( var p in v ){\r
+       var p;\r
+//     if( v.length ) return false;\r
+       for( p in v ){\r
                if( v.hasOwnProperty( p ) ) return false;\r
        };\r
        return true;\r
index d6c3d32..767914f 100644 (file)
@@ -1,3 +1,9 @@
+/**\r
+ * @preserve Copyright 2012-2014 pettanR team.\r
+ * https://sourceforge.jp/projects/pettanr/\r
+ * BSD 3-Clause License\r
+ */\r
+\r
 /* \r
  * ビルトインオブジェクトに拡張したい10のメソッド\r
  * http://d.hatena.ne.jp/ofk/20080922/1222047483\r
index db0c897..51e9cdb 100644 (file)
@@ -5,7 +5,14 @@
  *\r
  */\r
 \r
-X.Dom.Parser = {\r
+X_Dom_Parser = {\r
+       CHARS : {\r
+               A:1,B:1,C:1,D:1,E:1,F:1,G:1,H:1,I:1,J:1,K:1,L:1,M:1,N:1,O:1,P:1,Q:1,R:1,S:1,T:1,U:1,V:1,W:1,X:1,Y:1,Z:1,\r
+               a:2,b:2,c:2,d:2,e:2,f:2,g:2,h:2,i:2,j:2,k:2,l:2,m:2,n:2,o:2,p:2,q:2,r:2,s:2,t:2,u:2,v:2,w:2,x:2,y:2,z:2,\r
+               '0' : 4, '1' : 4, '2' : 4, '3' : 4, '4' : 4, '5' : 4, '6' : 4, '7' : 4, '8' : 4, '9' : 4,\r
+               \r
+               '\t' : 16, '\r\n' : 16, '\r' : 16, '\n' : 16, '\f' : 16, '\b' : 16, ' ' : 16\r
+       },\r
        alphabets  : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',\r
        whiteSpace : '\t\r\n\f\b ',\r
 \r
@@ -13,24 +20,24 @@ X.Dom.Parser = {
        empty : X.Dom.DTD.EMPTY,\r
 \r
        // Block Elements - HTML 4.01\r
-       block : {address:1,applet:1,blockquote:1,button:1,center:1,dd:1,del:1,dir:1,div:1,dl:1,dt:1,fieldset:1,form:1,frameset:1,hr:1,iframe:1,ins:1,isindex:1,li:1,map:1,menu:1,noframes:1,noscript:1,object:1,ol:1,p:1,pre:1,script:1,table:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1,ul:1},\r
-\r
+       block : {ADDRESS:1,APPLET:1,BLOCKQUOTE:1,BUTTON:1,CENTER:1,DD:1,DEL:1,DIR:1,DIV:1,DL:1,DT:1,FIELDSET:1,FORM:1,FRAMESET:1,HR:1,IFRAME:1,INS:1,\r
+               ISINDEX:1,LI:1,MAP:1,MENU:1,NOFRAMES:1,NOSCRIPT:1,OBJECT:1,OL:1,P:1,PRE:1,SCRIPT:1,TABLE:1,TBODY:1,TD:1,TFOOT:1,TH:1,THEAD:1,TR:1,UL:1 },\r
        // Inline Elements - HTML 4.01\r
-       inline : {a:1,abbr:1,acronym:1,applet:1,b:1,basefont:1,bdo:1,big:1,br:1,button:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,iframe:1,img:1,input:1,ins:1,kbd:1,label:1,map:1,object:1,q:1,s:1,samp:1,script:1,select:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,textarea:1,tt:1,u:1,'var':1},\r
-\r
+       inline : {A:1,ABBR:1,ACRONYM:1,APPLET:1,B:1,BASEFONT:1,BDO:1,BIG:1,BR:1,BUTTON:1,CITE:1,CODE:1,DEL:1,DFN:1,EM:1,FONT:1,I:1,IFRAME:1,IMG:1,\r
+               INPUT:1,INS:1,KBD:1,LABEL:1,MAP:1,OBJECT:1,Q:1,S:1,SAMP:1,SCRIPT:1,SELECT:1,SMALL:1,SPAN:1,STRIKE:1,STRONG:1,SUB:1,SUP:1,TEXTAREA:1,TT:1,U:1,VAR:1},\r
        // Elements that you can, intentionally, leave open\r
        // (and which close themselves)\r
-       closeSelf : {colgroup:1,dd:1,dt:1,li:1,options:1,p:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1}, // add tbody\r
+       closeSelf : {OLGROUP:1,DD:1,DT:1,LI:1,OPTIONS:1,P:1,TBODY:1,TD:1,TFOOT:1,TH:1,THEAD:1,TR:1}, // add tbody\r
 \r
        sisters : {\r
-               th : { td : 1 },\r
-               td : { th : 1 },\r
-               dt : { dd : 1 },\r
-               dd : { dt : 1 },\r
-               colgroup : { caption : 1 },\r
-               thead    : { caption : 1, colgroup : 1 },\r
-               tfoot    : { caption : 1, colgroup : 1, thead : 1, tbody : 1 },\r
-               tbody    : { caption : 1, colgroup : 1, thead : 1, tfoot : 1 }\r
+               TH : { TD : 1 },\r
+               TD : { TH : 1 },\r
+               DT : { DD : 1 },\r
+               DD : { DT : 1 },\r
+               COLGROUP : { CAPTION : 1 },\r
+               THEAD    : { CAPTION : 1, COLGROUP : 1 },\r
+               TFOOT    : { CAPTION : 1, COLGROUP : 1, THEAD : 1, TBODY : 1 },\r
+               TBODY    : { CAPTION : 1, COLGROUP : 1, THEAD : 1, TFOOT : 1 }\r
        },\r
        /*\r
         * http://www.tohoho-web.com/html/tbody.htm\r
@@ -44,14 +51,14 @@ X.Dom.Parser = {
        fillAttrs : X.Dom.Attr.noValue, //{checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};\r
 \r
        // Special Elements (can contain anything)\r
-       special : { script : 1, style : 1, plaintext : 1, xmp : 1, textarea : 1 },\r
+       special : { SCRIPT : 1, STYLE : 1, PLAINTEXT : 1, XMP : 1, TEXTAREA : 1 },\r
        \r
        exec : function( html, handler, async ){\r
-               var special        = X.Dom.Parser.special,\r
-                       plainText      = X.Dom.Parser.plainText,\r
+               var special        = X_Dom_Parser.special,\r
+                       //plainText      = X_Dom_Parser.plainText,\r
                        startTime      = async && X.getTime(),\r
-                       _parseStartTag = X.Dom.Parser._parseStartTag,\r
-                       _parseEndTag   = X.Dom.Parser._parseEndTag,\r
+                       _parseStartTag = X_Dom_Parser._parseStartTag,\r
+                       _parseEndTag   = X_Dom_Parser._parseEndTag,\r
                        stack          = async ? async[ 1 ] : [],\r
                        lastHtml       = html,\r
                        chars, last, text, index;\r
@@ -61,8 +68,8 @@ X.Dom.Parser = {
                        last  = stack[ stack.length - 1 ];\r
                        \r
                        // Make sure we're not in a script or style element\r
-                       if ( last && special[ last.toLowerCase() ] === 1 ) {\r
-                               if( 0 <= ( index = html.toLowerCase().indexOf( '</' + last.toLowerCase() ) ) ){\r
+                       if ( last && special[ last ] === 1 ) {\r
+                               if( 0 <= ( index = html.toUpperCase().indexOf( '</' + last ) ) ){\r
                                        handler.chars( html.substring( 0, index ) );\r
                                        if( index = _parseEndTag( stack, handler, html ) ){\r
                                                html = html.substring( index );\r
@@ -119,7 +126,7 @@ X.Dom.Parser = {
                        \r
                        if( async && startTime + 15 <= X.getTime() && html ){\r
                                handler.progress( 1 - html.length / async[ 0 ] );\r
-                               X.Timer.once( 0, X.Dom.Parser.exec, [ html, handler, async ] );\r
+                               X.Timer.once( 0, X_Dom_Parser.exec, [ html, handler, async ] );\r
                                return;\r
                        };\r
                        \r
@@ -127,15 +134,15 @@ X.Dom.Parser = {
                };\r
                \r
                // Clean up any remaining tags\r
-               X.Dom.Parser.parseEndTag( stack, handler );\r
+               X_Dom_Parser.parseEndTag( stack, handler );\r
                \r
                async && handler.complete();\r
        },\r
 \r
        _parseStartTag : function( stack, last, handler, html ){\r
-               var alphabets = X.Dom.Parser.alphabets,\r
-                       whiteSpace = X.Dom.Parser.whiteSpace,\r
-                       saveAttr = X.Dom.Parser.saveAttr,\r
+               var alphabets = X_Dom_Parser.CHARS,\r
+                       whiteSpace = X_Dom_Parser.CHARS,\r
+                       saveAttr = X_Dom_Parser.saveAttr,\r
                        uri   = X.Dom.DTD.ATTR_VAL_IS_URI,\r
                        phase = 0,\r
                        l     = html.length,\r
@@ -151,16 +158,16 @@ X.Dom.Parser = {
                                        chr === '<' && ( ++phase );\r
                                        break;\r
                                case 1 : // タグ名の開始を待つ\r
-                                       alphabets.indexOf( chr ) !== -1 && ( ++phase && ( start = i ) );\r
+                                       ( alphabets[ chr ] & 3 ) && ( ++phase && ( start = i ) );\r
                                        break;\r
                                case 2 : // タグ名の終わりの空白文字を待つ\r
-                                       whiteSpace.indexOf( chr ) !== -1 ?\r
+                                       ( whiteSpace[ chr ] & 16 ) ?\r
                                                ( ++phase && ( tagName = html.substring( start, i ) ) ) :\r
                                        ( chr === '>' || ( empty = html.substr( i, 2 ) === '/>' ) ) &&\r
                                                ( ( tagName = html.substring( start, i ) ) && ( phase = 9 ) );\r
                                        break;\r
                                case 3 : // 属性名の開始を待つ\r
-                                       alphabets.indexOf( chr ) !== -1 ?\r
+                                       ( alphabets[ chr ] & 3 ) ?\r
                                                ( ++phase && ( start = i ) ) :\r
                                        ( chr === '>' || ( empty = html.substr( i, 2 ) === '/>' ) ) &&\r
                                                ( phase = 9 );\r
@@ -168,13 +175,13 @@ X.Dom.Parser = {
                                case 4 : // 属性名の終わりを待つ\r
                                        chr === '=' ?\r
                                                ( ( phase = 6 ) && ( attrName = html.substring( start, i ) ) ) :\r
-                                       whiteSpace.indexOf( chr ) !== -1 &&\r
+                                       ( whiteSpace[ chr ] & 16 ) &&\r
                                                ( ( phase = 5 ) && ( attrName = html.substring( start, i ) ) );\r
                                        break;\r
                                case 5 : // 属性の = または次の属性または htmlタグの閉じ\r
-                                       whiteSpace.indexOf( chr ) !== -1 ?// ie4 未対応の属性には cite = http:// となる\r
+                                       ( whiteSpace[ chr ] & 16 ) ?// ie4 未対応の属性には cite = http:// となる\r
                                                1 :\r
-                                       alphabets.indexOf( chr ) !== -1 ?\r
+                                       ( alphabets[ chr ] & 3 ) ?\r
                                                ( ( phase = 4 ) && ( attrs[ attrs.length ] = attrName ) && ( start = i ) ) :\r
                                        chr === '=' ?\r
                                                ( phase = 6 ) :\r
@@ -184,14 +191,14 @@ X.Dom.Parser = {
                                case 6 : // 属性値の開始 quot を待つ\r
                                        ( chr === '"' || chr === "'" ) ?\r
                                                ( ( phase = 7 ) && ( quot = chr ) && ( start = i + 1 ) ):\r
-                                       whiteSpace.indexOf( chr ) === -1 &&\r
+                                       !( whiteSpace[ chr ] & 16 ) &&\r
                                                ( ( phase = 8 ) && ( start = i ) ); // no quot\r
                                        break;\r
                                case 7 : //属性値の閉じ quot を待つ\r
                                        !escape && ( chr === quot ) && ( phase = 3 ) && saveAttr( attrs, attrName, html.substring( start, i ) );\r
                                        break;\r
                                case 8 : //閉じ quot のない属性の値\r
-                                       whiteSpace.indexOf( chr ) !== -1 ?\r
+                                       ( whiteSpace[ chr ] & 16 ) ?\r
                                                ( ( phase = 3 ) && saveAttr( attrs, attrName, html.substring( start, i ) ) ) :\r
                                        ( chr === '>' ) ?\r
                                                ( ( phase = 9 ) && saveAttr( attrs, attrName, html.substring( start, i ) ) ) :\r
@@ -204,15 +211,15 @@ X.Dom.Parser = {
                };\r
                if( phase === 9 ){\r
                        if( empty ) ++i;\r
-                       if( X.Dom.Parser.parseStartTag( stack, last, handler, tagName, attrs, empty, i ) === false ) return false;\r
+                       if( X_Dom_Parser.parseStartTag( stack, last, handler, tagName.toUpperCase(), attrs, empty, i ) === false ) return false;\r
                        return i;\r
                };\r
                return 0; // error\r
        },\r
 \r
        _parseEndTag : function( stack, handler, html ){\r
-               var alphabets = X.Dom.Parser.alphabets,\r
-                       whiteSpace = X.Dom.Parser.whiteSpace,\r
+               var alphabets = X_Dom_Parser.CHARS,\r
+                       whiteSpace = X_Dom_Parser.CHARS,\r
                        phase = 0,\r
                        l     = html.length,\r
                        i     = 0,\r
@@ -226,10 +233,10 @@ X.Dom.Parser = {
                                        html.substr( i, 2 ) === '</' && ( ++phase && ++i );\r
                                        break;\r
                                case 1 : // タグ名の開始を待つ\r
-                                       alphabets.indexOf( chr ) !== -1 && ( ++phase && ( start = i ) );\r
+                                       ( alphabets[ chr ] & 3 ) && ( ++phase && ( start = i ) );\r
                                        break;\r
                                case 2 : // タグ名の終わりの空白文字を待つ\r
-                                       whiteSpace.indexOf( chr ) !== -1 && ( ++phase );\r
+                                       ( whiteSpace[ chr ] & 16 ) && ( ++phase );\r
                                        ( chr === '>' ) && ( phase = 9 );\r
                                        ( phase !== 2 ) && ( tagName = html.substring( start, i ) );\r
                                        break;\r
@@ -240,7 +247,7 @@ X.Dom.Parser = {
                        ++i;\r
                };\r
                if( phase === 9 ){\r
-                       X.Dom.Parser.parseEndTag( stack, handler, tagName );\r
+                       X_Dom_Parser.parseEndTag( stack, handler, tagName.toUpperCase() );\r
                        return i;\r
                };\r
                return 0; // error\r
@@ -248,7 +255,7 @@ X.Dom.Parser = {
 \r
        saveAttr : function( attrs, name, value ){\r
                name  = name.toLowerCase();\r
-               value = X.Dom.Parser.fillAttrs[ name ] === 1 ? name : value;\r
+               value = X_Dom_Parser.fillAttrs[ name ] === 1 ? name : value;\r
                attrs[ attrs.length ] = {\r
                        name    : name,\r
                        value   : value,\r
@@ -260,18 +267,17 @@ X.Dom.Parser = {
        },\r
 \r
        parseStartTag : function( stack, last, handler, tagName, attrs, unary, index ) {\r
-               var tagLower = tagName.toLowerCase(),\r
-                       inline   = X.Dom.Parser.inline,\r
-                       parseEndTag = X.Dom.Parser.parseEndTag,\r
-                       sisters  = X.Dom.Parser.sisters;\r
-               if ( X.Dom.Parser.block[ tagLower ] === 1 ) {\r
-                       while ( last && inline[ last.toLowerCase() ] === 1 ) {\r
+               var inline   = X_Dom_Parser.inline,\r
+                       parseEndTag = X_Dom_Parser.parseEndTag,\r
+                       sisters  = X_Dom_Parser.sisters;\r
+               if ( X_Dom_Parser.block[ tagName ] === 1 ) {\r
+                       while ( last && inline[ last ] === 1 ) {\r
                                parseEndTag( stack, handler, last );\r
                                last = stack[ stack.length - 1 ];\r
                        };\r
                };\r
-               X.Dom.Parser.closeSelf[ tagLower ] === 1 && ( last === tagName || ( sisters[ tagLower ] && sisters[ tagLower ][ last.toLowerCase() ] === 1 ) ) && parseEndTag( stack, handler, last );\r
-               unary = unary || X.Dom.Parser.empty[ tagName.toUpperCase() ];\r
+               last && X_Dom_Parser.closeSelf[ tagName ] === 1 && ( last === tagName || ( sisters[ tagName ] && sisters[ tagName ][ last ] === 1 ) ) && parseEndTag( stack, handler, last );\r
+               unary = unary || X_Dom_Parser.empty[ tagName ];\r
                !unary && ( stack[ stack.length ] = tagName );\r
                \r
                return handler.start( tagName, attrs, unary, index );\r
@@ -304,7 +310,7 @@ X.Dom._htmlStringToXNode = {
        nest : [],\r
        err : function( html ){\r
                X.Dom._htmlStringToXNode.flat.length = 0;\r
-               X.Dom._htmlStringToXNode.ignoreError !== true && X.Notification.warn( 'X.Dom.Parser() error ' + html );\r
+               X.Dom._htmlStringToXNode.ignoreError !== true && X.Notification.warn( 'X_Dom_Parser() error ' + html );\r
        },\r
        start : function( tagName, attrs, noChild, length ){\r
                var xnode,\r
@@ -352,7 +358,7 @@ X.Dom.parse = function( html, ignoreError ){
        worker.flat = [];\r
        worker.nest.length = 0;\r
        worker.ignoreError = ignoreError;\r
-       X.Dom.Parser.exec( html, worker );\r
+       X_Dom_Parser.exec( html, worker );\r
        ret = worker.flat;\r
        delete worker.flat;\r
        return ret;\r
@@ -369,7 +375,7 @@ X.Dom._asyncHtmlStringToXNode = {
        comment : X.emptyFunction,\r
        \r
        progress : function( pct ){\r
-               this.asyncDispatch( 0, { type : X.Event.PROGRESS, progress : pct } );\r
+               this.asyncDispatch( 0, { type : X.Event.PROGRESS, percent : pct } );\r
        },\r
        complete : function(){\r
                var ret = X.Dom._htmlStringToXNode.flat;\r
@@ -385,6 +391,6 @@ X.Dom.asyncParse = function( html, ignoreError ){
        worker.flat = [];\r
        worker.nest.length = 0;\r
        worker.ignoreError = ignoreError;\r
-       X.Dom.Parser.exec( html, dispatcher, [ html.length, [] ] );\r
+       X_Dom_Parser.exec( html, dispatcher, [ html.length, [] ] );\r
        return dispatcher;\r
 };\r
index 9a017e7..9bcb62f 100644 (file)
@@ -191,7 +191,7 @@ X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT,
        X.Dom.asyncParse( html, true )\r
                .listen( X.Event.PROGRESS,\r
                        function(e){\r
-                               elmProgress.style.width = ( e.progress * 100 | 0 ) + '%';\r
+                               elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';\r
                        }\r
                )\r
                .listenOnce( X.Event.SUCCESS, function( e ){\r
@@ -223,7 +223,7 @@ X.Dom.DOM_IE4 ?
        X.Dom.asyncParse( html, true )\r
                .listen( X.Event.PROGRESS,\r
                        function( e ){\r
-                               elmProgress.style.width = ( e.progress * 100 | 0 ) + '%';\r
+                               elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';\r
                        }\r
                )\r
                .listenOnce( X.Event.SUCCESS,\r
diff --git a/0.6.x/js/06_audio/00_XAudio.js b/0.6.x/js/06_audio/00_XAudio.js
new file mode 100644 (file)
index 0000000..b4cb185
--- /dev/null
@@ -0,0 +1,132 @@
+X.Audio = {\r
+       HTML5       : 1,\r
+       Flash       : 2,\r
+       SilverLight : 3,\r
+       Unity       : 4,\r
+       WMP         : 5,\r
+       RealPlayer  : 6,\r
+       QuickTime   : 7,\r
+       \r
+       create : function( sourceList, opt_option ){\r
+               return new X_AudioProxy( X.Type.isArray( sourceList ) ? X.copyArray( sourceList ) : [ sourceList ], opt_option || {} );\r
+       }\r
+};\r
+\r
+var X_Audio_BACKENDS = [];\r
+\r
+function X_Audio_detectBackend( proxy, sourceList, option ){\r
+       var source = sourceList.shift() || '', \r
+               parts  = source.split( '?' )[ 0 ].split( '#' )[ 0 ].split( '.' ),\r
+               ext    = parts[ parts.length - 1 ],\r
+               backend, ext, sup;\r
+       \r
+       if( source && X_Audio_BACKENDS.length ){\r
+               sup      = [ proxy, option, sourceList, source, ext ];\r
+               sup[ 5 ] = sup;\r
+               X_Audio_BACKENDS[ 0 ]\r
+                       .detect( source, ext )\r
+                       .listenOnce( [ 'support', 'nosupport' ], X_Audio_detectComplete, sup );\r
+       } else {\r
+               proxy.asyncDispatch( 0, 'nobackend' );\r
+       };\r
+};\r
+\r
+function X_Audio_detectComplete( e, proxy, option, sourceList, source, ext, sup ){\r
+       var i = X_Audio_BACKENDS.indexOf( this ), backend;\r
+       \r
+       this.unlisten( [ 'support', 'nosupport' ], X_Audio_detectComplete, sup );\r
+       \r
+       switch( e.type ){\r
+               case 'support' :\r
+                       proxy._backend = i;\r
+                       proxy.asyncDispatch( 0, { type : 'backendfound', option : option, source : source } );\r
+                       break;\r
+               case 'nosupport' :\r
+                       if( backend = X_Audio_BACKENDS[ i + 1 ] ){\r
+                               backend.detect( source, ext ).listen( [ 'support', 'nosupport' ], X_Audio_detectComplete, sup );\r
+                       } else\r
+                       if( sourceList.length ){\r
+                               X_Audio_detectBackend( proxy, sourceList, option );\r
+                       } else {\r
+                               proxy.asyncDispatch( 0, 'nobackend' );\r
+                       };\r
+                       break;\r
+       };\r
+};\r
+\r
+\r
+X_AudioProxy = X.EventDispatcher.inherits(\r
+       'X.AV.AudioProxy',\r
+       X.Class.POOL_OBJECT,\r
+       {\r
+               source      : '',\r
+               backendName : '',\r
+               _backend    : -1,\r
+               \r
+               Constructor : function( sourceList, option ){\r
+                       X_Audio_detectBackend( this, sourceList, option );\r
+                       this.listenOnce( [ 'backendfound', 'nobackend', X.Event.KILL_INSTANCE ], X_AudioProxy_handleEvent );\r
+               },\r
+               \r
+               close : function(){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].close.call( this );\r
+               },\r
+               \r
+               play : function( position ){\r
+                       //console.log( 'proxy play ' + this._backend );\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].play.call( this, position );\r
+               },\r
+               \r
+               pause : function(){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].pause.call( this );\r
+               },\r
+               \r
+               stop : function(){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].stop.call( this );\r
+               },\r
+               \r
+               loop : function( v ){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].loop.call( this, v );\r
+               },\r
+\r
+               state : function(){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].state.call( this );\r
+               },\r
+\r
+               volume : function( v ){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].volume.call( this, v );\r
+               },\r
+\r
+               startTime : function( time ){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].startTime.call( this, time );\r
+               },\r
+\r
+               currentTime : function( time ){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].currentTime.call( this, time );\r
+               },\r
+\r
+               isPlaying : function(){\r
+                       return this._backend !== -1 && X_Audio_BACKENDS[ this._backend ].isPlaying.call( this );\r
+               }\r
+               \r
+       }\r
+);\r
+\r
+function X_AudioProxy_handleEvent( e ){\r
+       switch( e.type ){\r
+               case 'backendfound' :\r
+                       this.unlisten( 'nobackend', X_AudioProxy_handleEvent );\r
+                       this.source = e.source;\r
+                       this.backendName = X_Audio_BACKENDS[ this._backend ].backendName;\r
+                       X_Audio_BACKENDS[ this._backend ].register( this, e.source, e.option );\r
+                       break;\r
+               \r
+               case 'nobackend' :\r
+                       this.kill();\r
+                       break;\r
+               \r
+               case X.Event.KILL_INSTANCE :\r
+                       this.close();\r
+                       break;\r
+       };\r
+};\r
diff --git a/0.6.x/js/06_audio/01_XHTML5Audio.js b/0.6.x/js/06_audio/01_XHTML5Audio.js
new file mode 100644 (file)
index 0000000..a044ef2
--- /dev/null
@@ -0,0 +1,321 @@
+/*\r
+ * original : uupaa-js HTML5Audio.js\r
+ * https://code.google.com/p/uupaa-js/source/browse/trunk/0.8/src/Audio/HTML5Audio.js?r=568\r
+ */\r
+\r
+var X_Audio_HTML5Audio, X_Audio_HTML5AudioWrapper, X_Audio_rawAudio,\r
+       X_Audio_HTML5Audio_LIVE_LIST = [],\r
+       X_Audio_HTML5Audio_POOL_LIST = [];\r
+       \r
+\r
+if( window.HTMLAudioElement ){\r
+       \r
+       function getHTML5AudioWrapper( proxy ){\r
+               var i = X_Audio_HTML5Audio_LIVE_LIST.length;\r
+               for( ; i; ){\r
+                       if( X_Audio_HTML5Audio_LIVE_LIST[ --i ].proxy === proxy ) return X_Audio_HTML5Audio_LIVE_LIST[ i ];\r
+               };\r
+       };\r
+       \r
+       X_Audio_HTML5Audio = X.Class._override(\r
+               new X.EventDispatcher(),\r
+               {\r
+                       backendName : 'HTML5 Audio',\r
+               /*\r
+                * HTML5 の audio 要素と video 要素でサポートされているメディアフォーマット\r
+                * https://developer.mozilla.org/ja/docs/Web/HTML/Supported_media_formats\r
+                * \r
+                * 主要ブラウザのHTML5 audioタグで使えるファイル形式の再生対応状況を調べてみた\r
+                * http://sothis.blog.so-net.ne.jp/2010-10-27\r
+                * ダメ元で仕様に含まれていない SHOUTcast もテストしてみました。\r
+                * \r
+                * IE9 の HTML5 Audio について\r
+                * http://kentablog.cluscore.com/2011/05/ie9-html5-audio.html\r
+                * 1.Audioオブジェクトを作ることができないので、Audioタグを使う\r
+                * 2.クロスドメインアクセスには、「clientaccesspolicy.xml」か「crossdomain.xml」が必要\r
+                * 3.wav が不可\r
+                * \r
+                * IE9でHTML5 autio タグが無効になる\r
+                * http://bbs.wankuma.com/index.cgi?mode=al2&namber=64886&KLOG=109\r
+                *  IEのバージョン9.0.8112.16421では、Audioオブジェクトのnewも対応してました。\r
+                *  createElement等で動的生成すると、よろしくない\r
+                * \r
+                * media-can-play-wav-audio.html\r
+                * https://github.com/adobe/webkit/blob/master/LayoutTests/media/media-can-play-wav-audio.html\r
+                * testExpected("audio.canPlayType('audio/wav; codecs=1')", "probably");\r
+                * \r
+                * HTML5 audioタグ ブラウザ間の違い\r
+                * http://wiki.bit-hive.com/tomizoo/pg/HTML5%20audio%A5%BF%A5%B0%20%A5%D6%A5%E9%A5%A6%A5%B6%B4%D6%A4%CE%B0%E3%A4%A4\r
+                *  - volume, muted iPhone(iOS4-6)、Android(2.3.6)では動作せず。\r
+                *  - FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。iPhoneはload()が不要。\r
+                */     \r
+                       detect : function( source, ext ){\r
+                               var ok, mineType;\r
+                               switch( ext ){\r
+                                       case 'mp3' :\r
+                                               ok = X.UA.IE || X.UA.Chrome || ( X.UA.OS === 'windows' && X.UA.Safari );\r
+                                               mineType = 'audio/mpeg';\r
+                                               break;\r
+                                       case 'ogg' :\r
+                                               ok = 15 <= X.UA.Gecko || X.UA.Chrome || X.UA.Opera;\r
+                                               mineType = 'audio/ogg';\r
+                                               break;\r
+                                       case 'm4a' :\r
+                                               ok = X.UA.IE || X.UA.WebKit;\r
+                                               mineType = 'audio/mp4';\r
+                                               break;\r
+                                       case 'webm' :\r
+                                               ok = 2 <= X.UA.Gecko || 10.6 <= X.UA.Opera; // firefox4+(Gecko2+)\r
+                                               mineType = 'audio/webm';\r
+                                               break;\r
+                                       case 'wav' :\r
+                                               ok = X.UA.Gecko || X.UA.Opera || ( X.UA.OS === 'windows' && X.UA.Safari );\r
+                                               mineType = 'audio/wav'; // audio/x-wav ?\r
+                                               break;\r
+                               };\r
+                               \r
+                               if( !ok && mineType ){\r
+                                       if( !X_Audio_rawAudio ) X_Audio_rawAudio = new Audio;\r
+                                       ok = X_Audio_rawAudio.canPlayType( mineType );\r
+                               };\r
+                               \r
+                               // TODO canPlay\r
+                               this.asyncDispatch( 0, ok ? 'support' : 'nosupport' );\r
+                               \r
+                               return this;\r
+                       },\r
+                       \r
+                       register : function( proxy, source, option ){\r
+                               X_Audio_HTML5Audio_LIVE_LIST.push( new X_Audio_HTML5AudioWrapper( proxy, source, option ) );\r
+                       },\r
+                       \r
+                       close : function(){\r
+                               return getHTML5AudioWrapper( this ).close();\r
+                       },\r
+                       \r
+                       play : function( position ){\r
+                               return getHTML5AudioWrapper( this ).play( position );\r
+                       },\r
+                       \r
+                       pause : function(){\r
+                               return getHTML5AudioWrapper( this ).pause();\r
+                       },\r
+                       \r
+                       stop : function(){\r
+                               return getHTML5AudioWrapper( this ).stop();\r
+                       },\r
+                       \r
+                       loop : function( v ){\r
+                               return getHTML5AudioWrapper( this ).loop( v );\r
+                       },\r
+       \r
+                       state : function(){\r
+                               return getHTML5AudioWrapper( this ).state();\r
+                       },\r
+       \r
+                       volume : function( v ){\r
+                               return getHTML5AudioWrapper( this ).volume( v );\r
+                       },\r
+       \r
+                       startTime : function( time ){\r
+                               return getHTML5AudioWrapper( this ).startTime( time );\r
+                       },\r
+       \r
+                       currentTime : function( time ){\r
+                               return getHTML5AudioWrapper( this ).currentTime( time );\r
+                       },\r
+       \r
+                       isPlaying : function(){\r
+                               return getHTML5AudioWrapper( this ).isPlaying();\r
+                       }\r
+               }\r
+       );\r
+       \r
+       X_Audio_BACKENDS.push( X_Audio_HTML5Audio );\r
+       \r
+       X_Audio_HTML5AudioWrapper = X.EventDispatcher.inherits(\r
+               'X.AV.HTML5AudioWrapper',\r
+               X.Class.POOL_OBJECT,\r
+               {\r
+                       \r
+                       proxy           : null,\r
+                       xnodeAudio      : null,\r
+                       rawAudio        : null,\r
+                       \r
+                       _closed         : true,\r
+                       _lastUserAction : '',\r
+                       \r
+                       _loop           : false,\r
+                       _startTime      : 0,\r
+                       _volume         : 0.5,\r
+                       _autoplay       : false,\r
+                       \r
+                       Constructor : function( proxy, source, option ){\r
+                               this.proxy   = proxy;\r
+                               this._closed = false;\r
+                               \r
+                               if( option.loop )      this._loop      = true;\r
+                               if( option.startTime ) this._startTime = option.startTime;\r
+                               if( option.volume )    this._volume    = option.volume;\r
+                               \r
+                               this.xnodeAudio = new X.EventDispatcher( this.rawAudio = X_Audio_rawAudio || new Audio( source ) )//X.Dom.Node.create( 'audio', { src : source } ).appendToRoot();//( X.Dom.Node._systemNode );\r
+                                       .listen( [\r
+                                               'loadstart', 'load', 'progress', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'play', 'pause', 'loadedmetadata',\r
+                                               'loadeddata', 'waiting', 'playing', 'canplay', 'canplaythrough', 'seeking', 'seeked', 'timeupdate', 'ended',\r
+                                               'ratechange', 'durationchange', 'volumechange' ], this, this.handleEventProxy );                                \r
+                               if( X_Audio_rawAudio ){\r
+                                       X_Audio_rawAudio.src = source;\r
+                                       X_Audio_rawAudio.load(); // 要る?\r
+                                       X_Audio_rawAudio = null;\r
+                               };\r
+\r
+                               this.rawAudio.volume   = this._volume;\r
+                               this.rawAudio.autoplay = false;\r
+                               option.autoplay && X.Timer.once( 100, this, this.play );\r
+                               \r
+                               this.listenOnce( X.Event.KILL_INSTANCE );\r
+                       },\r
+                       \r
+                       handleEvent : function( e ){\r
+                               switch( e.type ){\r
+\r
+                                       case X.Event.KILL_INSTANCE :\r
+                                               this.xnodeAudio.unlisten();\r
+                                               this.xnodeAudio.kill(); // <img> と同じく <audio> は pool した方がいいかも\r
+                                               break;\r
+                               };\r
+                       },\r
+                       /*\r
+                        * http://uguisu.skr.jp/html/table3.html\r
+                        */\r
+                       handleEventProxy : function( e ){\r
+                               switch( e.type ){\r
+                                       case 'loadstart' :      //      ブラウザがコンテンツの検索を開始した場合に発生\r
+                                               break;\r
+                                       case 'progress' :       //      ブラウザがコンテンツの取得を実行した場合に発生\r
+                                               console.log( e.loaded / e.total );\r
+                                               break;\r
+                                       case 'suspend' :        //      ブラウザが意図的にコンテンツの取得を現在行っていない場合に発生(ダウンロードは未完了)\r
+                                       case 'abort' :          //      ダウンロードの完了前にコンテンツの取得を停止した場合に発生(この停止はエラーによるものではない)\r
+                                       case 'error' :          //      コンテンツの取得実行中にエラーが発生した場合に発生\r
+                                       case 'emptied' :        //      読み込み中に致命的なエラーが発生したか、実行状態ででload()メソッドが実行された場合に発生\r
+                                       case 'stalled' :        //      ブラウザがコンテンツの取得を試みたが、データがまだ用意されていない場合に発生\r
+                                       case 'play' :           //      再生が開始された。play()メソッドからの復帰後に発生する場合に発生\r
+                                       case 'pause' :          //      再生が一時停止された。pauseメソッドからの復帰後に発生する場合に発生\r
+                                       case 'loadedmetadata' : //      ブラウザがメディアリソースの長さと寸法を判定した場合に発生\r
+                                       case 'loadeddata' :     //      コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生\r
+                                       case 'waiting' :        //      次のフレームが利用不可のため再生を停止したが、そのフレームがやがて利用可能になると想定している場合に発生\r
+                                       case 'playing' :        //      再生が開始された場合に発生\r
+                                       case 'canplay' :        //      今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生\r
+                                       case 'canplaythrough' : //      今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生\r
+                                       case 'seeking' :        //      シークがtrueに変化し、イベントを発生させるのに十分な時間がシーク操作にかかっている場合に発生\r
+                                       case 'seeked' :         //      シークがfalseに変化した場合に発生\r
+                                       case 'timeupdate' :     //      通常の再生が行われ現在の再生位置の変化が起こった場合に発生\r
+                                               break;\r
+                                       \r
+                                       case 'ended' :\r
+                                               //!this._closed && this._lastUserAction !== 'stop' && this._loop && this.play();\r
+                                               break;\r
+       \r
+                                       case 'ratechange' :     // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生\r
+                                       case 'durationchange' : // duration属性が更新された場合に発生\r
+                                       case 'volumechange' :   // volume属性とmuted属性のどちらかが変化した場合に発生\r
+                               };\r
+                               \r
+                               //console.log( 'html5 ' + e.type + ' ' + ( this.proxy._listeners && this.proxy._listeners[ e.type ] && this.proxy._listeners[ e.type ].length ) );\r
+                               //e.type === 'canplaythrough' && console.dir( e );\r
+                               this.proxy.dispatch( e );\r
+                       },\r
+                       \r
+                       close : function(){\r
+                               // pool, proxy を外す\r
+                               //this.kill();\r
+                       },\r
+                       \r
+                       play : function( position ){\r
+                               // もし kill 後に autoplayTimer で呼ばれても、_closed==true なので平気\r
+                           if( this._closed ) return;\r
+                           this._lastUserAction = 'play';\r
+                       \r
+                           if( X.UA.Chrome ){ // [CHROME][FIX] volume TODO どの version で 修正される?\r
+                               // [!] delay\r
+                               X.Timer.once( 0, this, this._fixForChrome, [ this.rawAudio.volume ] );\r
+                               this.rawAudio.volume = 0;\r
+                           };\r
+                           \r
+                           if( !this.rawAudio.paused ){\r
+                               this.currentTime( this._startTime );\r
+                           };\r
+                           this.rawAudio.play();\r
+                       },\r
+                       \r
+                       // [CHROME][FIX] volume\r
+                       _fixForChrome : X.UA.Chrome && function( volume ){\r
+                               !this._closed && ( this.rawAudio.volume = volume );\r
+                       },\r
+                       \r
+                       pause : function(){\r
+                           if( !this._closed && !this.rawAudio.error ){\r
+                               this._lastUserAction = 'pause';\r
+                               this.rawAudio.pause();          \r
+                           };\r
+                       },\r
+                       \r
+                       stop : function(){\r
+                           if( !this._closed && !this.rawAudio.error ){\r
+                               this._lastUserAction = 'stop';\r
+                               this.rawAudio.pause();\r
+                               this.currentTime( this._startTime );\r
+                           };\r
+                       },\r
+                       \r
+                       loop : function( v ){\r
+                           if( v === undefined ) return this._loop;\r
+                           this.rawAudio.loop = this._loop = v;\r
+                       },\r
+       \r
+                       state : function(){\r
+                           var paused = !!this.rawAudio.paused,\r
+                               ended  = !!this.rawAudio.ended;\r
+                       \r
+                           if( this._lastUserAction === 'stop' ){\r
+                               if( paused ){\r
+                                   paused = false;\r
+                                   ended  = true;\r
+                               };\r
+                           };\r
+                       \r
+                           return {\r
+                               loop     : this.rawAudio.loop,\r
+                               error    : this.rawAudio.error    || 0,   // 0, 1 ~ 4\r
+                               paused   : paused,\r
+                               ended    : ended,\r
+                               source   : this.rawAudio.src      || '',\r
+                               duration : this.rawAudio.duration || 0\r
+                           };\r
+                       },\r
+       \r
+                       volume : function( v ){\r
+                           if( v === undefined ) return this.audio.volume;\r
+                           this.rawAudio.volume = v;\r
+                       },\r
+       \r
+                       startTime : function( time ){\r
+                           if( time === undefined ) return this._startTime;\r
+                           this._startTime = time;\r
+                       },\r
+       \r
+                       currentTime : function( time ){\r
+                           if( time === undefined ) return this.rawAudio.currentTime;\r
+                           this.rawAudio.currentTime = time;\r
+                       },\r
+       \r
+                       isPlaying : function(){\r
+                           return !this.rawAudio.error && !this.rawAudio.paused && !this.rawAudio.ended;\r
+                       }\r
+       \r
+               }\r
+       );\r
+       \r
+};\r
+\r
index 5d75604..08767db 100644 (file)
@@ -30,7 +30,13 @@ document.write( [
                \r
                'js/04_net/00_XNet.js',\r
                'js/04_net/01_XNetXHR.js',\r
-               'js/04_net/02_XNetJSONP.js'\r
+               'js/04_net/02_XNetJSONP.js',\r
+               'js/04_net/03_XNetForm.js',\r
+               'js/04_net/04_XNetImage.js',\r
+               \r
+               'js/06_audio/00_XAudio.js',\r
+               'js/06_audio/01_XHTML5Audio.js' \r
+               \r
        + '"></script>'\r
 ].join( '"></script><script src="' ));\r
 \r