From: itozyun Date: Tue, 30 Sep 2014 13:16:03 +0000 (+0900) Subject: Version 0.6.87, fix SuperConstructor @ X.Class & force convert to PointerEvent @... X-Git-Url: http://git.osdn.jp/view?a=commitdiff_plain;h=ee1651f04c1539d15db006d6285a4ff77c546613;p=pettanr%2FclientJs.git Version 0.6.87, fix SuperConstructor @ X.Class & force convert to PointerEvent @ X.Dom.Event. --- diff --git a/0.6.x/index.html b/0.6.x/index.html index 457d051..27f8468 100644 --- a/0.6.x/index.html +++ b/0.6.x/index.html @@ -12,29 +12,7 @@ - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/0.6.x/js/00_core/00_X.js b/0.6.x/js/00_core/00_X.js index 2a9cfe3..f1293b8 100644 --- a/0.6.x/js/00_core/00_X.js +++ b/0.6.x/js/00_core/00_X.js @@ -8,7 +8,8 @@ if( !window['console'] || ( window.parent && window.parent.log ) ) console = { l } }; var undefined, - X = new Function( 'return X._shortcut && X._shortcut.apply( X._shortcut, arguments )' ); + X = new Function( 'return X._shortcut && X._shortcut.apply( X._shortcut, arguments )' ), + X_TEMP = {}; X.VERSION = '0.6.50'; @@ -61,6 +62,38 @@ X.cloneObject = function( src ){ return ret; }; +X.deepCopy = function( src ){ + function clone( src, objSrc, objCopy, n ) { + var ret, i, key; + if( !src ){ // 0, "", null, undefined, NaN, false + return src; + } else + if( X.Type.isArray( src ) ){ + i = objSrc.indexOf( src ); + if( i !== -1 ) return objCopy[ i ]; + objSrc[ ++n ] = src; + objCopy[ n ] = ret = []; + } else + if( X.Type.isObject( src ) ){ + i = objSrc.indexOf( src ); + if( i !== -1 ) return objCopy[ i ]; + objSrc[ ++n ] = src; + objCopy[ n ] = ret = {}; + } else { + // string, number, true + return src; + }; + for( key in src ){ + ret[ key ] = clone( src[ key ], objSrc, objCopy, n ); + }; + return ret; + }; + return clone( src, [], [], -1 ); +}; + + + + X.copyArray = function( ary ){ var ret = [], i = ary.length; if( !i ) return ret; diff --git a/0.6.x/js/00_core/04_XClass.js b/0.6.x/js/00_core/04_XClass.js index 28fc4ad..ae07f5e 100644 --- a/0.6.x/js/00_core/04_XClass.js +++ b/0.6.x/js/00_core/04_XClass.js @@ -17,6 +17,8 @@ var X_Class_CLASS_LIST = [], X_Class_DEF_LIST = [], X_Class_PRIVATE_CLASS_LIST = [], X_Class_PRIVATE_DEF_LIST = [], + X_Class_CALLING_SUPER = [], + X_Class_CALL_SUPER_STACK = [], X_Class_killPrivateFlag = false, X_Class_traits = null, X_Class_useObjectCreate = false, // !!Object.create, http://jsperf.com/prototype-vs-object-create-perf @@ -458,10 +460,39 @@ function X_Class_actualConstructor( args ){ }; return instance; }; - +/* クラス定義を辿ってスーパークラスのコンストラクタを探す。 + * 呼び出したコンストラクタは配列に控える。 + * さらに呼ばれた場合、配列を元にさらに奥のコンストラクタを取得 + * TODO 現在 new しているインスタンスを保持してチェックする + */ function X_Class_superConstructor(){ - var s = X_Class_getClassDef( this ).SuperConstructor; - return s && s.apply( this, arguments ); + var sClass = this, + i = X_Class_CALLING_SUPER.indexOf( sClass ), + n = -1, + l, sList, def, sConst, ret; + + if( i === -1 ){ + X_Class_CALLING_SUPER[ l = X_Class_CALLING_SUPER.length ] = sClass; + X_Class_CALL_SUPER_STACK[ l ] = sList = []; + } else { + sList = X_Class_CALL_SUPER_STACK[ i ]; + }; + + while( sClass ){ + def = X_Class_getClassDef( sClass ); + sClass = def.SuperClass; + sConst = def.SuperConstructor; + if( sConst && sList[ ++n ] !== sConst ){ + sList[ n ] = sConst; + ret = sConst.apply( this, arguments ); + --sList.length; + if( !sList.length ){ + X_Class_CALLING_SUPER.splice( i, 1 ); + X_Class_CALL_SUPER_STACK.splice( i, 1 ); + }; + return ret; + }; + }; }; console.log( 'X.Core.Class' ); diff --git a/0.6.x/js/00_core/06_XEventDispatcher.js b/0.6.x/js/00_core/06_XEventDispatcher.js index 4f1f136..e71c638 100644 --- a/0.6.x/js/00_core/06_XEventDispatcher.js +++ b/0.6.x/js/00_core/06_XEventDispatcher.js @@ -19,16 +19,17 @@ X.Event = { COMPLETE : 1, - SUCCESS : 2, - ERROR : 3, - PROGRESS : 4, - BEFORE_CANCEL : 5, - CANCELED : 6, - TIMEOUT : 7, - BEFORE_KILL_INSTANCE : 8, - KILL_INSTANCE : 9, - KILL_INSTANCE_CANCELED : 10, - _LAST_EVENT : 10 + READY : 2, + SUCCESS : 3, + ERROR : 4, + PROGRESS : 5, + BEFORE_CANCEL : 6, + CANCELED : 7, + TIMEOUT : 8, + BEFORE_KILL_INSTANCE : 9, + KILL_INSTANCE : 10, + KILL_INSTANCE_CANCELED : 11, + _LAST_EVENT : 11 }; // ------------------------------------------------------------------------- // @@ -215,7 +216,9 @@ X.EventDispatcher = * @param {Array=} opt_arg3 */ listening : function( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ - var list = this._listeners, unlistens, i, f, hash; + var list = this._listeners, + unlistens, i, f, hash; + if( opt_type === undefined ) return !!list; if( !list || !( list = list[ opt_type ] ) ) return false; if( opt_arg1 === undefined ) return true; @@ -274,7 +277,8 @@ function X_EventDispatcher_dispatch( e ){ if( !type ){ e = { type : type = e }; }; - e.target = e.target || this; + e.target = e.target || this; + e.currentTarget = e.currentTarget || this; ++this._dispatching; @@ -310,7 +314,7 @@ function X_EventDispatcher_dispatch( e ){ if( r & X.Callback.STOP_NOW ){ sysOnly = true; }; - ret |= r; + ret |= X.Type.isFinite( r ) ? r : 0; }; if( ( --this._dispatching ) === 0 ){ @@ -358,7 +362,7 @@ function X_EventDispatcher_dispatch( e ){ */ function X_EventDispatcher_listen( type, opt_arg1, opt_arg2, opt_arg3 ){ var list = this._listeners, - i, r, f; + i, raw, f; if( this._dispatching ){ if( !this._reserves ) this._reserves = []; @@ -373,7 +377,8 @@ function X_EventDispatcher_listen( type, opt_arg1, opt_arg2, opt_arg3 ){ return this; }; - ( !list || !list[ type ] ) && X.Type.isString( type ) && X_EventDispatcher_actualAddEvent( this, type ); + raw = this._rawObject || this._ie4getRawNode && this._ie4getRawNode(); + raw && ( !list || !list[ type ] ) && X.Type.isString( type ) && X_EventDispatcher_actualAddEvent( this, type, raw ); if( this.listening( type, opt_arg1, opt_arg2, opt_arg3 ) ) return this; @@ -398,7 +403,7 @@ function X_EventDispatcher_listen( type, opt_arg1, opt_arg2, opt_arg3 ){ */ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ var list = this._listeners, - _list, reserves, unlistens, i, f; + _list, reserves, unlistens, i, f, raw; if( !list ) return this; if( X.Type.isArray( opt_type ) ){ @@ -455,7 +460,8 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ _list.splice( i, 1 ); if( !_list.length ){ delete this._listeners[ opt_type ]; - X.Type.isString( opt_type ) && X_EventDispatcher_actualRemoveEvent( this, opt_type ); + raw = this._rawObject || this._ie4getRawNode && this._ie4getRawNode(); + raw && X.Type.isString( opt_type ) && X_EventDispatcher_actualRemoveEvent( this, opt_type, raw ); if( X.isEmptyObject( this._listeners ) ) delete this._listeners; }; }; @@ -467,31 +473,29 @@ var X_EventDispatcher_actualAddEvent = // Days on the Moon DOM Events とブラウザの実装 // http://nanto.asablo.jp/blog/2007/03/23/1339502 // Safari 2 では関数オブジェクトしか EventListener として使えませんが、Safari のナイトリービルドでは handleEvent メソッドを持つオブジェクトも EventListener として使えるようです。 - X_EventDispatcher_temp.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3- - (function( that, type ){ - var raw = that._rawObject; - if( !raw ) return; - that._handleEvent = that._handleEvent || X.Callback.create( that, X_EventDispatcher_actualHandleEvent ); - type = X.Dom.Event.Rename[ type] || type; - if( raw.addEventListener ){ - raw.addEventListener( type, that._handleEvent, false ); + X_EventDispatcher_temp.EVENT_W3C /* && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) */ ? // Safari3- + (function( that, type, raw ){ + var i; + + type = X.Dom.Event.Rename[ type ] || type; + + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualAddEvent( that, type[ --i ], raw ); + }; } else { - // Safari は Image, Opera7 は window - raw[ 'on' + type ] = that._handleEvent; - }; - }) : - X_EventDispatcher_temp.EVENT_W3C ? - (function( that, type ){ - if( that._rawObject ){ - that._handleEvent = that._handleEvent || X.Callback.create( that, X_EventDispatcher_actualHandleEvent ); - that._rawObject.addEventListener( X.Dom.Event.Rename[ type ] || type, that._handleEvent, false ); + that._handleEvent || ( that._handleEvent = X.Callback.create( that, X_EventDispatcher_actualHandleEvent ) ); + + if( raw.addEventListener ){ + raw.addEventListener( type, that._handleEvent, false ); + } else { + // Safari は Image, Opera7 は window + raw[ 'on' + type ] = that._handleEvent; + }; }; }) : X_EventDispatcher_temp.EVENT_IE ? - (function( that, type ){ - var raw = that._rawObject; - if( !raw ) return; - type = X.Dom.Event.Rename[ type ] || type; + (function( that, type, raw ){ //if( type === 'load' && that._tag && X.Dom.Event._LOAD_FIX_TAGS[ that._tag ] ){ // type = 'readystatechange'; //}; @@ -499,55 +503,61 @@ var X_EventDispatcher_actualAddEvent = // ie8- の XHR は window.event が更新されないため, eventType 毎に callback を指定する raw[ 'on' + type ] = X.Callback.create( that, X_EventDispatcher_dispatch, [ type ] ); } else { - that._handleEvent = that._handleEvent || X.Callback.create( that, X_EventDispatcher_actualHandleEvent ); + type = X.Dom.Event.Rename[ type ] || type; - if( raw.attachEvent ){ - raw.attachEvent( 'on' + type, that._handleEvent ); - } else { - raw[ 'on' + type ] = that._handleEvent; + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualAddEvent( that, type[ --i ], raw ); + }; + } else{ + that._handleEvent || ( that._handleEvent = X.Callback.create( that, X_EventDispatcher_actualHandleEvent ) ); + + if( raw.attachEvent ){ + raw.attachEvent( 'on' + type, that._handleEvent ); + } else { + raw[ 'on' + type ] = that._handleEvent; + }; }; }; - }) : - (function( that, type ){ - var raw = that._rawObject || ( that._ie4getRawNode && that._ie4getRawNode() ); - if( !raw ) return; - raw[ 'on' + ( X.Dom.Event.Rename[ type ] || type ) ] = that._handleEvent = that._handleEvent || X.Callback.create( that, X_EventDispatcher_actualHandleEvent ); + (function( that, type, raw ){ + var i; + type = X.Dom.Event.Rename[ type ] || type; + + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualAddEvent( that, type[ --i ], raw ); + }; + } else { + raw[ 'on' + type ] = that._handleEvent || ( that._handleEvent = X.Callback.create( that, X_EventDispatcher_actualHandleEvent ) ); + }; }); var X_EventDispatcher_actualRemoveEvent = - X_EventDispatcher_temp.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3- - (function( that, type ){ - var raw = that._rawObject; - if( !raw ) return; + X_EventDispatcher_temp.EVENT_W3C /*&& ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 )*/ ? // Safari3- + (function( that, type, raw, opt_skip ){ type = X.Dom.Event.Rename[ type ] || type; - if( raw.addEventListener ){ // Image - raw.removeEventListener( type, that._handleEvent, false ); + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualRemoveEvent( that, type[ --i ], raw, !!i ); + }; } else { - raw[ 'on' + type ] = null; - }; - if( !that._listeners ){ - X.Callback._correct( that._handleEvent ); - delete that._handleEvent; - }; - }) : - X_EventDispatcher_temp.EVENT_W3C ? - (function( that, type ){ - var raw = that._rawObject; - if( !raw ) return; - raw.removeEventListener( X.Dom.Event.Rename[ type ] || type, that._handleEvent, false ); - if( !that._listeners ){ - X.Callback._correct( that._handleEvent ); - delete that._handleEvent; + if( raw.addEventListener ){ // Image + raw.removeEventListener( type, that._handleEvent, false ); + } else { + raw[ 'on' + type ] = null; + }; + if( !opt_skip && !that._listeners ){ + X.Callback._correct( that._handleEvent ); + delete that._handleEvent; + }; }; }) : X_EventDispatcher_temp.EVENT_IE ? - (function( that, type ){ - var raw = that._rawObject; - if( !raw ) return; - type = X.Dom.Event.Rename[ type ] || type; + (function( that, type, raw, opt_skip ){ + var i; //if( type === 'load' && that._tag && X.Dom.Event._LOAD_FIX_TAGS[ that._tag ] ){ // type = 'readystatechange'; //}; @@ -556,28 +566,41 @@ var X_EventDispatcher_actualRemoveEvent = raw[ 'on' + type ] = X.emptyFunction; raw[ 'on' + type ] = ''; } else { - if( raw.attachEvent ){ - raw.detachEvent( 'on' + type, that._handleEvent ); + type = X.Dom.Event.Rename[ type ] || type; + + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualRemoveEvent( that, type[ --i ], raw, !!i ); + }; } else { - raw[ 'on' + type ] = X.emptyFunction; - raw[ 'on' + type ] = ''; + if( raw.attachEvent ){ + raw.detachEvent( 'on' + type, that._handleEvent ); + } else { + raw[ 'on' + type ] = X.emptyFunction; + raw[ 'on' + type ] = ''; + }; + + if( !opt_skip && !that._listeners ){ + X.Callback._correct( that._handleEvent ); + delete that._handleEvent; + }; }; - - if( !that._listeners ){ - X.Callback._correct( that._handleEvent ); - delete that._handleEvent; - }; }; }) : - (function( that, type ){ - var raw = that._rawObject || ( that._ie4getRawNode && that._ie4getRawNode() ); - if( !raw ) return; + (function( that, type, raw, opt_skip ){ + var i; type = X.Dom.Event.Rename[ type ] || type; - raw[ 'on' + type ] = X.emptyFunction; - raw[ 'on' + type ] = ''; - if( !that._listeners ){ - X.Callback._correct( that._handleEvent ); - delete that._handleEvent; + if( X.Type.isArray( type ) ){ + for( i = type.length; i; ){ + X_EventDispatcher_actualRemoveEvent( that, type[ --i ], raw, !!i ); + }; + } else { + raw[ 'on' + type ] = X.emptyFunction; + raw[ 'on' + type ] = ''; + if( !opt_skip && !that._listeners ){ + X.Callback._correct( that._handleEvent ); + delete that._handleEvent; + }; }; }); @@ -586,15 +609,15 @@ var X_EventDispatcher_actualRemoveEvent = // Is this in regard to the Safari 1.x preventDefault bug on click/dblclick? // https://groups.google.com/forum/#!msg/comp.lang.javascript/uYEuCHjHxnw/yKoHtZJPa1QJ var X_EventDispatcher_actualHandleEvent = - X.UA.IE4 || X.UA.IE5678 ? // ie45678 EVENT_IE & EVENT_DOM0 for ie4 + X.UA.IE4 || X_EventDispatcher_temp.EVENT_IE ? // ie45678 EVENT_IE & EVENT_DOM0 for ie4 (function(){ var ret; - if( event.type === 'readystatechange' && this._tag && X.Dom.Event._LOAD_FIX_TAGS[ this._tag ] ){ + //if( event.type === 'readystatechange' && this._tag && X.Dom.Event._LOAD_FIX_TAGS[ this._tag ] ){ //type = 'readystatechange'; - }; + //}; - ret = X_EventDispatcher_dispatch.call( this, new X.Dom.Event( event, this, this._rawObject ) ); + ret = this.dispatch( new X.Dom.Event( event, this, this._rawObject ) ); if( ret & X.Callback.STOP_PROPAGATION ){ event.cancelBubble = true; @@ -606,7 +629,23 @@ var X_EventDispatcher_actualHandleEvent = }) : //X.Dom.EVENT_W3C & EVENT_DOM0 (function( e ){ - var ret = X_EventDispatcher_dispatch.call( this, new X.Dom.Event( e, this ) ); + var ev = new X.Dom.Event( e, this ), + ret = X.Callback.NONE, + i, l; + + // touch event -> pointer + if( X.Type.isArray( ev ) ){ + if( ev.length === 0 ){ + // TouchEvent の後に発生した MouseEvent のキャンセル + ret = X.Callback.STOP_PROPAGATION | X.Callback.PREVENT_DEFAULT; + } else { + for( i = 0, l = ev.length; i < l; ++i ){ + ret |= this.dispatch( ev[ i ] ) || 0; + }; + }; + } else { + ret = this.dispatch( ev ); + }; if( ret & X.Callback.STOP_PROPAGATION ){ e.stopPropagation(); @@ -635,24 +674,16 @@ if( X.UA.WebKit < 525.13 ){ // Safari3- }; // イベントの退避、dom が画面から抜かれる場合に実施しておく -function X_EventDispatcher_migrateEvent( that ){ - var hash = that._listeners, - type; - if( !hash ) return; - for( type in hash ){ - // 数字イベントの除外 - '' + parseFloat( type ) !== type && X_EventDispatcher_actualRemoveEvent( that, type ); - }; -}; - // 退避したイベントの復帰 -function X_EventDispatcher_restoreEvent( that ){ +function X_EventDispatcher_toggleAllEvents( that, add ){ var hash = that._listeners, + raw = that._rawObject || that._ie4getRawNode && that._ie4getRawNode(), + f = add ? X_EventDispatcher_actualAddEvent : X_EventDispatcher_actualRemoveEvent, type; - if( !hash ) return; + if( !hash || !raw ) return; for( type in hash ){ // 数字イベントの除外 - '' + parseFloat( type ) !== type && X_EventDispatcher_actualAddEvent( that, type ); + '' + parseFloat( type ) !== type && f( that, type, raw ); }; }; diff --git a/0.6.x/js/01_dom/10_XDom.js b/0.6.x/js/01_dom/10_XDom.js index 1f6386b..9355f21 100644 --- a/0.6.x/js/01_dom/10_XDom.js +++ b/0.6.x/js/01_dom/10_XDom.js @@ -238,8 +238,6 @@ X.Dom = X.Class._override( _getSize : X.UA.IE ? new Function( 'return[X.Dom._root.clientWidth,X.Dom._root.clientHeight]' ) : - 4 <= X.UA.iOS ? - new Function( 'return[window.innerWidth,window.innerHeight]' ) : new Function( 'return[window.innerWidth,window.innerHeight]' ), getSize : function(){ @@ -345,35 +343,7 @@ if( document.layers ){ X.Dom.EVENT_POINTER = navigator.msPointerEnabled || navigator.pointerEnabled; X.Dom.EVENT_TOUCH = !X.Dom.EVENT_POINTER && window.ontouchstart !== undefined; -X.Dom.moveToHead = { - STYLE : true, - LINK : true, - TITLE : true, - BGSOUND : true, - AREA : true, - BASE : true, - META : true -}; -X.Dom.cleanupTagNames = { - SCRIPT : true, - NOSCRIPT : true, - NOFRAMES : true, - '!' : true, // ie - COMMENT : true, // ie - NOEMBED : true, - NOLAYER : true - }; -X.Dom.skipCleanupTagNames = { - PRE : true, - TEXTAREA : true, - CODE : true, - KBD : true, - SAMP : true, - XMP : true, - PLAINTEXT : true, - LISTING : true -}; X.Dom.CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 ); @@ -435,7 +405,7 @@ X.Dom.getAbsolutePath = function( path ){ ss = '//', _ary, ary, i = 0; - if( 'http:file'.indexOf( path.substr( 0, 4 ) ) !== -1 ) return path; + if( 'http:file:https:'.indexOf( path.substr( 0, 4 ) ) !== -1 ) return path; _ary = X.Dom.baseURL.split( ss ); ary = _ary[ 1 ].split( s ); diff --git a/0.6.x/js/01_dom/11_XDomDTD.js b/0.6.x/js/01_dom/11_XDomDTD.js index 894427b..07c2432 100644 --- a/0.6.x/js/01_dom/11_XDomDTD.js +++ b/0.6.x/js/01_dom/11_XDomDTD.js @@ -1,4 +1,5 @@ +/* なんで */ X.Dom.DTD = { EMPTY : { @@ -42,4 +43,33 @@ X.Dom.DTD = { } }; +X.Dom.moveToHead = { + STYLE : true, + LINK : true, + TITLE : true, + BGSOUND : true, + AREA : true, + BASE : true, + META : true +}; + +X.Dom.cleanupTagNames = { + SCRIPT : true, + NOSCRIPT : true, + NOFRAMES : true, + '!' : true, // ie + COMMENT : true, // ie + NOEMBED : true, + NOLAYER : true +}; +X.Dom.skipCleanupTagNames = { + PRE : true, + TEXTAREA : true, + CODE : true, + KBD : true, + SAMP : true, + XMP : true, + PLAINTEXT : true, + LISTING : true +}; diff --git a/0.6.x/js/01_dom/11_XDomNode.js b/0.6.x/js/01_dom/11_XDomNode.js index 4c443e1..ff29163 100644 --- a/0.6.x/js/01_dom/11_XDomNode.js +++ b/0.6.x/js/01_dom/11_XDomNode.js @@ -1303,7 +1303,7 @@ Node.prototype._afterActualCreate = }; // src の onload があるので先ではないか? // ie の str から要素を作る場合、srcだけ イベント設定後ではないか? - X_EventDispatcher_restoreEvent( this );// イベントの復帰 + X_EventDispatcher_toggleAllEvents( this, true );// イベントの復帰 }) : X.Dom.DOM_IE4 ? (function(){ var xnodes, i; @@ -1321,7 +1321,7 @@ Node.prototype._afterActualCreate = this._ie4getRawNode().style.filter = X.Dom.Style.SPECIAL_FIX( this._css ); }; delete this._dirty; - X_EventDispatcher_restoreEvent( this );// イベントの復帰 + X_EventDispatcher_toggleAllEvents( this, true );// イベントの復帰 }) : (function(){}); @@ -1339,7 +1339,7 @@ Node.prototype._actualRemove = }; if( !elm ) return; - this._xnodeType === 1 && X_EventDispatcher_migrateEvent( this );// イベントの退避 + this._xnodeType === 1 && X_EventDispatcher_toggleAllEvents( this, false );// イベントの退避 // elm.parentNode.tagName for ie7 if( !X.UA.MacIE ){ !isChild && elm.parentNode && elm.parentNode.tagName && elm.parentNode.removeChild( elm ); @@ -1359,7 +1359,7 @@ Node.prototype._actualRemove = }; if( !elm ) return; - this._xnodeType === 1 && X_EventDispatcher_migrateEvent( this );// イベントの退避 + this._xnodeType === 1 && X_EventDispatcher_toggleAllEvents( this, false );// イベントの退避 if( X.Dom.Attr.HAS_VALUE[ this._tag ] && ( !this._newAttrs || !X.inObject( 'value', this._newAttrs ) ) ){ this._attrs.value = elm.value; diff --git a/0.6.x/js/01_dom/12_XDomEvent.js b/0.6.x/js/01_dom/12_XDomEvent.js index fd81b01..183090e 100644 --- a/0.6.x/js/01_dom/12_XDomEvent.js +++ b/0.6.x/js/01_dom/12_XDomEvent.js @@ -4,169 +4,304 @@ * http://d.hatena.ne.jp/uupaa/20100430/1272561922 * event.offsetX と offsetY の互換性について * + * http://www.keynavi.net/ja/tipsj/gokan.html + * Safari : マウスイベントは大丈夫ですが ページ全体に対するキーイベントをきちんと扱えない問題があります。 + * その他、リンクに対するフォーカス(element.focus())の動作がおかしい、 スクリーン上のマウス位置(event.screenX/Y)をブラウザ画面の 左下隅から計算する などの問題があり修正が待たれます。 + * */ +// http://msdn.microsoft.com/ja-jp/library/ie/dn255104%28v=vs.85%29.aspx +var X_Dom_Event_devicePixelRatio = window.devicePixelRatio || ( window.screen.deviceXDPI / window.screen.logicalXDPI ), + X_Dom_Event_convertMSPointerType = window.MSPointerEvent && { + 2 : 'touch', + 3 : 'pen', + 4 : 'mouse' + }; + if( !X.UA.IE || 9 <= X.UA.IE ){ X.Dom.Event = function( e, xnode ){ - var touch0; - //this._event = e; - this.type = X.Dom.Event.RenameTo[ e.type ] || e.type; - - //http://www.quirksmode.org/js/events_properties.html - if( e.target ){ - this.target = Node._getXNode( e.target.nodeType === 3 ? e.target.parentNode : e.target );// defeat Safari bug // xnode - }; - if( e.relatedTarget ){ - this.relatedTarget = Node._getXNode( e.relatedTarget.nodeType === 3 ? e.relatedTarget.parentNode : e.relatedTarget ); // xnode - }; - - this.currentTarget = xnode; // xnode - this.eventPhase = e.eventPhase; - - this.clientX = e.clientX; - this.clientY = e.clientY; - //this.screenX = e.screenX; - //this.screenY = e.screenY; - this.pageX = e.pageX; - this.pageY = e.pageY; - this.offsetX = e.offsetX || e.layerX || 0; // 要素上の座標を取得 - this.offsetY = e.offsetY || e.layerY || 0; - - this.keyCode = e.keyCode; - this.altKey = e.altKey; - this.ctrlKey = e.ctrlKey; - this.shiftKey = e.shiftKey; - - // http://www.programming-magic.com/20090127231544/ - this.which = e.which || ( e.button + 1 ); // 左:1, 中:2, 右:3 - this.button = e.button; + var _type = e.type, + type, + changedTouches, targetTouches, targetIDs, changedTargets, isEnd, + altKey, ctrlKey, metaKey, shiftKey, target, related, + i, n, time, touch, ev; - // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel + //this._event = e; + this.type = type = X.Dom.Event.RenameTo[ _type ] || _type; - // TODO - // axis - // https://w3g.jp/blog/tools/wheelevent_crossbrowser - // ホイール系イベント2014年版クロスブラウザ - if( e.deltaY !== undefined ){ - this.deltaX = e.deltaX; - this.deltaY = e.deltaY; - } else - if( e.wheelDeltaY !== undefined ){ - this.deltaX = e.wheelDeltaX / 120; - this.deltaY = e.wheelDeltaY / 120; - } else - if( e.wheelDelta !== undefined ){ - this.deltaX = 0; - this.deltaY = e.wheelDelta / -120; + // http://msdn.microsoft.com/ja-jp/library/ie/dn304886%28v=vs.85%29.aspx + // ポインター イベントの更新 + if( e.pointerType ){ + // PointerEvent; + if( X_Dom_Event_convertMSPointerType ){ + this.pointerType = X_Dom_Event_convertMSPointerType[ e.pointerType ]; + this.pressure = e.pressure || ( e.button !== -1 ? 0.5 : 0 ); + // ポインターの接触形状の スクリーン ピクセル単位の幅と高さ なので変換。(多分、、、) + this.width = e.width / X_Dom_Event_devicePixelRatio; + this.height = e.height / X_Dom_Event_devicePixelRatio; + } else { + this.pointerType = e.pointerType; + this.pressure = e.pressure; + // ポインターの接触形状の CSS ピクセル単位の幅と高さ。 + this.width = e.width; + this.height = e.height; + }; + + switch( this.pointerType ){ + case 'pen' : + //Y-Z 平面と、ペンの軸が含まれる平面の間の角度を返します。Y 軸の範囲は -90 ~ +90 です。X の傾きの正の方向は右方向です。 + this.tiltX = e.tiltX; + this.tiltY = e.tiltY; + if( _type === 'MSPointerHover' ){ + this.type = 'pointermove'; // ie10 には pointerhover と pointermoveがあり、ie11 で一本化。ie11 では buttons を見て hover 状態を判定 + }; + case 'touch' : + this.radiusX = e.radiusX; + this.radiusY = e.radiusY; + this.rotationAngle = e.rotationAngle; + case 'mouse' : + }; + + this.button = e.button; + this.buttons = e.buttons; + + this.pointerId = e.pointerId; + this.target = Node._getXNode( e.target ); + this.relatedTarget = Node._getXNode( e.relatedTarget ); // xnode + this.isPrimary = e.isPrimary; + this.hwTimestamp = e.hwTimestamp; + this.timestamp = e.timestamp; + + this.altKey = e.altKey; + this.ctrlKey = e.ctrlKey; + this.metaKey = e.metaKey; + this.shiftKey = e.shiftKey; + //this.screenX = touch.screenX; + //this.screenY = touch.screenY; + this.clientX = e.clientX; + this.clientY = e.clientY; + this.pageX = e.pageX; + this.pageY = e.pageY; + this.offsetX = e.offsetX; + this.offsetY = e.offsetY; } else - if( e.detail !== undefined ){ - this.deltaX = 0; - this.deltaY = e.type === 'MozMousePixelScroll' ? e.detail / 45 : e.detail / 3; // 3 + if( X.Dom.Event.toPointer[ _type ] ){ + // Touch or Mouse + + /* e.constructor === window.TouchEvent -> e.touches for iOS3.13 */ + if( touches = e.changedTouches ){ + if( touches.length === 0 ){ + alert( 'e.changedTouches.length === 0' ); + }; + xnode._cancelMouse = type; + + events = []; + altKey = e.altKey; + ctrlKey = e.ctrlKey; + metaKey = e.metaKey; + shiftKey = e.shiftKey; + time = X.getTime(); + for( i = touches.length; i; ){ + touch = touches[ --i ]; + target = touch.target; + related = touch.relatedTarget; + events[ i ] = { + type : type, + pointerType : 'touch', + target : Node._getXNode( target.nodeType === 3 ? target.parentNode : target ),// defeat Safari bug // xnodetouch.target, + currentTarget : xnode, + relatedTarget : Node._getXNode( related.nodeType === 3 ? related.parentNode : related ), // xnode + isPrimary : true, + hwTimestamp : time, + timestamp : time, + buttons : e.button, + buttons : e.buttons || e.button, + altKey : altKey, + ctrlKey : ctrlKey, + metaKey : metaKey, + shiftKey : shiftKey, + pointerId : touch.identifier + 2, + //screenX : touch.screenX, + //screenY : touch.screenY, + clientX : touch.clientX, + clientY : touch.clientY, + pageX : touch.pageX, + pageY : touch.pageY, + offsetX : touch.offsetX, // 要素上の座標を取得 + offsetY : touch.offsetY, + radiusX : touch.radiusX || 0, + radiusY : touch.radiusY || 0, + rotationAngle : touch.rotationAngle || 0, + pressure : touch.force || touch.webkitForce || ( isEnd ? 0 : 0.5 ), + width : touch.width || 0, + height : touch.height || 0 + }; + }; + return events.length === 1 ? events[ 0 ] : events; + } else { + + if( xnode._cancelMouse === type ){ + delete xnode._cancelMouse; + return []; + }; + + // MouseEvent; + this.type = type; + this.pointerType = 'mouse'; + + // http://www.programming-magic.com/20090127231544/ + // TODO Opera で button==2の場合、コンテキストメニューイベントを発火 「ツール」->「設定」->「詳細設定」->「コンテンツ」->「Javascriptオプション」で「右クリックを制御するスクリプトを許可する」 + this.button = e.button !== undefined ? e.button : + e.which !== undefined ? e.which - 1 : -1; + this.buttons = e.buttons !== undefined ? e.buttons : this.button === 0 ? 1 : this.button === 1 ? 2 : this.button === 2 ? 4 : 0; + this.pressure = ( this.button !== -1 ? 0.5 : 0 ); + + elm = e.target; + this.target = Node._getXNode( elm.nodeType === 3 ? elm.parentNode : elm );// defeat Safari bug // xnodetouch.target; + this.isPrimary = true; + this.hwTimestamp = this.timestamp = X.getTime(); + this.altKey = e.altKey; + this.ctrlKey = e.ctrlKey; + this.metaKey = e.metaKey; + this.shiftKey = e.shiftKey; + this.pointerId = 1; + //this.screenX = touch.screenX; + //this.screenY = touch.screenY; + // TODO http://uupaa-js.googlecode.com/svn-history/r8/trunk/doc/reference/symbols/src/trunk_uu.module.ui.js.html + // Safari2ではclientX,YはpageX,Yと同じ値を返す + this.clientX = e.clientX; + this.clientY = e.clientY; + this.pageX = e.pageX; + this.pageY = e.pageY; + this.offsetX = e.offsetX || e.layerX; // 要素上の座標を取得 + this.offsetY = e.offsetY || e.layerY; + }; } else { - this.deltaX = this.deltaY = 0; - }; - - if( /* e.constructor === window.TouchEvent || */ e.touches /* for iOS3.13 */ ){ - // TouchEvent - this.touches = e.touches; - this.changedTouches = e.changedTouches; - this.targetTouches = e.targetTouches; - this.metaKey = e.metaKey; - this.force = e.force || e.webkitForce || 0; - // - if( this.touches.length ){ - touch0 = this.touches[ 0 ]; - this.clientX = touch0.clientX; - this.clientY = touch0.clientY; - this.pageX = touch0.pageX; - this.pageY = touch0.pageY; - this.offsetX = touch0.offsetX || touch0.layerX; - this.offsetY = touch0.offsetY || touch0.layerY; + // Other + + this.keyCode = e.keyCode || e.which; + this.altKey = e.altKey; + this.ctrlKey = e.ctrlKey; + this.shiftKey = e.shiftKey; + this.metaKey = e.metaKey; + + this.button = e.button !== undefined ? e.button : + e.which !== undefined ? e.which - 1 : -1; + this.buttons = e.buttons !== undefined ? e.buttons : this.button === 0 ? 1 : this.button === 1 ? 2 : this.button === 2 ? 4 : 0; + + //http://www.quirksmode.org/js/events_properties.html + if( elm = e.target ){ + this.target = Node._getXNode( elm.nodeType === 3 ? elm.parentNode : elm );// defeat Safari bug // xnode }; - } else - if( e.constructor === window.PointerEvent ){ - // PointerEvent; - this.currentPoint = e.currentPoint; - this.width = e.width; - this.height = e.height; - this.timeStamp = e.timeStamp; - this.hwTimestamp = e.hwTimestamp; - this.intermediatePoints = e.intermediatePoints; - this.isPrimary = e.isPrimary; - this.pointerId = e.pointerId; - this.pointerType = e.pointerType; - this.pressure = e.pressure; - this.tiltX = e.tiltX; - this.tiltY = e.tiltY; + if( elm = e.relatedTarget ){ + this.relatedTarget = Node._getXNode( elm.nodeType === 3 ? elm.parentNode : elm ); // xnode + }; + + if( type === 'wheel' ){ + // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel + // TODO axis + // https://w3g.jp/blog/tools/wheelevent_crossbrowser + // ホイール系イベント2014年版クロスブラウザ + if( e.deltaY !== undefined ){ + this.deltaX = e.deltaX; + this.deltaY = e.deltaY; + this.deltaZ = e.deltaZ; + } else + if( e.wheelDeltaY !== undefined ){ + this.deltaX = e.wheelDeltaX / 120; + this.deltaY = e.wheelDeltaY / 120; + this.deltaZ = e.wheelDeltaZ / 120 || 0; + } else + if( e.wheelDelta !== undefined ){ + this.deltaX = this.deltaZ = 0; + this.deltaY = e.wheelDelta / -120; + } else + if( e.detail !== undefined ){ + this.deltaX = this.deltaZ = 0; + this.deltaY = _type === 'MozMousePixelScroll' ? e.detail / 45 : e.detail / 3; // 3 + } else { + this.deltaX = this.deltaY = this.deltaZ = 0; + }; + }; }; - }; - if( !window.PointerEvent && window.MSPointerEvent ){ - window.PointerEvent = window.MSPointerEvent; + + this.currentTarget = xnode; // xnode + this.eventPhase = e.eventPhase; + this.detail = e.detail; + }; } else { - X.Dom.Event = function( e, xnode, element, opt_type ){ + X.Dom.Event = function( e, xnode, element ){ var btn; - //this._event = e; - this.type = X.Dom.Event.RenameTo[ e.type ] || e.type || opt_type; + this.type = X.Dom.Event.RenameTo[ e.type ] || e.type; this.target = Node._getXNode( e.srcElement ); // xnode if( this.target && this.target._xnodeType === 3 ) this.target = this.target.parent; // ie4 の fake Textnode がヒットしていないか? this.currentTarget = xnode; // xnode - this.relatedTarget = Node._getXNode( e.formElement ? e.formElement : e.toElement ); // xnode + this.relatedTarget = Node._getXNode( e.formElement || e.toElement ); // xnode this.eventPhase = e.srcElement === element ? 2: 3; - this.clientX = e.clientX; - this.clientY = e.clientY; - //this.screenX = e.screenX; - //this.screenY = e.screenY; - - if( X.Dom._root ){ // uuu... - - this.pageX = e.clientX + X.Dom._root.scrollLeft; - this.pageY = e.clientY + X.Dom._root.scrollTop; - - // DOMAssistant 2.8.1 - //event.pageX = DOMAssistant.def(e.pageX)? e.pageX : (event.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0)); - //event.pageY = DOMAssistant.def(e.pageY)? e.pageY : (event.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0)); - }; - - - - if( 5 <= X.UA.IE ){ - this.offsetX = e.offsetX; // イベントターゲット左上からの座標 - this.offsetY = e.offsetY; - }// else - //if( e.srcElement ){ - // this.offsetX = e.x - e.srcElement.offsetLeft; // e.x はイベント発生要素の親要素を基準にした座標。 - // this.offsetY = e.y - e.srcElement.offsetTop; - //}; - this.keyCode = e.keyCode; this.altKey = e.altKey; this.ctrlKey = e.ctrlKey; - this.shiftKey = e.shiftKey; - + this.shiftKey = e.shiftKey; + // http://www.programming-magic.com/20090127231544/ switch( this.type ){ case 'click' : case 'dblclick' : - this.which = 1; + this.button = 0; break; case 'contextmenu' : - this.which = 3; + this.button = 2; break; default : + // mouseup, mousedown btn = e.button; - this.which = - btn & 1 ? 1 : + this.button = + btn & 1 ? 0 : btn & 4 ? 2 : - btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2 + btn & 2 ? 1 : -1; // 左:1(click:0), 中:4, 右:2 + + }; + this.buttons = e.button; + + if( type = X.Dom.Event.toPointer[ e.type ] ){ + this.type = type; + this.clientX = e.clientX; + this.clientY = e.clientY; + //this.screenX = e.screenX; + //this.screenY = e.screenY; + + //if( X.Dom._root ){ // uuu... + this.pageX = e.clientX + X.Dom._root.scrollLeft; + this.pageY = e.clientY + X.Dom._root.scrollTop; + // DOMAssistant 2.8.1 + //event.pageX = DOMAssistant.def(e.pageX)? e.pageX : (event.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0)); + //event.pageY = DOMAssistant.def(e.pageY)? e.pageY : (event.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0)); + //}; + + if( 5 <= X.UA.IE ){ + this.offsetX = e.offsetX; // イベントターゲット左上からの座標 + this.offsetY = e.offsetY; + }// else + //if( e.srcElement ){ + // this.offsetX = e.x - e.srcElement.offsetLeft; // e.x はイベント発生要素の親要素を基準にした座標。 + // this.offsetY = e.y - e.srcElement.offsetTop; + //}; + + this.deltaX = 0; + this.deltaY = e.wheelDelta / -120; + + this.pointerId = 1; + this.radiusX = 0; + this.radiusY = 0; + this.rotationAngle = 0; + this.width = 0; + this.height = 0; + this.tiltX = 0; + this.tiltY = 0; }; - this.button = this.which - 1; - this.deltaX = 0; - this.deltaY = e.wheelDelta / -120; - - if( this.type === 'wheel' ) console.log( e.wheelDelta ); }; }; @@ -203,28 +338,52 @@ X.Dom.Event._LOAD_FIX_TAGS = { //LINK : true }; -X.Dom.Event.Rename = {}; -X.Dom.Event.RenameTo = {}; +X.Dom.Event.Rename = {}; +X.Dom.Event.RenameTo = {}; +X.Dom.Event.toPointer = !X.Dom.EVENT_POINTER && ( X.Dom.EVENT_TOUCH ? + { + touchdown : 'pointerdown', + mousedown : 'pointerdown', + touchup : 'pointerup', + mouseup : 'pointerup', + touchmove : 'pointermove', + mousemove : 'pointermove', + touchcancel : 'pointercancel', + contextmenu : 'contextmenu', + dbclick : 'dbclick', + click : 'click', + tap : 'click' + } : + { + mousedown : 'pointerdown', + mouseup : 'pointerup', + mousemove : 'pointermove', + contextmenu : 'contextmenu', + dbclick : 'dbclick', + click : 'click' + }); + + // https://github.com/georgeadamson/jQuery.prefixfree-events/blob/master/jQuery.prefixfree-events.js // https://developer.mozilla.org/en-US/docs/Web/Events/wheel // if( document.onwheel === undefined ){ // DOMMoseScroll if( X.UA.Gecko && window.MouseScrollEvent ){ - if( 2 <= X.UA.Gecko || ( 1.9 < X.UA.Gecko && 1 <= X.UA.GeckoPatch ) ){ // Gecko 1.9.1+ (firefox3.5+) + if( 2 <= X.UA.Gecko || ( 1.9 <= X.UA.Gecko && 1 <= X.UA.GeckoPatch ) ){ // Gecko 1.9.1+ (firefox3.5+) console.log( 'wheel <= MozMousePixelScroll' ); X.Dom.Event.Rename[ 'wheel' ] = 'MozMousePixelScroll'; } else - if( 0.9 < X.UA.Gecko && 7 <= X.UA.GeckoPatch ){ // Gecko 0.9.7+ (NN6.2+?) + if( 1 <= X.UA.Gecko || ( 0.9 <= X.UA.Gecko && 7 <= X.UA.GeckoPatch ) ){ // Gecko 0.9.7+ (NN6.2+?) console.log( 'wheel <= DOMMouseScroll' ); X.Dom.Event.Rename[ 'wheel' ] = 'DOMMouseScroll'; }; } else { X.Dom.Event.Rename[ 'wheel' ] = 'mousewheel'; }; - if( document.onmousewheel !== undefined ){ // Opera で判定失敗 - X.Dom.Event.Rename[ 'wheel' ] = 'mousewheel'; - }; + //if( document.onmousewheel !== undefined ){ // Opera で判定失敗する + // X.Dom.Event.Rename[ 'wheel' ] = 'mousewheel'; + //}; }; @@ -276,18 +435,43 @@ if( window.onmoztransitionend !== undefined && window.ontransitionend === undefi X.Dom.Event.Rename[ 'transitionend' ] = 'mozTransitionEnd'; }; - -if( navigator.msPointerEnabled && !navigator.pointerEnabled ){ - console.log( 'pointerdown <= MSPointerDown' ); - X.Dom.Event.Rename[ 'pointerdown' ] = 'MSPointerDown'; - X.Dom.Event.Rename[ 'pointerup' ] = 'MSPointerUp'; - X.Dom.Event.Rename[ 'pointermove' ] = 'MSPointerMove'; - X.Dom.Event.Rename[ 'pointercancel' ] = 'MSPointerCancel'; +if( !navigator.pointerEnabled ){ + if( navigator.msPointerEnabled ){ + console.log( 'pointerdown <= MSPointerDown' ); + X.Dom.Event.Rename[ 'pointerdown' ] = 'MSPointerDown'; + X.Dom.Event.Rename[ 'pointerup' ] = 'MSPointerUp'; + X.Dom.Event.Rename[ 'pointermove' ] = [ 'MSPointerMove', 'MSPointerHover' ];// ie10 と ie11 でペンのhoverevent の値が異なる + X.Dom.Event.Rename[ 'pointercancel' ] = 'MSPointerCancel'; + // http://msdn.microsoft.com/ja-jp/library/ie/dn304886%28v=vs.85%29.aspx + } else + if( X.Dom.EVENT_TOUCH ){ + X.Dom.Event.Rename[ 'pointerdown' ] = [ 'touchdown', 'mousedown' ]; + X.Dom.Event.Rename[ 'pointerup' ] = [ 'touchup', 'mouseup' ]; + X.Dom.Event.Rename[ 'pointermove' ] = [ 'touchmove', 'mousemove' ]; + X.Dom.Event.Rename[ 'pointercancel' ] = 'touchcancel'; + X.Dom.Event.Rename[ 'click' ] = [ 'click', 'tap' ]; + } else { + X.Dom.Event.Rename[ 'pointerdown' ] = 'mousedown'; + X.Dom.Event.Rename[ 'pointerup' ] = 'mouseup'; + X.Dom.Event.Rename[ 'pointermove' ] = 'mousemove'; + X.Dom.Event.Rename[ 'pointercancel' ] = 'mouseleave';//?? + // Opera + // X.Dom.Event.Rename[ 'contextmenu' ] = 'mousedown'; button==2 の場合 + }; }; + (function( rename, renameTo ){ - for( var k in rename ){ - renameTo[ rename[ k ] ] = k; + var k, name, i; + for( k in rename ){ + name = rename[ k ]; + if( X.Type.isArray( name ) ){ + for( i = name.length; i; ){ + renameTo[ name[ --i ] ] = k; + }; + } else { + renameTo[ name ] = k; + }; }; })( X.Dom.Event.Rename, X.Dom.Event.RenameTo ); @@ -308,14 +492,14 @@ if( X.Dom.EVENT_W3C ){ if( 6 <= X.UA.IE && X.inHead ){ // if this script in Head document.write( "' +].join( '">