• R/O
  • HTTP
  • SSH
  • HTTPS

clientJs: コミット

クライアント側 js 開発用


コミットメタ情報

リビジョン321cf844195090369e92f5d0c67dcd360eaa6fdd (tree)
日時2015-02-19 14:06:43
作者itozyun <itozyun@user...>
コミッターitozyun

ログメッセージ

Version 0.6.131, cleanup X.EventDispatcher.

変更サマリ

差分

--- a/0.6.x/js/01_core/11_XClass.js
+++ b/0.6.x/js/01_core/11_XClass.js
@@ -54,11 +54,10 @@ X_Class_CommonProps =
5454 // X.Event.KILL_INSTANCE_CANCELED は kill() がキャンセルされた場合に発行。また dispatchループ中にkill()が呼ばれると一旦キャンセルされ発行。
5555 // (flagを立ててdispatchの終わりにkillする)
5656 if( this.instanceOf( X.EventDispatcher ) ){
57- //console.log( 'this.instanceOf( X.EventDispatcher )! ' + this._dispatching );
5857 if( !def.isPrivate ){
59- if( this._dispatching ){
58+ if( this[ '_listeners' ] && this[ '_listeners' ]._dispatching ){
6059 this.dispatch( X.Event.BEFORE_KILL_INSTANCE );
61- this._killReserved = true;
60+ this[ '_listeners' ]._killReserved = true;
6261 this.dispatch( X.Event.KILL_INSTANCE_CANCELED );
6362 return;
6463 } else
@@ -86,8 +85,8 @@ X_Class_CommonProps =
8685 if( i !== -1 ){
8786 data = X_Class_getPrivate( instance );
8887 X_Class_killPrivateFlag = true;
89- if( data._dispatching && data.instanceOf( X.EventDispatcher ) ){
90- data._killReserved = true;
88+ if( data[ '_listeners' ] && data[ '_listeners' ]._dispatching && data.instanceOf( X.EventDispatcher ) ){
89+ data[ '_listeners' ]._killReserved = true;
9190 } else {
9291 data.kill();
9392 };
--- a/0.6.x/js/01_core/13_XEventDispatcher.js
+++ b/0.6.x/js/01_core/13_XEventDispatcher.js
@@ -29,7 +29,33 @@ var X_EventDispatcher_once = false,
2929 X_EventDispatcher_unlock = false,
3030 X_EventDispatcher_needsIndex = false,
3131
32- X_EventDispatcher_safariPreventDefault = false; // Safari3-
32+ X_EventDispatcher_safariPreventDefault = false, // Safari3-
33+
34+ X_EventDispatcher_EVENT_TARGET_TYPE = {
35+ OTHER : 0,
36+ XHR : 1,
37+ SILVER_LIGHT : 2
38+ },
39+
40+ X_EventDispatcher_LAZY_TIMERS = {}; // Object.<number, X.EventDispatcher> number は timerID
41+
42+/*
43+ * イベントリスナをイベント名(string)や数値(1~,フレームワーク内で定義)をキーとするArrayで記憶します。
44+ * Arrayには、{k:種類,x:コンテキスト(thisObject),f:関数,s:サプリメントする引数の配列} というハッシュ、または関数が蓄えられています。
45+ * また、dispatch 中の状態と操作を記録し不整合が起きないようにするためのプロパティを持ちます。
46+ * @typedef {(
47+ * {
48+ * _handleEvent : function,
49+ * _dispatching : number,
50+ * _reserves : (Array|undefined),
51+ * _unlistens : {Object.<(number|string), Array.<(X.Callback|function)>>},
52+ * _killReserved : (Boolean|undefiend)
53+ * }
54+ * |
55+ * Object.<(number|string), Array.<(callbackHash|function)>>
56+ * )}
57+ */
58+var X_EventDispatcher_listeners;
3359
3460 // ------------------------------------------------------------------------- //
3561 // --- interface ----------------------------------------------------------- //
@@ -61,14 +87,19 @@ X.EventDispatcher =
6187 /** @lends X.EventDispatcher.prototype */
6288 {
6389
64-
65-
66- // TODO _rawObjectType EventTarget, XHR, Silverlight, ...
90+ /**
91+ * OTHER(Node,window,document,Image,Audio), XHR, Silverlight
92+ * @private
93+ * @type {number}
94+ */
95+ '_rawType' : X_EventDispatcher_EVENT_TARGET_TYPE.OTHER,
96+
6797 /**
6898 * イベントリスナをイベント名(string)や数値(1~,フレームワーク内で定義)をキーとするArrayで記憶します。
6999 * Arrayには、{k:種類,x:コンテキスト(thisObject),f:関数,s:サプリメントする引数の配列} というハッシュ、または関数が蓄えられています。
100+ *
70101 * @private
71- * @type {Object.<(number|string), Array.<(callbackHash|function)>>}
102+ * @type {X_EventDispatcher_listeners}
72103 */
73104 '_listeners' : null,
74105
@@ -76,62 +107,15 @@ X.EventDispatcher =
76107 * _rawObject には HTMLElement, window, document, XHR といったイベントターゲットオブジェクトを設定します。
77108 * _rawObject が設定されていると listen(), unlisten() 時に addEventListener(DOM Level2) や detachEvent(ie5~8), on~(DOM0) 等を操作します。
78109 * _rawObject は最初の listen() 前に設定しておかないと addEventListener 等が意図したように行われません。
79- * X.Node では非同期に HTMLElement を生成していて、要素生成以前に listen, unlisten を呼び出すことができます。これは適宜に X_EventDispatcher_toggleAllEvents を呼んで解決しているためです。
110+ * X.Node では非同期に HTMLElement を生成していますが、要素生成以前に listen, unlisten を呼び出すことができます。これは適宜に X_EventDispatcher_toggleAllEvents を呼んで解決しているためです。
80111 * @private
81112 * @type {Object}
82113 */
83114 '_rawObject' : null,
84-
85- /**
86- * _rawObject がある場合、イベントターゲットオブジェクトに対して addEventListener, attachEvent, onXX 時に実際に渡される関数。
87- * イベントタイプが変わっても、単一の オブジェクトを使いまわす。(但し例外は、IE8以下の XHR|MSXML に対して。)最初の listen で生成されて、最後の unlisten で削除される。
88- * @private
89- * @type {X.Callback}
90- */
91- '_handleEvent' : null,
92-
93- /**
94- * dispatch 中に dispatch が呼ばれた際に、そのネストの深さを保存する。
95- * dispatch() 終了時に _dispatching が 0 の場合に、現在のインスタンスの dispatch がすべて終わったことになる。
96- * @private
97- * @type {number}
98- */
99- '_dispatching' : 0, // dispatch 中の unlisten で使用
100-
101- /**
102- * dispatch 中に listen が呼ばれた場合に、配列のindexがずれることを避けるため、一旦保持する。
103- * _dispatching が 0 のときに _reserves を使って listen() を呼び出す。
104- * @private
105- * @type {Object.<(number|string), Array.<(X.Callback|function)>>}
106- */
107- '_reserves' : null,
108-
109- /**
110- * dispatch 中に unlisten が呼ばれた場合に、配列のindexがずれることを避けるため、一旦保持する。
111- * _dispatching が 0 のときに _unlistens を使って unlisten() を呼び出す。
112- * @private
113- * @type {Object.<(number|string), Array.<(X.Callback|function)>>}
114- */
115- '_unlistens' : null,
116-
117- /**
118- * dispatch 中に kill が呼ばれた場合に、X.EventDispatcher インスタンスの削除を dispatch 後にずらすために立てるフラグ。
119- * @private
120- * @type {boolean}
121- */
122- '_killReserved' : false,
123-
124- /**
125- * asyncDispatch 中に kill が呼ばれた場合に、X.EventDispatcher インスタンスの削除を最後のタイマーの発火後にずらすために立てるフラグ。
126- * TODO asyncDispatch の解除はどうする?
127- * @private
128- * @type {boolean}
129- */
130- '_lastLazyID' : false,
131115
132116 /**
133117 * X.EventDispatcher のコンストラクタの実体。
134- * @@@constructs
118+ * @constructs
135119 * @this {X.EventDispatcher}
136120 * @param {object=} opt_rawObject
137121 */
@@ -196,30 +180,31 @@ X.EventDispatcher =
196180 * @param {Array=} opt_arg3
197181 */
198182 listening : function( opt_type, opt_arg1, opt_arg2, opt_arg3 ){
199- var list = this._listeners,
200- unlistens, i, f, hash;
183+ var listeners = this[ '_listeners' ],
184+ lock = X_EventDispatcher_lock || X_EventDispatcher_unlock,
185+ list, cbHash, unlistens, i, f;
201186
202- if( opt_type === undefined ) return !!list;
203- if( !list || !( list = list[ opt_type ] ) ) return false;
187+ if( opt_type === undefined ) return !!listeners;
188+ if( !listeners || !( list = listeners[ opt_type ] ) ) return false;
204189 if( opt_arg1 === undefined ) return true;
205190
206191 if( opt_arg1.k ){
207- hash = opt_arg1;
192+ cbHash = opt_arg1;
208193 } else {
209- hash = X_Callback_classifyCallbackArgs( opt_arg1, opt_arg2, opt_arg3, this );
194+ cbHash = X_Callback_classifyCallbackArgs( opt_arg1, opt_arg2, opt_arg3, this );
210195 };
211196
212- if( ( unlistens = this._unlistens ) && ( unlistens = unlistens[ opt_type ] ) ){
197+ if( ( unlistens = listeners._unlistens ) && ( unlistens = unlistens[ opt_type ] ) ){
213198 for( i = unlistens.length; i; ){
214199 f = unlistens[ --i ];
215- if( f === hash || ( f.x === hash.x && f.f === hash.f && f.s === hash.s ) ) return false;
200+ if( f === cbHash || ( f.x === cbHash.x && f.f === cbHash.f && f.s === cbHash.s && f.lock === lock ) ) return false;
216201 };
217202 };
218203 for( i = list.length; i; ){
219204 f = list[ --i ];
220- if( f === hash || ( f.x === hash.x && f.f === hash.f && f.s === hash.s ) ){
205+ if( f === cbHash || ( f.x === cbHash.x && f.f === cbHash.f && f.s === cbHash.s && f.lock === lock ) ){
221206 // index を要求された場合、lock されていない、または unlock なら index を返す
222- return X_EventDispatcher_needsIndex ? ( X_EventDispatcher_unlock || !f.lock ? i : false ) : true;
207+ return X_EventDispatcher_needsIndex ? i : true;
223208 };
224209 };
225210 return false;
@@ -233,11 +218,14 @@ X.EventDispatcher =
233218 * @return {number} X.Timer.add() の戻り値
234219 */
235220 asyncDispatch : function( delay, e ){
221+ var timerID;
236222 if( delay && e === undefined ){
237223 e = delay;
238224 delay = 0;
239225 };
240- return this[ '_lastLazyID' ] = X.Timer.add( delay, 1, this, X_EventDispatcher_dispatch, [ e ] );
226+ timerID = X.Timer.add( delay, 1, this, X_EventDispatcher_dispatch, [ e ] );
227+ X_EventDispatcher_LAZY_TIMERS[ timerID ] = this;
228+ return timerID;
241229 }
242230 }
243231 );
@@ -253,12 +241,12 @@ X.EventDispatcher =
253241 * @param {(eventHash|string|number)} e
254242 */
255243 function X_EventDispatcher_dispatch( e ){
256- var list = this[ '_listeners' ],
257- ret = X_Callback_NONE,
258- type = e[ 'type' ],
259- unlistens, i, l, args, f, r, sysOnly;
244+ var listeners = this[ '_listeners' ],
245+ ret = X_Callback_NONE,
246+ type = e[ 'type' ],
247+ list, unlistens, i, l, args, f, r, sysOnly, timerID;
260248
261- if( !list || !( list = list[ type || e ] ) ) return ret;
249+ if( !listeners || !( list = listeners[ type || e ] ) ) return ret;
262250
263251 // 数値, 文字が渡された場合
264252 if( !type ){
@@ -267,17 +255,21 @@ function X_EventDispatcher_dispatch( e ){
267255 e.target = e.target || this;
268256 e.currentTarget = e.currentTarget || this;
269257
270- ++this._dispatching;
258+ if( listeners._dispatching ){
259+ ++listeners._dispatching;
260+ } else {
261+ listeners._dispatching = 1;
262+ };
271263
272264 // todo:
273265 // type も保存
274- this._unlistens = this._unlistens || {};
275- unlistens = this._unlistens[ type ];
266+ listeners._unlistens = listeners._unlistens || {};
267+ unlistens = listeners._unlistens[ type ];
276268
277269 for( i = 0; i < list.length; ++i ){
278270 f = list[ i ];
279271 if( !unlistens ){
280- unlistens = this._unlistens[ type ];
272+ unlistens = listeners._unlistens[ type ];
281273 };
282274 if( unlistens && unlistens.indexOf( f ) !== -1 ) continue;
283275
@@ -292,7 +284,7 @@ function X_EventDispatcher_dispatch( e ){
292284 if( f.once || r & X_Callback_UN_LISTEN ){
293285 // dispatch 中に unlisten が作られることがある
294286 if( !unlistens ){
295- unlistens = this._unlistens || ( this._unlistens = {} );
287+ unlistens = listeners._unlistens || ( listeners._unlistens = {} );
296288 unlistens = unlistens[ type ] || ( unlistens[ type ] = [] );
297289 };
298290 unlistens.indexOf( f ) === -1 && ( unlistens[ unlistens.length ] = f );
@@ -304,33 +296,12 @@ function X_EventDispatcher_dispatch( e ){
304296 ret |= X.Type.isFinite( r ) ? r : 0;
305297 };
306298
307- if( ( --this._dispatching ) === 0 ){
308-
309- if( this[ '_lastLazyID' ] && X_Timer_currentUID === this[ '_lastLazyID' ] ){
310- delete this[ '_lastLazyID' ];
311- };
312-
313- // dispatch 中に unlisten された要素の削除
314- unlistens = this._unlistens;
315- delete this._dispatching;
316- delete this._unlistens;
317- // _unlistens に入っている callbackHash は、lock をクリアしている
318- X_EventDispatcher_unlock = true;
319- for( type in unlistens ){
320- //if( X_EMPTY_OBJECT[ type ] ) continue;
321- list = unlistens[ type ];
322- for( i = list.length; i; ){
323- this.unlisten( type, list[ --i ] );
324- };
325- list.length = 0;
326- delete unlistens[ type ];
327- };
328- X_EventDispatcher_unlock = false;
299+ if( ( --listeners._dispatching ) === 0 ){
300+
301+ delete listeners._dispatching;
329302
330- if( this._killReserved ){
331- this.kill();
332- } else
333- if( list = this._reserves ){
303+ // dispatch 中に listen されたイベントの追加
304+ if( list = listeners._reserves ){
334305 for( i = 0, l = list.length; i < l; ++i ){
335306 f = list[ i ];
336307 X_EventDispatcher_once = f[ 4 ];
@@ -341,7 +312,36 @@ function X_EventDispatcher_dispatch( e ){
341312 f.length = 0;
342313 };
343314 list.length = 0;
344- delete this._reserves;
315+ delete listeners._reserves;
316+ };
317+
318+ // dispatch 中に unlisten されたイベントの削除
319+ if( unlistens = listeners._unlistens ){
320+ delete listeners._unlistens;
321+
322+ // _unlistens に入っている callbackHash は、lock をクリアしている
323+ X_EventDispatcher_unlock = true;
324+ for( type in unlistens ){
325+ //if( X_EMPTY_OBJECT[ type ] ) continue;
326+ list = unlistens[ type ];
327+ for( i = list.length; i; ){
328+ this.unlisten( type, list[ --i ] );
329+ };
330+ list.length = 0;
331+ delete unlistens[ type ];
332+ };
333+ X_EventDispatcher_unlock = false;
334+ };
335+
336+ if( X_EventDispatcher_LAZY_TIMERS[ X_Timer_currentUID ] === this ){
337+ delete X_EventDispatcher_LAZY_TIMERS[ X_Timer_currentUID ];
338+ };
339+
340+ if( listeners._killReserved ){
341+ for( timerID in X_EventDispatcher_LAZY_TIMERS ){
342+ if( X_EventDispatcher_LAZY_TIMERS[ timerID ] === this ) return ret;
343+ };
344+ this.kill();
345345 };
346346 };
347347
@@ -359,14 +359,14 @@ function X_EventDispatcher_dispatch( e ){
359359 * @return {X.EventDispatcher}
360360 */
361361 function X_EventDispatcher_listen( type, opt_arg1, opt_arg2, opt_arg3 ){
362- var list = this._listeners,
363- i, raw, add, f;
362+ var listeners = this[ '_listeners' ],
363+ i, raw, add, list, f;
364364
365365 if( !type ) return this;
366366
367- if( this._dispatching ){
368- if( !this._reserves ) this._reserves = [];
369- this._reserves[ this._reserves.length ] = [ type, opt_arg1, opt_arg2, opt_arg3, X_EventDispatcher_once, X_EventDispatcher_lock ];
367+ if( listeners && listeners._dispatching ){
368+ if( !listeners._reserves ) listeners._reserves = [];
369+ listeners._reserves[ listeners._reserves.length ] = [ type, opt_arg1, opt_arg2, opt_arg3, X_EventDispatcher_once, X_EventDispatcher_lock ];
370370 return this;
371371 };
372372
@@ -378,12 +378,12 @@ function X_EventDispatcher_listen( type, opt_arg1, opt_arg2, opt_arg3 ){
378378 };
379379
380380 raw = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
381- add = raw && ( !list || !list[ type ] ) && X.Type.isString( type );
382-
381+ add = raw && ( !listeners || !listeners[ type ] ) && X.Type.isString( type );
382+
383383 if( this.listening( type, opt_arg1 || this, opt_arg2, opt_arg3 ) ) return this;
384384
385- if( !list ) list = this._listeners = {};
386- if( !( list = list[ type ] ) ) list = this._listeners[ type ] = [];
385+ if( !listeners ) listeners = this[ '_listeners' ] = {};
386+ list = listeners[ type ] || ( listeners[ type ] = [] );
387387
388388 add && X_EventDispatcher_addEvent( this, type, raw, list );
389389
@@ -416,9 +416,9 @@ function X_EventDispatcher_systemListen( that, type, opt_arg1, opt_arg2, opt_arg
416416 * @param {Array=} opt_arg3
417417 */
418418 function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){
419- var list = this._listeners,
420- _list, reserves, unlistens, i, f, raw, empty;
421- if( !list ) return this;
419+ var listeners = this[ '_listeners' ],
420+ list, reserves, unlistens, i, f, raw, k, empty;
421+ if( !listeners ) return this;
422422
423423 if( X.Type.isArray( opt_type ) ){
424424 for( i = opt_type.length; i; ){
@@ -432,11 +432,12 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){
432432
433433 if( opt_type === undefined ){
434434 // 全て削除
435- for( opt_type in list ){
435+ for( opt_type in listeners ){
436436 //if( X_EMPTY_OBJECT[ opt_type ] ) continue;
437- _list = list[ opt_type ];
438- for( i = _list.length; i; ){
439- this.unlisten( opt_type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用
437+ if( opt_type.charAt( 0 ) === '_' ) continue;
438+ list = listeners[ opt_type ];
439+ for( i = list.length; i; ){
440+ this.unlisten( opt_type, list[ --i ] ); // override されていることがあるので、必ず unlisten を使用
440441 };
441442 // this.unlisten( opt_type ); これは無茶!
442443 };
@@ -444,19 +445,19 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){
444445 } else
445446 if( opt_arg1 === undefined ){
446447 // 同一タイプを全て削除
447- if( _list = list[ opt_type ] ){
448- for( i = _list.length; i; ){
449- this.unlisten( opt_type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用
448+ if( list = listeners[ opt_type ] ){
449+ for( i = list.length; i; ){
450+ this.unlisten( opt_type, list[ --i ] ); // override されていることがあるので、必ず unlisten を使用
450451 };
451452 };
452453 return this;
453454 } else
454- if( reserves = this._reserves ){
455+ if( reserves = listeners._reserves ){
455456 for( i = reserves.length; i; ){
456457 f = reserves[ --i ];
457- if( f[ 0 ] === opt_type && f[ 1 ] === opt_arg1 && f[ 2 ] === opt_arg2 && f[ 3 ] === opt_arg3 ){
458+ if( f[ 0 ] === opt_type && f[ 1 ] === opt_arg1 && f[ 2 ] === opt_arg2 && f[ 3 ] === opt_arg3 && ( !f[ 5 ] || X_EventDispatcher_unlock ) ){
458459 reserves.splice( i, 1 );
459- if( !reserves.legth ) delete this._reserves;
460+ if( !reserves.legth ) delete listeners._reserves;
460461 return this;
461462 };
462463 };
@@ -467,22 +468,31 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){
467468 X_EventDispatcher_needsIndex = false;
468469 if( i === false ) return this;
469470
470- f = ( _list = list[ opt_type ] )[ i ];
471- // _unlistens に入っている callbackHash は、lock をクリアしている
472- if( unlistens = this._unlistens ){
471+ f = ( list = listeners[ opt_type ] )[ i ];
472+
473+ if( unlistens = listeners._unlistens ){
474+ // _unlistens に入っている callbackHash は、lock のチェックは済んでいる
473475 ( unlistens = unlistens[ opt_type ] ) ?
474476 ( unlistens[ unlistens.length ] = f ) :
475- ( this._unlistens[ opt_type ] = [ f ] );
477+ ( listeners._unlistens[ opt_type ] = [ f ] );
476478 } else {
477479 delete f.once;
478- _list.splice( i, 1 );
479- if( !_list.length ){
480+ list.splice( i, 1 );
481+ if( !list.length ){
480482 raw = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
481- delete list[ opt_type ];
482- if( empty = X_Object_isEmpty( list ) ) delete this._listeners;
483+ delete listeners[ opt_type ];
484+ //empty = X_Object_isEmpty( listeners );
485+ // TODO カウンター
486+ empty = true;
487+ for( k in listeners ){
488+ if( k.charAt( 0 ) === '_' ) continue;
489+ empty = false;
490+ break;
491+ };
483492 if( raw && '' + parseFloat( opt_type ) !== '' + opt_type ){ // 数字イベントの除外
484- X_EventDispatcher_removeEvent( this, opt_type, raw, _list, !empty );
493+ X_EventDispatcher_removeEvent( this, opt_type, raw, list, !empty );
485494 };
495+ if( empty ) delete this[ '_listeners' ];
486496 };
487497 };
488498 return this;
@@ -515,66 +525,84 @@ var X_EventDispatcher_actualAddEvent =
515525 // Days on the Moon DOM Events とブラウザの実装
516526 // http://nanto.asablo.jp/blog/2007/03/23/1339502
517527 // Safari 2 では関数オブジェクトしか EventListener として使えませんが、Safari のナイトリービルドでは handleEvent メソッドを持つオブジェクトも EventListener として使えるようです。
518- X_UA_EVENT.W3C /* && ( X_UA.WebKit < 525.13 || X_UA.Opera7 || X_UA.NetFront < 4 ) */ ? // Safari3-
528+ X_UA_EVENT.W3C ?
519529 (function( that, type, raw, list ){
520- if( that._isXHR && X_UA.Opera < 12 ){
521- // Opera11- の XHR は event オブジェクトが返らないため, eventType 毎に callback を指定する addEventListener もない
522- raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
523- } else
524- if( that._isSilverlight ){
525- list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
526- list.sltoken = raw.AddEventListener( type, list.slcallback );
527- } else
528- // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない?
529- // むしろ、MacOSX のブラウザ全般で起こる??
530- if( ( X_UA.WebKit || X_UA.Blink ) &&
531- ( type === 'webkitTransitionEnd' || type === 'transitionend' ||
532- type === 'animationend' || type === 'webkitAnimationEnd' ||
533- type === 'animationstart' || type === 'webkitAnimationStart' ||
534- type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){
535- raw.addEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );
536- } else {
537- console.log( 'event > ' + type );
538- that._handleEvent || ( that._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
530+ var f;
531+ switch( that[ '_rawType' ] ){
532+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
533+ list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
534+ list.sltoken = raw.AddEventListener( type, list.slcallback );
535+ break;
536+
537+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
538+ if( X_UA.Opera < 12 ){
539+ // Opera11- の XHR は event オブジェクトが返らないため, eventType 毎に callback を指定する addEventListener もない
540+ raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
541+ break;
542+ };
539543
540- if( raw.addEventListener ){
541- raw.addEventListener( type, that._handleEvent, false );
542- } else {
543- // Safari は Image, Opera7 は window
544- raw[ 'on' + type ] = that._handleEvent;
545- };
544+ default :
545+ // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない?
546+ // むしろ、MacOSX のブラウザ全般で起こる??
547+ if( ( X_UA.WebKit || X_UA.Blink ) &&
548+ ( type === 'webkitTransitionEnd' || type === 'transitionend' ||
549+ type === 'animationend' || type === 'webkitAnimationEnd' ||
550+ type === 'animationstart' || type === 'webkitAnimationStart' ||
551+ type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){
552+ raw.addEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );
553+ } else {
554+ f = that[ '_listeners' ]._handleEvent || ( that[ '_listeners' ]._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
555+
556+ if( raw.addEventListener ){
557+ raw.addEventListener( type, f, false );
558+ } else {
559+ // Safari は Image, Opera7 は window
560+ raw[ 'on' + type ] = f;
561+ };
562+ };
546563 };
547564 }) :
548565 X_UA_EVENT.IE ?
549566 (function( that, type, raw, list ){
550- if( that._isXHR ){
551- // ie8- の XHR は window.event が更新されないため, eventType 毎に callback を指定する
552- raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
553- } else
554- if( that._isSilverlight ){
555- list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
556- list.sltoken = raw.AddEventListener( type, list.slcallback );
557- } else {
558- that._handleEvent || ( that._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
567+ var f;
568+ switch( that[ '_rawType' ] ){
569+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
570+ list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
571+ list.sltoken = raw.AddEventListener( type, list.slcallback );
572+ break;
559573
560- if( raw.attachEvent ){
561- raw.attachEvent( 'on' + type, that._handleEvent );
562- } else {
563- raw[ 'on' + type ] = that._handleEvent;
564- };
574+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
575+ // ie8- の XHR は window.event が更新されないため, eventType 毎に callback を指定する
576+ raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
577+ break;
578+
579+ default :
580+ f = that[ '_listeners' ]._handleEvent || ( that[ '_listeners' ]._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
581+
582+ if( raw.attachEvent ){
583+ raw.attachEvent( 'on' + type, f );
584+ } else {
585+ raw[ 'on' + type ] = f;
586+ };
587+ break;
565588 };
566589 }) :
567590 (function( that, type, raw, list ){
568- if( that._isXHR ){
569- // ie4 mobile は XHR をサポート!
570- raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
571- } else
572- if( that._isSilverlight ){
573- // DOM0 で Silverlight ってあるの?
574- list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
575- list.sltoken = raw.AddEventListener( type, list.slcallback );
576- } else {
577- raw[ 'on' + type ] = that._handleEvent || ( that._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
591+ switch( that[ '_rawType' ] ){
592+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
593+ // DOM0 で Silverlight ってあるの -> ie4 mobile?
594+ list.slcallback = X_Callback_create( that, X_EventDispatcher_sliverLightDispatch, [ type ] );
595+ list.sltoken = raw.AddEventListener( type, list.slcallback );
596+ break;
597+
598+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
599+ // ie4 mobile は XHR をサポート!
600+ raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] );
601+ break;
602+
603+ default :
604+ raw[ 'on' + type ] = that[ '_listeners' ]._handleEvent || ( that[ '_listeners' ]._handleEvent = X_Callback_create( that, X_EventDispatcher_actualHandleEvent ) );
605+ break;
578606 };
579607 });
580608
@@ -610,82 +638,97 @@ function X_EventDispatcher_removeEvent( that, type, raw, list, skip ){
610638 };
611639
612640 var X_EventDispatcher_actualRemoveEvent =
613- X_UA_EVENT.W3C /*&& ( X_UA.WebKit < 525.13 || X_UA.Opera7 || X_UA.NetFront < 4 )*/ ? // Safari3-
641+ X_UA_EVENT.W3C ?
614642 (function( that, type, raw, list, skip ){
615- if( that._isXHR && X_UA.Opera < 12 ){
616- X_Callback_correct( raw[ 'on' + type ] );
617- raw[ 'on' + type ] = '';
618- } else
619- if( that._isSilverlight ){
620- raw.RemoveEventListener( type, list.sltoken ); // token
621- X_Callback_correct( list.slcallback );
622- delete list.sltoken;
623- delete list.slcallback;
624- } else
625- if( ( X_UA.WebKit || X_UA.Blink ) &&
626- ( type === 'webkitTransitionEnd' || type === 'transitionend' ||
627- type === 'animationend' || type === 'webkitAnimationEnd' ||
628- type === 'animationstart' || type === 'webkitAnimationStart' ||
629- type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){
630- raw.removeEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );
631- } else {
632-
633- if( raw.addEventListener ){
634- raw.removeEventListener( type, that._handleEvent, false );
635- } else {
636- raw[ 'on' + type ] = null;
637- };
638- if( !skip ){
639- X_Callback_correct( that._handleEvent );
640- delete that._handleEvent;
641- };
643+ switch( that[ '_rawType' ] ){
644+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
645+ raw.RemoveEventListener( type, list.sltoken ); // token
646+ X_Callback_correct( list.slcallback );
647+ delete list.sltoken;
648+ delete list.slcallback;
649+ break;
650+
651+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
652+ if( X_UA.Opera < 12 ){
653+ // Opera11- の XHR は event オブジェクトが返らないため, eventType 毎に callback を指定する addEventListener もない
654+ X_Callback_correct( raw[ 'on' + type ] );
655+ raw[ 'on' + type ] = '';
656+ break;
657+ };
658+
659+ default :
660+ if( ( X_UA.WebKit || X_UA.Blink ) &&
661+ ( type === 'webkitTransitionEnd' || type === 'transitionend' ||
662+ type === 'animationend' || type === 'webkitAnimationEnd' ||
663+ type === 'animationstart' || type === 'webkitAnimationStart' ||
664+ type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){
665+ raw.removeEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );
666+ } else
667+ if( raw.addEventListener ){
668+ raw.removeEventListener( type, that[ '_listeners' ]._handleEvent, false );
669+ } else {
670+ raw[ 'on' + type ] = null;
671+ };
672+
673+ if( !skip && that[ '_listeners' ]._handleEvent ){
674+ X_Callback_correct( that[ '_listeners' ]._handleEvent );
675+ delete that[ '_listeners' ]._handleEvent;
676+ };
642677 };
643678 }) :
644679 X_UA_EVENT.IE ?
645680 (function( that, type, raw, list, skip ){
646- if( that._isXHR ){
647- X_Callback_correct( raw[ 'on' + type ] );
648- raw[ 'on' + type ] = X.emptyFunction;
649- raw[ 'on' + type ] = '';
650- } else
651- if( that._isSilverlight ){
652- raw.RemoveEventListener( type, list.sltoken ); // token
653- X_Callback_correct( list.slcallback );
654- delete list.sltoken;
655- delete list.slcallback;
656- } else {
657- if( raw.attachEvent ){
658- raw.detachEvent( 'on' + type, that._handleEvent );
659- } else {
681+ switch( that[ '_rawType' ] ){
682+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
683+ raw.RemoveEventListener( type, list.sltoken ); // token
684+ X_Callback_correct( list.slcallback );
685+ delete list.sltoken;
686+ delete list.slcallback;
687+ break;
688+
689+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
690+ X_Callback_correct( raw[ 'on' + type ] );
660691 raw[ 'on' + type ] = X.emptyFunction;
661692 raw[ 'on' + type ] = '';
662- };
663-
664- if( !skip ){
665- X_Callback_correct( that._handleEvent );
666- delete that._handleEvent;
667- };
693+ break;
694+
695+ default :
696+ if( raw.attachEvent ){
697+ raw.detachEvent( 'on' + type, that[ '_listeners' ]._handleEvent );
698+ } else {
699+ raw[ 'on' + type ] = X.emptyFunction;
700+ raw[ 'on' + type ] = '';
701+ };
702+
703+ if( !skip ){
704+ X_Callback_correct( that[ '_listeners' ]._handleEvent );
705+ delete that[ '_listeners' ]._handleEvent;
706+ };
668707 };
669708 }) :
670709 (function( that, type, raw, list, skip ){
671- if( that._isXHR ){
672- X_Callback_correct( raw[ 'on' + type ] );
673- raw[ 'on' + type ] = X.emptyFunction;
674- raw[ 'on' + type ] = '';
675- } else
676- if( that._isSilverlight ){
677- raw.RemoveEventListener( type, list.sltoken ); // token
678- X_Callback_correct( list.slcallback );
679- delete list.sltoken;
680- delete list.slcallback;
681- } else {
682- raw[ 'on' + type ] = X.emptyFunction;
683- raw[ 'on' + type ] = '';
710+ switch( that[ '_rawType' ] ){
711+ case X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT :
712+ raw.RemoveEventListener( type, list.sltoken ); // token
713+ X_Callback_correct( list.slcallback );
714+ delete list.sltoken;
715+ delete list.slcallback;
716+ break;
684717
685- if( !skip ){
686- X_Callback_correct( that._handleEvent );
687- delete that._handleEvent;
688- };
718+ case X_EventDispatcher_EVENT_TARGET_TYPE.XHR :
719+ X_Callback_correct( raw[ 'on' + type ] );
720+ raw[ 'on' + type ] = X.emptyFunction;
721+ raw[ 'on' + type ] = '';
722+ break;
723+
724+ default :
725+ raw[ 'on' + type ] = X.emptyFunction;
726+ raw[ 'on' + type ] = '';
727+
728+ if( !skip ){
729+ X_Callback_correct( that[ '_listeners' ]._handleEvent );
730+ delete that[ '_listeners' ]._handleEvent;
731+ };
689732 };
690733 });
691734
@@ -762,13 +805,14 @@ if( X_UA.WebKit < 525.13 ){ // Safari3-
762805 // イベントの退避、dom が画面から抜かれる場合に実施しておく
763806 // 退避したイベントの復帰
764807 function X_EventDispatcher_toggleAllEvents( that, add ){
765- var list = that._listeners,
808+ var list = that[ '_listeners' ],
766809 raw = that._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that ),
767810 f = add ? X_EventDispatcher_addEvent : X_EventDispatcher_removeEvent,
768811 type;
769812 if( !list || !raw ) return;
770813 for( type in list ){
771814 //if( X_EMPTY_OBJECT[ type ] ) continue;
815+ if( type.charAt( 0 ) === '_' ) continue;
772816 // 数字イベントの除外
773817 if( '' + parseFloat( type ) !== type ){
774818 // TODO type rename はここ
--- a/0.6.x/js/01_core/14_XTimer.js
+++ b/0.6.x/js/01_core/14_XTimer.js
@@ -114,7 +114,7 @@ X.Timer = {
114114 var list = X_Timer_TICKET_LIST,
115115 i = list.length,
116116 l = i,
117- f, q;
117+ f, q, eventDispatcher, lazy, listeners;
118118 // fire 中の cancel
119119 if( X_Timer_busyTimeout ){
120120 if( !X_Timer_removal ) X_Timer_removal = {};
@@ -123,6 +123,26 @@ X.Timer = {
123123 for( ; i; ){
124124 if( ( q = list[ --i ] ).uid === uid ){
125125 list.splice( i, 1 );
126+
127+ /*
128+ * lazyDispatch 中の EventDispatcher の有無を調べる
129+ */
130+ if( X_EventDispatcher_LAZY_TIMERS[ uid ] ){
131+ eventDispatcher = X_EventDispatcher_LAZY_TIMERS[ uid ];
132+ delete X_EventDispatcher_LAZY_TIMERS[ uid ];
133+
134+ listeners = eventDispatcher[ '_listeners' ];
135+ if( listeners && !listeners._dispatching && listeners._killReserved ){
136+ for( uid in X_EventDispatcher_LAZY_TIMERS ){
137+ if( X_EventDispatcher_LAZY_TIMERS[ uid ] === eventDispatcher ){
138+ lazy = true;
139+ break;
140+ };
141+ };
142+ !lazy && eventDispatcher.kill();
143+ };
144+ };
145+
126146 !X_Timer_skipUpdate && ( q.last <= X_Timer_waitTime || l === 1 ) && X_Timer_update();
127147 break;
128148 };
--- a/0.6.x/js/02_dom/02_XNode.js
+++ b/0.6.x/js/02_dom/02_XNode.js
@@ -9,7 +9,7 @@ var
99 STYLE_IS_INVISIBLE : 2 << 2, // visibility : hidden or opacity : 0
1010 STYLE_IS_POS_ABSOLUTE : 2 << 3, // position : absolute
1111 STYLE_IS_NO_OVERFLOW : 2 << 4, // overflow : hidden
12- STYLE_IS_WIDTH_LENGTH : 2 << 5, // width : width() のための commitUpdate が不要
12+ STYLE_IS_WIDTH_LENGTH : 2 << 5, // width : overflow:hidden,要素無し、または要素が非表示なら、 width() のための commitUpdate が不要
1313 STYLE_IS_WIDTH_PCT : 2 << 6, // width : width() のための commitUpdate が不要かもしれない。(親で LENGTH が指定されているなら)
1414 STYLE_IS_HEIGHT_LENGTH : 2 << 7, // height :
1515 STYLE_IS_HEIGHT_PCT : 2 << 8, // height :
@@ -18,34 +18,33 @@ var
1818
1919 DIRTY_POSITION : 2 << 11, // 要素位置の変更が起こった。
2020 DIRTY_CONTENT : 2 << 12, // width, height, x, y textNode の内容 TODO html と排他なので ID と共通でいい
21- DIRTY_ID : 2 << 13, // width, height, x, y
22- DIRTY_CLASSNAME : 2 << 14, // X_Node_CSS_getCharSize, width, height, x, y
23- DIRTY_ATTR : 2 << 15, // X_Node_CSS_getCharSize, width, height, x, y
24- DIRTY_CSS : 2 << 16, // X_Node_CSS_getCharSize, width, height, x, y
25- DIRTY_IE_FILTER : X_UA.IE < 10 && X_UA.ActiveX ? 2 << 17 : 0, //
21+ DIRTY_ID : 2 << 12, // width, height, x, y
22+ DIRTY_CLASSNAME : 2 << 13, // X_Node_CSS_getCharSize, width, height, x, y
23+ DIRTY_ATTR : 2 << 14, // X_Node_CSS_getCharSize, width, height, x, y
24+ DIRTY_CSS : 2 << 15, // X_Node_CSS_getCharSize, width, height, x, y
25+ DIRTY_IE_FILTER : X_UA.IE < 10 && X_UA.ActiveX ? 2 << 16 : 0, //
2626
27-
28- ELM_NEED_INIT : 2 << 18,
29- OLD_ATTRTEXT : 2 << 19,
30- OLD_CSSTEXT : 2 << 20,
27+ ACTUAL_LISTENING : 2 << 17,
28+ OLD_ATTRTEXT : 2 << 18,
29+ OLD_CSSTEXT : 2 << 19,
3130
3231 // filter 要素が親子になると不具合が出るのを検出
33- IE_FILTER_NOW : 2 << 21,
32+ IE_FILTER_NOW : 2 << 20,
3433
3534 //GPU_WAITING : 2 << 20, // 1:子のGPU解除待
36- GPU_RESERVED : 2 << 22, // 2:GPU予約
37- GPU_NOW : 2 << 23, // 3:GPU now!
38- GPU_RELEASE_RESERVED : 2 << 24, // 4:GPU解除予約
35+ GPU_RESERVED : 2 << 21, // 2:GPU予約
36+ GPU_NOW : 2 << 22, // 3:GPU now!
37+ GPU_RELEASE_RESERVED : 2 << 23, // 4:GPU解除予約
3938
40- IE4_HAS_TEXTNODE : X_UA.IE4 ? 2 << 22 : 0,
41- IE4_HAS_ELEMENT : X_UA.IE4 ? 2 << 23 : 0,
42- IE4_DIRTY_CHILDREN : X_UA.IE4 ? 2 << 24 : 0,
43- IE4_FIXED : X_UA.IE4 ? 2 << 25 : 0,
39+ IE4_HAS_TEXTNODE : X_UA.IE4 ? 2 << 21 : 0,
40+ IE4_HAS_ELEMENT : X_UA.IE4 ? 2 << 22 : 0,
41+ IE4_DIRTY_CHILDREN : X_UA.IE4 ? 2 << 23 : 0,
42+ IE4_FIXED : X_UA.IE4 ? 2 << 24 : 0,
4443
45- IE5_DISPLAY_NONE_FIX : X_UA.IE5 && X_UA.ActiveX ? 2 << 25 : 0
44+ IE5_DISPLAY_NONE_FIX : X_UA.IE5 && X_UA.ActiveX ? 2 << 24 : 0
4645 },
4746
48- X_Node_BITMASK_RESET_STYLE = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (
47+ X_Node_BITMASK_RESET_STYLE = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (
4948 X_Node_State.STYLE_IS_DISPLAY_NONE |
5049 X_Node_State.STYLE_IS_INVISIBLE |
5150 X_Node_State.STYLE_IS_POS_ABSOLUTE |
@@ -57,15 +56,15 @@ var
5756 X_Node_State.STYLE_IS_FONT_LENGTH |
5857 X_Node_State.STYLE_IS_FONT_PCT ),
5958
60- X_Node_BitMask_IS_DIRTY = X_Node_State.DIRTY_POSITION |
59+ X_Node_BitMask_IS_DIRTY = X_Node_State.DIRTY_POSITION |
6160 X_Node_State.DIRTY_CONTENT | X_Node_State.DIRTY_ID | X_Node_State.DIRTY_CLASSNAME |
6261 X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_CSS | X_Node_State.DIRTY_IE_FILTER,
6362
64- X_Node_BitMask_RESET_DIRTY = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ X_Node_BitMask_IS_DIRTY,
63+ X_Node_BitMask_RESET_DIRTY = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ X_Node_BitMask_IS_DIRTY,
6564
66- X_Node_BitMask_RESET_GPU = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( X_Node_State.GPU_RESERVED | X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ),
65+ X_Node_BitMask_RESET_GPU = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( X_Node_State.GPU_RESERVED | X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ),
6766
68- X_Node_BitMask_IE4_IS_MIX = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,
67+ X_Node_BitMask_IE4_IS_MIX = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,
6968
7069 X_Node_TYPE = {
7170 XNODE : 1,
@@ -106,7 +105,7 @@ var
106105 _uid : 0,
107106 _flags : X_Node_State.DESTROYED,
108107
109- _rawObject : null,
108+ // _rawObject : null,
110109 _rect : null, //
111110 _fontSize : 0,
112111
@@ -224,7 +223,7 @@ var
224223
225224 appendTo : X_Node_appendTo,
226225
227- appendToRoot : X_Node_appendToRoot,
226+ appendToRoot : X_Node_appendToRoot, // remove
228227
229228 before : X_Node_before, // remove
230229
@@ -676,27 +675,29 @@ function X_Node_destroy( isChild ){
676675 };
677676
678677 function X_Node_onBeforeKill( e ){
679- var xnodes = this._xnodes,
680- elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ),
681- i;
682-
683- if( !this._flags ) return;
678+ var xnodes = this._xnodes, i, elm;
684679
685- delete X_Node_CHASHE[ this._uid ];
680+ if( !this._flags ) return X.Callback.NONE;
686681
682+ elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
683+ elm && this._listeners && this.unlisten(); // イベントの退避
684+
687685 if( xnodes && ( i = xnodes.length ) ){
688686 for( ; i; ){
689687 X_Node_onBeforeKill.call( xnodes[ --i ] );
690688 };
691689 };
692690
693- e && this.remove();
694- elm && this._listeners && this.unlisten(); // イベントの退避
695-
696- if( e && elm && elm.parentNode && elm.parentNode.tagName ){
697- delete this._flags;
698- return X.Callback.PREVENT_DEFAULT;
691+ delete X_Node_CHASHE[ this._uid ];
692+
693+ if( e ){
694+ this.remove();
695+ if( X_Node_reserveRemoval[ X_Node_reserveRemoval.length - 1 ] === this ){
696+ delete this._flags;
697+ return X.Callback.PREVENT_DEFAULT;
698+ };
699699 };
700+ return X.Callback.NONE;
700701 };
701702
702703
@@ -1039,6 +1040,7 @@ function X_Node_startUpdate( time ){
10391040 if( i = removal.length ){
10401041 for( ; i; ){
10411042 xnode = removal[ --i ];
1043+ // TODO GPU レイヤーの子の場合、remove をスキップする。 非GPU レイヤーへ apppend される場合、clone する?
10421044 X_Node__actualRemove( xnode );
10431045 !xnode._flags && xnode.kill();
10441046 };
@@ -1066,8 +1068,8 @@ function X_Node_startUpdate( time ){
10661068 };
10671069
10681070 /*
1069- * 1. GPU_NOW の場合、これ以下の一切の更新を行わない
1070- * 2. GPU解放予約 の場合、この要素のみ変更を行う。rAF 後にさらに更新するためフラグを立てる。
1071+ * 1. GPU_NOW の場合、子の変更は行わない
1072+ * 2. GPU解放予約 の場合//、この要素のみ変更を行う。rAF 後にさらに更新するためフラグを立てる。
10711073 * 3. GPU予約 -> GPU
10721074 * 4. style="display:none" の場合、これ以下の変更を行わない。
10731075 * 5. ie5 非表示フラグが立っていて、親と自身の class・id によって非表示になっていて、親と自身に変更がない。accumulatedFlags を使用。
@@ -1118,7 +1120,7 @@ var X_Node__commitUpdate =
11181120 return nextElement;
11191121 };
11201122 elm && ( elm.style.display = 'none' );
1121- return elm.nextSibling === nextElement ? elm : nextElement;
1123+ return ( elm && elm.nextSibling === nextElement ) ? elm : nextElement;
11221124 };
11231125
11241126 // 5. ie5 非表示fixフラグ
@@ -1140,7 +1142,7 @@ var X_Node__commitUpdate =
11401142 };
11411143 } else
11421144 if( X_Node_strictElmCreation ){
1143- that._flags & X_Node_State.DIRTY_CSS && X_Node_CSS_objToCssText( that, true );
1145+ that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??
11441146
11451147 that._rawObject = elm =
11461148 document.createElement( [
@@ -1148,9 +1150,9 @@ var X_Node__commitUpdate =
11481150 ' UID="', that._uid, '"',
11491151 that._id ? ' id="' + that._id + '"' : '',
11501152 that._className ? ' class="' + that._className + '"' : '',
1151- that._flags & X_Node_State.OLD_ATTRTEXT ? X_Node_Attr_objToAttrText( that ) : that._attrText,
1153+ X_Node_Attr_objToAttrText( that, true ),
11521154 that._cssText ? ' style="' + that._cssText + '"' : '',
1153- '>' ].join( '' ) );
1155+ '>' ].join( '' ) );
11541156 } else {
11551157 that._rawObject = elm = document.createElement( that._tag );
11561158 };
@@ -1163,18 +1165,17 @@ var X_Node__commitUpdate =
11631165 };
11641166
11651167 if( that._tag ){
1166- // src の onload があるので先ではないか?
1167- // TODO ie の str から要素を作る場合、srcだけ イベント設定後ではないか?
11681168 X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰
1169+ that._flags |= X_Node_State.ACTUAL_LISTENING;
11691170
11701171 if( X_Node_documentFragment ){
11711172 //( frg = X_Node_documentFragment ).appendChild( elm );
11721173 };
11731174
11741175 if( X_Node_strictElmCreation ){
1175- // TODO src 等の設定
1176- delete that._newAttrs;
11771176 that._flags &= X_Node_BitMask_RESET_DIRTY;
1177+ // ie の string から要素を作る場合、ネットワーク系属性は onload イベントなどを拾うために、要素生成->イベント復帰後に適用する
1178+ that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR ); // Network 系の属性は遅らせて設定
11781179 that._flags |= X_Node_State.DIRTY_IE_FILTER;// doc 追加後に filter を指定しないと有効にならない。
11791180 } else {
11801181 elm.UID = that._uid;
@@ -1185,7 +1186,7 @@ var X_Node__commitUpdate =
11851186 // http://outcloud.blogspot.jp/2010/09/iframe.html
11861187 // この問題は firefox3.6 で確認
11871188 if( X_UA.Gecko ){
1188- if( that._tag === 'IFRAME' && !that._attrs[ 'src' ] ){
1189+ if( that._tag === 'IFRAME' && ( !that._attrs || !that._attrs[ 'src' ] ) ){
11891190 //elm.contentWindow.location.replace = elm.src = 'about:blank';
11901191 that.attr( 'src', 'about:blank' );
11911192 };
@@ -1200,19 +1201,19 @@ var X_Node__commitUpdate =
12001201 nextElement ?
12011202 parentElement.insertBefore( elm, nextElement ) :
12021203 parentElement.appendChild( elm );
1203-
1204- if( X_Node_displayNoneFixForIE5 ) that._flags |= X_Node_State.DIRTY_POSITION;
12051204 };
12061205
1207- that._flags & X_Node_State.DIRTY_POSITION && X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰
1208- that._flags &= ~X_Node_State.DIRTY_POSITION;
1206+ if( that._listeners && ( that._flags & X_Node_State.ACTUAL_LISTENING ) === 0 ){
1207+ X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避
1208+ that._flags |= X_Node_State.ACTUAL_LISTENING;
1209+ };
12091210
12101211 // 8. 更新の適用
1211- if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ) delete that._fontSize;
1212-
1213- that._flags & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );
1214-
1215-
1212+ if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ){
1213+ delete that._fontSize;
1214+ X_Node__updateRawNode( that, elm );
1215+ };
1216+
12161217 // 9. ie5 only
12171218 // 親及び自身へのクラス・id指定で display : none になるケースがありそれを検出
12181219 // 生成と破棄が繰り返されてしまう、親と自身の id, class が変わった場合だけ再生成。 accumulatedFlags & ( ID | CLASSNAME )
@@ -1266,7 +1267,7 @@ var X_Node__commitUpdate =
12661267 return prevElement;
12671268 };
12681269 };
1269- return elm || nextElement;
1270+ return elm || prevElement;
12701271 };
12711272
12721273 if( !elm ){
@@ -1341,7 +1342,6 @@ var X_Node__commitUpdate =
13411342 (function(){});
13421343
13431344 /*
1344- * TODO IE5 は filter-fix があるため、親から変更を適用し、自信の display:none を調べる
13451345 * GPU レイヤーするブラウザは、子要素から変更を当てていく? <- とりあえず、親要素から。
13461346 */
13471347 var X_Node__updateRawNode =
@@ -1416,7 +1416,6 @@ var X_Node__updateRawNode =
14161416 } else {
14171417 elm.style.cssText = ''; // IE5.5以下 Safari3.2 で必要
14181418 elm.removeAttribute( 'style' );
1419- delete that._cssText;
14201419 };
14211420 } else
14221421 if( that._flags & X_Node_State.DIRTY_IE_FILTER ){
@@ -1461,7 +1460,6 @@ var X_Node__updateRawNode =
14611460 } else {
14621461 elm.style.cssText = '';
14631462 elm.removeAttribute( 'style' );
1464- delete that._cssText;
14651463 };
14661464 } else
14671465 if( that._flags & X_Node_State.DIRTY_IE_FILTER ){
@@ -1519,12 +1517,12 @@ var X_Node__actualCreate =
15191517 } else {
15201518 if( !isChild ) X_Node__actualRemove( that, /* true */ false );
15211519
1522- that._flags & X_Node_State.DIRTY_CSS && X_Node_CSS_objToCssText( that, true );
1520+ that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true );
15231521
15241522 html = [
15251523 '<', that._tag, ' id=', ( that._id || ( 'ie4uid' + uid ) ), ' UID="', uid, '"',
15261524 that._className ? ' class="' + that._className + '"' : '',
1527- that._flags & X_Node_State.OLD_ATTRTEXT ? X_Node_Attr_objToAttrText( that ) : that._attrText,
1525+ X_Node_Attr_objToAttrText( that, true ),
15281526 that._cssText ? ' style="' + that._cssText + '"' : '',
15291527 '>' ];
15301528
@@ -1557,7 +1555,7 @@ var X_Node__actualCreate =
15571555 };
15581556 X_Dom_DTD_EMPTY[ that._tag ] || ( html[ n ] = '<\/' + that._tag + '>' );
15591557
1560- delete that._newAttrs;
1558+ that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR );
15611559 };
15621560
15631561 return html.join( '' );
@@ -1574,8 +1572,12 @@ var X_Node__afterActualCreate =
15741572 X_Node__afterActualCreate( xnodes[ --i ] );
15751573 };
15761574 };
1577- that._flags & X_Node_State.DIRTY_IE_FILTER && X_Node__updateRawNode( that, that._rawObject || X_Node__ie4getRawNode( that ) );
1578- that._flags &= X_Node_BitMask_RESET_DIRTY;
1575+ // ネットわーう系属性と filter は要素生成後に適用
1576+ if( that._flags & ( X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_IE_FILTER ) ){
1577+ X_Node__updateRawNode( that, that._rawObject || X_Node__ie4getRawNode( that ) );
1578+ } else {
1579+ that._flags &= X_Node_BitMask_RESET_DIRTY;
1580+ };
15791581 X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰
15801582 });
15811583
@@ -1597,7 +1599,10 @@ var X_Node__actualRemove =
15971599
15981600 if( !elm ) return;
15991601
1600- that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避
1602+ if( that._flags & X_Node_State.ACTUAL_LISTENING ){
1603+ that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避
1604+ that._flags &= ~X_Node_State.ACTUAL_LISTENING;
1605+ };
16011606
16021607 // ie5では filter の効いている要素をremove時に破棄して、再度append 時に新規生成する
16031608 // ちなみに elm.filters に触ると ie8 でなぜかカラム落ちが発生、、、
@@ -1606,10 +1611,23 @@ var X_Node__actualRemove =
16061611 //elm.style.removeAttribute( 'filter' );
16071612 isChild = false;
16081613 delete that._rawObject;
1609- // 破棄前に value を控える TODO checked, selected も!
1614+ // 破棄前にインタラクティブな属性値を控える
16101615 if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){
1616+ if( !that._attrs ) that._attrs = {};
16111617 that._attrs.value = elm.value;
16121618 };
1619+ if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){
1620+ if( !that._attrs ) that._attrs = {};
1621+ that._attrs.selected = elm.selected;
1622+ };
1623+ if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){
1624+ if( !that._attrs ) that._attrs = {};
1625+ that._attrs.selectedIndex = elm.selectedIndex;
1626+ };
1627+ if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){
1628+ that._attrs.checked = elm.checked;
1629+ };
1630+ // 子要素への参照を外す
16131631 elm.innerHTML = '';
16141632 };
16151633 };
@@ -1635,10 +1653,24 @@ var X_Node__actualRemove =
16351653 if( !elm ) return;
16361654 that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避
16371655
1638- // 破棄前に value を控える TODO checked, selected も!
1656+ // 破棄前にインタラクティブな属性値を控える
16391657 if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){
1658+ if( !that._attrs ) that._attrs = {};
16401659 that._attrs.value = elm.value;
16411660 };
1661+ if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){
1662+ if( !that._attrs ) that._attrs = {};
1663+ that._attrs.selected = elm.selected;
1664+ };
1665+ if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){
1666+ if( !that._attrs ) that._attrs = {};
1667+ that._attrs.selectedIndex = elm.selectedIndex;
1668+ };
1669+ if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){
1670+ if( !that._attrs ) that._attrs = {};
1671+ that._attrs.checked = elm.checked;
1672+ };
1673+
16421674 elm.removeAttribute( 'id' ); // ?
16431675 //document.all[ that._id || ( 'ie4uid' + that._uid ) ] = null; // MacIE5 でエラー
16441676 if( !isChild ) elm.outerHTML = '';
--- a/0.6.x/js/02_dom/05_XNodeAttr.js
+++ b/0.6.x/js/02_dom/05_XNodeAttr.js
@@ -61,57 +61,77 @@ X_Node_Attr_STATIC_VALUE_TYPES = {
6161 checkbox : true
6262 },
6363
64+// 自由な内容が入るため、参照文字への変換が必要
65+X_Node_Attr_toChrReferance = {
66+ value : true,
67+ title : true,
68+ alt : true
69+},
70+
6471 X_Node_Attr_renameForTag = {};
6572 // http://nanto.asablo.jp/blog/2005/10/29/123294
6673 // checked -> defaultChecked
6774 // 動的に生成した input 要素を文書ツリーに挿入する前に設定した checked 属性は反映されず、defaultChecked だと反映される
6875 // ロードイベントを拾うために、要素生成時にネットワーク関連の属性を設定しない。
6976 // -> src (img, iframe, ), link の href, <param name="movie" src=>
70-function X_Node_Attr_objToAttrText( that, skipNetwork, escape ){ // TODO value の escape " -> &quot;
77+ //
78+function X_Node_Attr_objToAttrText( that, skipNetworkForElmCreation ){
7179 var obj = that._attrs,
7280 noValue = X_Node_Attr_noValue,
7381 attrs = [ '' ], // 先頭にスペース
7482 plain = X_EMPTY_OBJECT,
75- n = 0, k, hasNetwork;
76-
77- that._flags &= ~X_Node_State.OLD_ATTRTEXT;
83+ n = 0, k, check;
7884
85+ if( skipNetworkForElmCreation ){
86+ delete that._newAttrs;
87+ // このあとで _newAttr にネットワーク系の属性を控える, attrText には加えない
88+ } else {
89+ that._flags &= ~X_Node_State.OLD_ATTRTEXT;
90+ // 完全な attrText
91+ };
92+
7993 if( !obj ){ // Opera7
8094 delete that._attrText;
8195 return '';
8296 };
97+
8398 for( k in obj ){
8499 if( plain[ k ] ) continue;
85100
86- if( skipNetwork ){
87- switch( k ){
88- case 'value' :
89- if( that._tag === 'LINK' && that._attr && that._attr.name === 'movie' ){
90- hasNetwork = true;
91- continue;
92- };
93- break;
101+ if( skipNetworkForElmCreation ){
102+ check = false;
103+ switch( that._tag + k ){
104+ case 'PARAMvalue' :
105+ check = obj[ 'name' ] !== 'movie';
106+ case 'INPUTsrc' :
107+ check = check || ( obj[ 'type' ] !== 'image' );
108+ case 'LINKhref' :
109+ check = check || ( obj[ 'rel' ] !== 'stylesheet' );
94110
95- case 'src' :
96- hasNetwork = true;
111+ if( !check ) break;
112+
113+ case 'IMGsrc' :
114+ case 'IFRAMEsrc' :
115+ case 'FRAMEsrc' :
116+ case 'SCRIPTsrc' :
117+ case 'EMBEDsrc' :
118+ case 'OBJECTdata' :
119+ case 'BGSOUNDsrc' :
120+ case 'APPLETcode' :
121+ //case 'AUDIOsrc' :
122+ //case 'VIDEOsrc' :
123+ if( !that._newAttrs ) that._newAttrs = {};
124+ that._newAttrs[ k ] = obj[ k ];
97125 continue;
98-
99- case 'href' :
100- if( that._tag === 'LINK' ){
101- hasNetwork = true;
102- continue;
103- };
104126 };
105127 };
106128
107129 attrs[ ++n ] = noValue[ k ] ? k : [
108130 k, '="',
109- k === 'value' ? X_String_toChrReferance( obj[ k ] ) : obj[ k ],
131+ X_Node_Attr_toChrReferance[ k ] ? X_String_toChrReferance( obj[ k ] ) : obj[ k ],
110132 '"' ].join( '' );
111133 };
112134
113- //if( hasNetwork ) that._flags |= X_Node_State.IE_NETWORK_ATTR
114-
115135 if( 0 < n ){
116136 return that._attrText = attrs.join( ' ' );
117137 };
--- a/0.6.x/js/02_dom/06_XNodeCSS.js
+++ b/0.6.x/js/02_dom/06_XNodeCSS.js
@@ -285,6 +285,7 @@ function X_Node_CSS_objToCssText( that, skipFilter ){
285285 };
286286
287287 if( 0 <= n ){
288+ // cssText には完全なものを控えるが、戻すのは filter を抜いたもの
288289 that._cssText = css.join( ';' );
289290 if( skipFilter ){
290291 --css.length;
@@ -522,7 +523,7 @@ Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
522523 if( css[ name ] === v ) continue;
523524 flags = X_Node_CSS_setStyle( css, flags, name, v );
524525 };
525- this._flags = flags | X_Node_State.DIRTY_CSS | X_Node_State.OLD_CSSTEXT;
526+ this._flags |= X_Node_State.DIRTY_CSS | X_Node_State.OLD_CSSTEXT;
526527 this._flags & X_Node_State.IN_TREE && X_Node_reserveUpdate();
527528 delete this._cssText;
528529 return this;
--- a/0.6.x/js/02_dom/10_XNodeAnime.js
+++ b/0.6.x/js/02_dom/10_XNodeAnime.js
@@ -472,24 +472,26 @@ function X_Node_Anime_updatePosition( xnode, x, y, opacity, useGPU ){
472472 });
473473 };
474474
475- if( useGPU ){
476- if( xnode._flags & X_Node_State.GPU_RELEASE_RESERVED ){
477- xnode._flags &= X_Node_BitMask_RESET_GPU;
478- xnode._flags |= X_Node_State.GPU_NOW;
479- } else
480- if( xnode._flags & X_Node_State.GPU_NOW ){
475+ if( X_Node_Anime_translateZ ){
476+ if( useGPU ){
477+ if( xnode._flags & X_Node_State.GPU_RELEASE_RESERVED ){
478+ xnode._flags &= X_Node_BitMask_RESET_GPU;
479+ xnode._flags |= X_Node_State.GPU_NOW;
480+ } else
481+ if( xnode._flags & X_Node_State.GPU_NOW ){
482+ } else {
483+ xnode._flags &= X_Node_BitMask_RESET_GPU;
484+ xnode._flags |= X_Node_State.GPU_RESERVED;
485+ };
481486 } else {
482- xnode._flags &= X_Node_BitMask_RESET_GPU;
483- xnode._flags |= X_Node_State.GPU_RESERVED;
484- };
485- } else {
486- if( xnode._flags & X_Node_State.GPU_NOW ){
487- xnode._flags &= X_Node_BitMask_RESET_GPU;
488- xnode._flags |= X_Node_State.GPU_RELEASE_RESERVED;
489- } else
490- if( xnode._flags & X_Node_State.GPU_RESERVED ){
491- xnode._flags &= X_Node_BitMask_RESET_GPU;
492- };
487+ if( xnode._flags & X_Node_State.GPU_NOW ){
488+ xnode._flags &= X_Node_BitMask_RESET_GPU;
489+ xnode._flags |= X_Node_State.GPU_RELEASE_RESERVED;
490+ } else
491+ if( xnode._flags & X_Node_State.GPU_RESERVED ){
492+ xnode._flags &= X_Node_BitMask_RESET_GPU;
493+ };
494+ };
493495 };
494496 };
495497
--- a/0.6.x/js/06_net/01_XNetXHR.js
+++ b/0.6.x/js/06_net/01_XNetXHR.js
@@ -85,9 +85,9 @@ if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){
8585 X_NET_XHRWrapper = X_Class_override(
8686 new X.EventDispatcher(),
8787 {
88-
88+
89+ _rawType : X_EventDispatcher_EVENT_TARGET_TYPE.XHR,
8990 _rawObject : X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X,
90- _isXHR : true, // X.EventDispatcher で使用 for ie8-
9191 _isXDR : false, // for ie8
9292
9393 _method : '',
--- a/0.6.x/js/07_audio/03_XSilverlightAudio.js
+++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js
@@ -22,7 +22,7 @@ if( X.Pulgin.SilverlightEnabled ){
2222 'X.AV.SilverlightAudioWrapper',
2323 X.Class.POOL_OBJECT,
2424 {
25- _isSilverlight : true, // for X.EventDispatcher.listen
25+ '_rawType' : X_EventDispatcher_EVENT_TARGET_TYPE.SILVER_LIGHT,
2626 proxy : null,
2727
2828 startTime : 0,
旧リポジトリブラウザで表示