OSDN Git Service

Version 0.6.11, add XUI_Gesture.
authoritozyun <itozyun@user.sourceforge.jp>
Thu, 31 Oct 2013 02:02:44 +0000 (11:02 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Thu, 31 Oct 2013 02:02:44 +0000 (11:02 +0900)
0.6.x/js/bootstrap.js [moved from 0.6.x/js/core/bootstrap.js with 100% similarity]
0.6.x/js/core/01_XUa.js
0.6.x/js/core/03_XCallback.js
0.6.x/js/core/05_XTimer.js
0.6.x/js/dom/13_XDomEvent.js
0.6.x/js/dom/17_XView.js
0.6.x/js/ui/05_XUI_Gesture.js [new file with mode: 0644]
0.6.x/js/ui/AbstractDisplayNode.js
0.6.x/js/ui/ChromeBox.js
0.6.x/js/ui/PageRoot.js

index 969346a..b04c1cc 100644 (file)
@@ -3,31 +3,37 @@ if( !window['console'] ) console = { log : function(){} };
 /*\r
  * UA\r
  */\r
-var X = X || {};\r
+var X = X || {\r
+       emptyFunction : new Function,\r
+       inHead        : (function( s ){\r
+               s = s[ s.length - 1 ];\r
+               return ( s.parent || s.parentNode ).tagName.toLowerCase() === ( 'head' );\r
+       })( document.scripts || document.getElementsByTagName( 'script' ) || document.all.tags( 'script' ) )\r
+};\r
 \r
-X.UA = (function(undefined){\r
+X.UA = (function( n, undefined ){\r
        var acme = {},\r
-               n    = navigator,\r
                dua  = n.userAgent,\r
                dav  = n.appVersion,\r
-               tv   = parseFloat(dav);\r
+               tv   = parseFloat(dav),\r
+               i;\r
        acme.Opera  = ( dua.indexOf("Opera") >= 0 ) ? tv : undefined;\r
        acme.IE = undefined;\r
-       if(document.all && !acme.Opera){\r
+       if( document.all && !acme.Opera ){\r
                acme.IE = parseFloat(dav.split("MSIE ")[1]) || undefined;\r
                return acme;\r
-       };      \r
+       };\r
        acme.Khtml  = ( dav.indexOf("Konqueror") >= 0 ) ? tv : undefined;\r
        acme.WebKit = parseFloat(dua.split("WebKit\/")[1]) || undefined;\r
        acme.Chrome = parseFloat(dua.split("Chrome\/")[1]) || undefined;\r
        // replace( reg, ) don't work for Sigmarion2 pocketIE\r
        acme.Gecko  = eval( '(dua.indexOf("Gecko\/") >= 0) ? parseFloat(dua.split("rv:")[1].replace( /^(\d*\.\d*)\.(\d*)/, "$1$2" )) : undefined' );\r
-       var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);\r
-       if(index && !acme.Chrome){\r
-               acme.Safari = parseFloat(dav.split("Version/")[1]);\r
-               if(!acme.Safari || parseFloat(dav.substr(index + 7)) <= 419.3){\r
+       i = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);\r
+       if( i && !acme.Chrome ){\r
+               acme.Safari = parseFloat( dav.split("Version/")[1] );\r
+               if( !acme.Safari || parseFloat(dav.substr( i + 7 )) <= 419.3 ){\r
                        acme.Safari = 2;\r
                };\r
        };\r
        return acme;\r
-})();
\ No newline at end of file
+})( navigator );
\ No newline at end of file
index ec30fa4..40b22fc 100644 (file)
@@ -5,11 +5,10 @@ X.Callback = {
        NONE             :  0,\r
        UN_LISTEN        :  1,\r
        STOP_PROPAGATION :  2,  // 上位階層への伝播のキャンセル\r
-       CANCEL_NOW       :  4,  // 同一階層のリスナーのキャンセル\r
-       STOP_NOW         :  8,\r
-       PREVENT_DEFAULT  : 16,  // 結果動作のキャンセル,\r
-       MONOPOLY         : 32,  // move event を独占する\r
-       SYS_CANCEL       : 64,\r
+       STOP_NOW         :  4,  // 同一階層のリスナーのキャンセル\r
+       PREVENT_DEFAULT  :  8,  // 結果動作のキャンセル,\r
+       MONOPOLY         : 16,  // move event を独占する\r
+       SYS_CANCEL       : 32,\r
        \r
        _LIVE_LIST : [],\r
        _POOL_LIST : [],\r
@@ -41,7 +40,7 @@ X.Callback = {
                if( !f ){\r
                        f = new Function( 'var a=arguments,f=a.callee;f.a=a;return f.c()' ); // f.t=this;\r
                        f.kill = self._kill;\r
-                       f.same = self._same;                    \r
+                       f.same = self._same;\r
                };\r
                live[ live.length ] = f;\r
                if( listener ){\r
index 7f3900c..d08c81e 100644 (file)
@@ -7,12 +7,14 @@ X.Timer = ( function(){
                clearTimeout   = window.clearTimeout,\r
                INTERVAL_TIME  = 16,\r
                TICKET_LIST    = [],\r
+               uid            = 0,\r
                timerId        = -1,\r
                next           = 0,\r
                INDEX_TIME     = 0,\r
                INDEX_LAST     = 1,\r
                INDEX_COUNT    = 2,\r
                INDEX_CALLBACK = 3;\r
+               INDEX_UID      = 4;\r
        \r
        function loop(){\r
                var c    = next,\r
@@ -57,6 +59,37 @@ X.Timer = ( function(){
            };\r
        };\r
        \r
+       var enterFrame =\r
+                       window.requestAnimationFrame ||\r
+                       window.webkitRequestAnimationFrame ||\r
+                       window.mozRequestAnimationFrame ||\r
+                       window.oRequestAnimationFrame ||\r
+                       window.msRequestAnimationFrame ||\r
+                       0,\r
+               cancelFrame =\r
+                       window.cancelRequestAnimationFrame ||\r
+                       window.webkitCancelAnimationFrame ||\r
+                       window.webkitCancelRequestAnimationFrame ||\r
+                       window.mozCancelRequestAnimationFrame ||\r
+                       window.oCancelRequestAnimationFrame ||\r
+                       window.msCancelRequestAnimationFrame ||\r
+                       0,\r
+               REQUEST_FRAME_LIST = [],\r
+               requestID;\r
+       \r
+       function onEnterFrame( time ){\r
+               var list = REQUEST_FRAME_LIST,\r
+                       i    = list.length,\r
+                       f;\r
+               time = time || ( Date.now ? Date.now() : +new Date );\r
+           for( ; i; ){\r
+               ( f = list[ --i ] )( time );\r
+               delete f.uid;\r
+               f.kill();\r
+           };\r
+           list.length = 0;\r
+       };\r
+       \r
        return {\r
                add : function( time, opt_count, args1, args2, args3 ){\r
                        time = time < INTERVAL_TIME ? 1 : ( time / INTERVAL_TIME ) | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
@@ -68,27 +101,27 @@ X.Timer = ( function(){
                                opt_count = 0;\r
                        };\r
 \r
-                       TICKET_LIST[ TICKET_LIST.length ] = [ time, time, opt_count, X.Callback.create( args1, args2, args3 ) ];\r
+                       TICKET_LIST[ TICKET_LIST.length ] = [ time, time, opt_count, X.Callback.create( args1, args2, args3 ), ++uid ];\r
                    update();\r
+                   return uid;\r
                },\r
                once : function( time, args1, args2, args3 ){\r
                        X.Timer.add( time, 1, args1, args2, args3 );\r
                },\r
-               remove : function( args1, args2 ){\r
+               remove : function( uid ){\r
                        var queue,\r
-                               i    = 0,\r
-                               list = TICKET_LIST;\r
-                       if( !callback ) return;\r
-                       while( queue = list[ i ] ){\r
-                               if( queue[ INDEX_CALLBACK ].same( args1, args2 ) === true ){\r
-                                       callback.kill();\r
+                               list = TICKET_LIST,\r
+                               i    = list.length,\r
+                               l    = i;\r
+                       for( ; i; ){\r
+                               if( ( queue = list[ --i ] )[ INDEX_UID ] === uid ){\r
                                        list.splice( i, 1 );\r
+                                       X.Callback._correct( queue[ INDEX_CALLBACK ] );\r
+                                       ( /* queue[ INDEX_COUNT ] <= next  || */ l === 1 ) && update();\r
+                                       queue.length = 0;\r
                                        break;\r
-                               } else {\r
-                                       ++i;\r
                                };\r
                        };\r
-                   update();\r
                }\r
                \r
                // string only ie4-\r
@@ -98,5 +131,28 @@ X.Timer = ( function(){
                        return _loop;\r
                })()\r
                \r
+               ,requestFrame : function( args1, args2, args3 ){\r
+                       var i = REQUEST_FRAME_LIST.length,\r
+                               f;\r
+                       i === 0 && ( requestID = ( enterFrame ? enterFrame( onEnterFrame ) : X.Timer.add( 16, 1, onEnterFrame ) ) );\r
+                       f = REQUEST_FRAME_LIST[ i ] = X.Callback.create( args1, args2, args3 );\r
+                       return f.uid = ++uid;\r
+               },\r
+               cancelFrame : function( uid ){\r
+                       var list = REQUEST_FRAME_LIST,\r
+                               i    = list.length,\r
+                               l    = i,\r
+                               f;\r
+                       for( ; i; ){\r
+                               if( ( f = list[ --i ] ).uid < uid ) break;\r
+                               if( f.uid === uid ){\r
+                                       list.splice( i, 1 );\r
+                                       delete f.uid;\r
+                                       X.Callback._correct( f );\r
+                                       l === 1 && cancelFrame ? cancelFrame( requestID ) : X.Timer.remove( requestID );\r
+                                       break;                                  \r
+                               };\r
+                       };\r
+               }\r
        };\r
 })();
\ No newline at end of file
index 38b1bc4..cde6b45 100644 (file)
@@ -6,46 +6,221 @@ if( window.addEventListener ){
        X.Dom.Event = function( e ){
                this._event        = e;
                this.type          = e.type;
-               this.target        = e.target;
-               this.currentTarget = e.currentTarget;
-               this.relatedTarget = e.relatedTarget;
+               this.target        = e.target; // xnode
+               this.currentTarget = e.currentTarget; // xnode
+               this.relatedTarget = e.relatedTarget; // xnode
                this.eventPhase    = e.eventPhase;
                
                this.clientX       = e.clientX;
                this.clientY       = e.clientY;
-               this.screenX       = e.screenX;
-               this.screenY       = e.screenY;
+               //this.screenX       = e.screenX;
+               //this.screenY       = e.screenY;
+               this.pageX         = e.pageX;
+               this.pageY         = e.pageY;
+               this.offsetX       = e.offsetX || e.layerX;
+               this.offsetY       = e.offsetY || e.layerY;
                
                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.wheelDelta    = e.wheelDelta;
+               
+               if( e.constructor === window.TouchEvent ){
+                       // TouchEvent
+                       this.touches        = e.touches;
+                       this.changedTouches = e.changedTouches;
+                       this.targetTouches  = e.targetTouches;
+                       //this.altKey         = e.altKey;
+                       //this.ctrlKey        = e.ctrlKey;
+                       this.metaKey        = e.metaKey;
+                       //this.shiftKey       = e.shiftKey;
+                       //this.type           = e.type;
+                       //this.target         = e.target;
+               } 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;
+               };
        };
 } else {
        X.Dom.Event = function( e, element ){
+               var btn;
+               
                this._event        = e;
                this.type          = e.type;
-               this.target        = e.srcElement;
-               this.currentTarget = element;
-               this.relatedTarget = e.formElement ? e.formElement : e.toElement;
+               this.target        = e.srcElement; // xnode
+               this.currentTarget = element; // xnode
+               this.relatedTarget = e.formElement ? 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;
+               //this.screenX       = e.screenX;
+               //this.screenY       = e.screenY;
+               this.pageX         = e.clientX + document.body.scrollLeft;
+               this.pageY         = e.clientY + document.body.scrollTop;
+               this.offsetX       = e.offsetX;
+               this.offsetY       = e.offsetY;
                
                this.keyCode       = e.keyCode;
                this.altKey        = e.altKey;
                this.ctrlKey       = e.ctrlKey;
                this.shiftKey      = e.shiftKey;
                
+               // http://www.programming-magic.com/20090127231544/
+               switch( this.type ){
+                       case 'click'    :
+                       case 'dblclick' :
+                               this.which = 1;
+                               break;
+                       case 'contextmenu' :
+                               this.which = 3;
+                               break;
+                       default :
+                               btn = e.button;
+                               this.which =
+                                       btn & 1 ? 1 :
+                                       btn & 4 ? 2 :
+                                       btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2
+               };
+
                this.wheelDelta    = e.wheelDelta;
        };
 };
 
+X.Dom.Event._Helper =
+       document.addEventListener ?
+               (function( elm, type ){
+                       elm.addEventListener( type, this, false );
+               }) :
+       document.attachEvent ?
+               (function( elm, type ){
+                       elm.attachEvent( 'on' + type, ( this.callback = X.Callback.create( this ) ) );
+               }) :
+               (function( elm, type ){
+                       this.callback = elm[ 'on' + type ] = X.Callback.create( this );
+               });
+
+X.Dom.Event._Helper.prototype.removeEvent =
+       document.removeEventListener ?
+               (function( migrate ){
+                       this.type && this.elm.removeEventListener( this.type, this, false );
+                       if( migrate ) return;
+                       delete this.elm;
+                       delete this.type;
+                       delete this.list;
+               }) :
+       document.detachEvent ?
+               (function( migrate ){
+                       this.type && this.elm.detachEvent( 'on' + this.type, this.callback );
+                       X.Callback._correct( this.callback );
+                       if( migrate ) return;
+                       delete this.elm;
+                       delete this.type;
+                       delete this.list;
+                       delete this.callback;
+               }) :
+               (function( migrate ){
+                       this.elm[ 'on' + this.type ] = X.Dom.Event.emptyFunc;
+                       this.elm[ 'on' + this.type ] = '';
+                       X.Callback._correct( this.callback );
+                       if( migrate ) return;
+                       delete this.elm;
+                       delete this.type;
+                       delete this.list;
+                       delete this.callback;
+               });
+
+/*
+ * eventDispatch 中の Event.remove への対処.
+ * 現在 dispatch 中の function より以前の function が抜かれた場合の対策
+ */
+X.Dom.Event._Helper.prototype.handleEvent =
+       document.removeEventListener ?
+               (function( e ){
+                       var list   = this.list,
+                               e      = new X.Dom.Event( e ),
+                               i      = 0,
+                               ret    = 0,
+                               p, f, r;
+                       list.removed = 0;
+                       for( ; i < list.length; ){
+                               list.pointer = i - list.removed;
+                               f = list[ list.pointer ];
+                               r = f( e );
+                               ret |= ( r || 0 );
+                               if( r & X.Callback.UN_LISTEN ){
+                                       list.splice( list.pointer, 1 );
+                                       X.Callback._correct( f );
+                                       if( list.length === 0 ){
+                                               this.removeEvent();
+                                               break;
+                                       };
+                               } else {
+                                       ++i;
+                               };
+                               if( r & X.Callback.STOP_NOW ) break;
+                       };
+                       delete list.pointer;
+                       delete list.removed;
+                       if( ret & X.Callback.STOP_PROPAGATION ){
+                               event.cancelBubble = true;
+                       };
+                       if( ret & X.Callback.PREVENT_DEFAULT ){
+                               return event.returnValue = false;
+                       };
+               }) :
+               (function(){
+                       var list   = this.list,
+                               e      = new X.Dom.Event( event, this.elm ),
+                               i      = 0,
+                               ret    = 0,
+                               p, f, r;
+                       list.removed = 0;
+                       for( ; i < list.length; ){
+                               list.pointer = i - list.removed;
+                               f = list[ list.pointer ];
+                               r = f( e );
+                               ret |= ( r || 0 );
+                               if( r & X.Callback.UN_LISTEN ){
+                                       list.splice( list.pointer, 1 );
+                                       X.Callback._correct( f );
+                                       if( list.length === 0 ){
+                                               this.removeEvent();
+                                               break;
+                                       };
+                               } else {
+                                       ++i;
+                               };
+                               if( r & X.Callback.STOP_NOW ) break;
+                       };
+                       delete list.pointer;
+                       delete list.removed;
+                       if( ret & X.Callback.STOP_PROPAGATION ){
+                               e.stopPropagation();
+                       };
+                       if( ret & X.Callback.PREVENT_DEFAULT ){
+                               e.preventDefault();
+                               return false;
+                       };
+               });
+
 X.Dom.Event._chashe  = [ {}, {}, null, {} ]; // window, document, documentElement, body
 X.Dom.Event._chashe2 = [];
 
@@ -54,7 +229,11 @@ X.Dom.Event.add = function( element, type, arg2, arg3, arg4 /* [ listener || ( c
                hash   = XEvent._getHash( element, true ),
                helper = hash[ type ],
                callback;
-       callback = typeof arg2 === 'function' ? X.Callback.create( element, arg2, arg3 ) : X.Callback.create( arg2, arg3, arg4 );
+       if( typeof arg2 === 'function' ){
+               callback = X.Callback.create( element, arg2, arg3 );
+       } else {
+               callback = X.Callback.create( arg2, arg3, arg4 );
+       };
        if( helper ){
                list = helper.list;
                list.indexOf( callback ) === -1 && ( list[ list.length ] = callback );
@@ -90,8 +269,11 @@ X.Dom.Event._getHash = function( element, create ){
                if( uid = parseFloat( element.getAttribute( '_UID' ) ) ){
                        return this._chashe2[ uid ];
                };
-               element.setAttrivute( '_UID', uid = this._chashe2.length );
-               if( create ) return this._chashe2[ uid ] = {};
+               if( create ){
+                       uid = this._chashe2.length;
+                       element.setAttrivute( '_UID', '' + uid );
+                       return this._chashe2[ uid ] = {};
+               };
                //
        } else {
                if( uid = 2 + element.UID ){
@@ -102,54 +284,62 @@ X.Dom.Event._getHash = function( element, create ){
                if( uid = element._UID ){
                        return this._chashe2[ uid ];
                };
-               element._UID = uid = this._chashe2.length;
-               if( create ) return this._chashe2[ uid ] = {};
+               if( create ){
+                       element._UID = uid = this._chashe2.length;
+                       return this._chashe2[ uid ] = {};
+               };
                //
        };
 };
 
-X.Dom.Event.remove = function( element, type, arg2, arg3 ){
-       var XEvent = X.Dom.Event,
-               hash   = XEvent._getHash( element ),
+X.Dom.Event.remove = function( /* element, type, arg2, arg3, arg4 */ ){
+       var element = arguments[ 0 ],
+               type    = arguments[ 1 ],
+               arg2, arg3, arg4,
+               hash    = X.Dom.Event._getHash( element ),
                helper, callback, i;
        if( !hash ) return;
        
-       // element のみ指定
-       if( type === void 0 ){
-               for( type in hash ){
-                       XEvent.remove( element, type );
-               };
-               XEvent._chashe.splice( XEvent._chashe.indexOf( hash ), 1 );
-               return;
-       };
-       // element, type まで指定
-       if( arg2 === void 0 ){
-               if( !( helper = hash[ type ] ) ) return;
-               list = helper.list;
-               i    = list.length;
-               for( ; i; ){
-                       callback = list[ --i ];
-                       X.Callback._correct( callback );
-               };
-               list.length = 0;
-               helper.removeEvent();
-               delete hash[ type ];
-               return;
-       };
-       if( !( helper = hash[ type ] ) ){
-               list = helper.list;
-               i    = list.indexOf( callback );
-               if( i !== -1 ){
-                       list.splice( i, 1 );
-                       if( list.pointer && i <= list.pointer ){
-                               ++list.removed;
+       switch( arguments.length ){
+               case 0 :
+                       return;
+               case 1 :
+                       for( type in hash ){
+                               X.Dom.Event.remove( element, type );
                        };
-                       X.Callback._correct( callback );
-                       if( list.length === 0 ){
+                       X.Dom.Event._chashe.splice( X.Dom.Event._chashe.indexOf( hash ), 1 );
+                       break;
+               case 2 :
+                       if( helper = hash[ type ] ){
+                               list = helper.list;
+                               i    = list.length;
+                               for( ; i; ){
+                                       callback = list[ --i ];
+                                       X.Callback._correct( callback );
+                               };
+                               list.length = 0;
                                helper.removeEvent();
                                delete hash[ type ];
+              };
+              break;
+           default :
+                       arg2     = arguments[ 2 ];
+                       arg3     = arguments[ 3 ];
+                       arg4     = arguments[ 4 ];
+                       callback = typeof arg2 === 'function' ? X.Callback.create( element, arg2, arg3 ) : X.Callback.create( arg2, arg3, arg4 );
+                       list = helper.list;
+                       i    = list.indexOf( callback );
+                       if( i !== -1 ){
+                               list.splice( i, 1 );
+                               if( list.pointer && i <= list.pointer ){
+                                       ++list.removed;
+                               };
+                               X.Callback._correct( callback );
+                               if( list.length === 0 ){
+                                       helper.removeEvent();
+                                       delete hash[ type ];
+                               };
                        };
-               };
        };
 };
 
@@ -176,104 +366,6 @@ X.Dom.Event.restore = function( element ){
        };
 };
 
-X.Dom.Event._Helper =
-       document.addEventListener ?
-               (function( elm, type ){
-                       elm.addEventListener( type, this, false );
-               }) :
-       document.attachEvent ?
-               (function( elm, type ){
-                       elm.attachEvent( 'on' + type, ( this.callback = X.Callback.create( this ) ) );
-               }) :
-               (function( elm, type ){
-                       this.callback = elm[ 'on' + type ] = X.Callback.create( this );
-               });
-
-/*
- * eventDispatch 中の Event.remove への対処.
- * 現在 dispatch 中の function より以前の function が抜かれた場合の対策
- */
-X.Dom.Event._currentList = void 0;
-
-// eventDispatch 内で remove, add されていたら?
-X.Dom.Event._Helper.prototype.handleEvent = function( e ){
-       var list   = X.Dom.Event._currentList = this.list,
-               e      = window.addEventListener ?
-                               new X.Dom.Event( e ) :
-                               new X.Dom.Event( event, this.elm ),
-               me     = X.Dom.Event,
-               i      = 0,
-               ret    = 0,
-               p, f, r;
-       list.removed = 0;
-       for( ; i < list.length; ){
-               me._currentList = list;
-               list.pointer    = p = i - list.removed;
-               f = list[ p ];
-               r = f( e ) || 0;
-               me._currentList = null;
-               ret |= r;
-               if( r & X.Callback.UN_LISTEN ){
-                       list.splice( p, 1 );
-                       X.Callback._correct( f );
-                       if( list.length === 0 ){
-                               this.removeEvent();
-                               break;
-                       };
-               } else {
-                       ++i;
-               };
-               if( r & X.Callback.CANCEL_NOW ) break;
-       };
-       delete me._currentList;
-       if( window.addEventListener ){
-               if( ret & X.Callback.STOP_PROPAGATION ){
-                       e.stopPropagation();
-               };
-               if( ret & X.Callback.PREVENT_DEFAULT ){
-                       e.preventDefault();
-                       return false;
-               };                              
-       } else {
-               if( ret & X.Callback.STOP_PROPAGATION ){
-                       event.cancelBubble = true;
-               };
-               if( ret & X.Callback.PREVENT_DEFAULT ){
-                       return event.returnValue = false;
-               };                              
-       };
-};
-
-X.Dom.Event._Helper.prototype.removeEvent =
-       document.removeEventListener ?
-               (function( migrate ){
-                       this.type && this.elm.removeEventListener( this.type, this, false );
-                       if( migrate ) return;
-                       delete this.elm;
-                       delete this.type;
-                       delete this.list;
-               }) :
-       document.detachEvent ?
-               (function( migrate ){
-                       this.type && this.elm.detachEvent( 'on' + this.type, this.callback );
-                       X.Callback._correct( this.callback );
-                       if( migrate ) return;
-                       delete this.elm;
-                       delete this.type;
-                       delete this.list;
-                       delete this.callback;
-               }) :
-               (function( migrate ){
-                       this.elm[ 'on' + this.type ] = X.Dom.Event.emptyFunc;
-                       this.elm[ 'on' + this.type ] = '';
-                       X.Callback._correct( this.callback );
-                       if( migrate ) return;
-                       delete this.elm;
-                       delete this.type;
-                       delete this.list;
-                       delete this.callback;
-               });
-
 if( !document.removeEventListener && !document.detachEvent ){
        X.Dom.Event.emptyFunc = new Function();
 };
\ No newline at end of file
index 855583d..469ab81 100644 (file)
@@ -16,61 +16,143 @@ X.View = {
                // FOCUS\r
                // DISABLED\r
                // ENABLED\r
-       \r
+               // BASE_FONT_SIZE_CHANGE\r
+               \r
        /* -- Pointing Device Event -- */\r
-               _START_POINTER    : 10,\r
+               _START_POINTER    : 9.5,\r
                \r
                CONTEXT_MENU      : 10, // rightclick or longtouch or menukey or ctrl + click\r
                \r
        /* -- ここよりあとははノード上をバブルアップ -- */\r
-               _NO_BUBLEUP       : 10.5,               \r
-               //\r
-               POINTER_START     : 11,\r
-               POINTER_END       : 12,\r
-               POINTER_MOVE      : 13,\r
+               _START_BUBLEUP    : 10.5,               \r
+\r
+               // raw pointing device event\r
+               _POINTER_DOWN     : 11,\r
+               _POINTER_UP       : 12,\r
+               _POINTER_MOVE     : 13,\r
+               _POINTER_CANCEL   : 14,\r
+               _TOUCH_START      : 15,\r
+               _TOUCH_END        : 16,\r
+               _TOUCH_MOVE       : 17,\r
+               _TOUCH_CANCEL     : 18,\r
+               _MOUSE_DOWN       : 19,\r
+               _MOUSE_UP         : 20,\r
+               _MOUSE_MOVE       : 21,\r
+               _MOUSE_CANCEL     : 22,\r
+               \r
+               SELECT            : 23, // click or tap or enterkey\r
+               FILE_DRAG         : 24,\r
+       \r
+       /* -- ここより後は X.UI 用のイベント -- */\r
+               _START_XUI_EVENT  : 24.5,\r
+       \r
+       /* -- Mouse only -- */\r
+               MOUSE_MOVE        : 25,\r
+               MOUSE_STAY        : 26,\r
+               MOUSE_STAY_END    : 27,\r
+               MOUSE_WHEEL       : 28,\r
+       \r
+       /* -- Gesuture Event -- */\r
+               HOLD              : 33,\r
+               HOLD_END          : 34,\r
+               TAP               : 35,\r
+               DOUBLE_TAP        : 36,\r
+               DRAG              : 37,\r
+               DRAG_START        : 38,\r
+               DRAG_END          : 39,\r
+               DRAG_UP           : 40,\r
+               DRAG_RIGHT        : 41,\r
+               DRAG_LEFT         : 42,\r
+               DRAG_DOWN         : 43,\r
+               SWIP              : 44,\r
+               SWIP_UP           : 45,\r
+               SWIP_RIGHT        : 46,\r
+               SWIP_LEFT         : 47,         \r
+               SWIP_DOWN         : 48,\r
+               TRANSFORM         : 49,\r
+               TRANSFORM_START   : 50,\r
+               TRANSFORM_END     : 51,\r
+               PINCH             : 52,\r
+               PINCH_IN          : 53,\r
+               PINCH_OUT         : 54,\r
+               ROTATE            : 55,\r
                \r
-               SELECT            : 14, // click or tap or enterkey\r
-               FILE_DRAG         : 15,\r
+               _END_XUI_EVENT    : 55.5,\r
                \r
+               _END_POINTER      : 55.5,\r
        /* -- Pointing Device Event -- */\r
-               _END_POINTER      : 15,\r
                \r
-               KEY_DOWN          : 16,\r
-               KEY_UP            : 17,\r
+               KEY_DOWN          : 56,\r
+               KEY_UP            : 57,\r
+               KEY_HOLD          : 58,\r
                \r
-               SCROLL            : 18,\r
+               SCROLL              : 59,\r
+               SCROLL_START        : 60,\r
+               SCROLL_END          : 61,\r
+               SCROLL_BEFORE_START : 62, // cancelable\r
+               SCROLL_BEFORE_END   : 63,\r
        \r
-               CHANGE            : 19,\r
-               SUBMIT            : 20,\r
+               CHANGE            : 64,\r
+               SUBMIT            : 65,\r
                \r
                IdToName : {},\r
                NameToID : {}\r
        }\r
 };\r
+/*\r
+X.View.Event.IdToName[ X.View.Event.MOUSE_MOVE       ] = 'mousemove';\r
+X.View.Event.IdToName[ X.View.Event.MOUSE_STAY       ] = 'stay';\r
+X.View.Event.IdToName[ X.View.Event.MOUSE_STAY_END   ] = 'stayend';\r
+X.View.Event.IdToName[ X.View.Event.MOUSE_WHEEL      ] = document.onmousewheel !== void 0 ? 'mousewheel' : 'DOMMouseScroll';\r
+X.View.Event.IdToName[ X.View.Event.HOLD     ] = 'hold';\r
+X.View.Event.IdToName[ X.View.Event.HOLD_END ] = 'holdend';\r
+X.View.Event.IdToName[ X.View.Event.TAP      ] = 'tap';\r
+X.View.Event.IdToName[ X.View.Event.DOUBLE_TAP     ] = 'dobuletap';\r
+X.View.Event.IdToName[ X.View.Event.DRAG             ] = 'drag';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_START       ] = 'dragstart';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_END         ] = 'dragend';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_END         ] = 'dragup';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_END         ] = 'dragleft';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_END         ] = 'dragright';\r
+X.View.Event.IdToName[ X.View.Event.DRAG_END         ] = 'dragdown';\r
+X.View.Event.IdToName[ X.View.Event.SWIP             ] = 'swip';\r
+X.View.Event.IdToName[ X.View.Event.SWIP_LEFT        ] = 'swipleft';\r
+X.View.Event.IdToName[ X.View.Event.SWIP_RIGHT       ] = 'swipright';\r
+X.View.Event.IdToName[ X.View.Event.SWIP_TOP         ] = 'swiptop';\r
+X.View.Event.IdToName[ X.View.Event.SWIP_BOTTOM      ] = 'swipbottom';\r
+X.View.Event.IdToName[ X.View.Event.TRANSFORM        ] = 'transform';\r
+X.View.Event.IdToName[ X.View.Event.TRANSFORM_START  ] = 'transformstart';\r
+X.View.Event.IdToName[ X.View.Event.TRANSFORM_END    ] = 'transformend';\r
+X.View.Event.IdToName[ X.View.Event.PINCH            ] = 'pinch';\r
+X.View.Event.IdToName[ X.View.Event.PINCH_IN         ] = 'pinchin';\r
+X.View.Event.IdToName[ X.View.Event.PINCH_OUT        ] = 'pinchout';\r
+X.View.Event.IdToName[ X.View.Event.ROTATE           ] = 'rotate';\r
+*/\r
 \r
-if( window.navigator.msPointerEnabled ){\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_START ] = 'MSPointerDown';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_END   ] = 'MSPointerUp';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_MOVE  ] = 'MSPointerMove';\r
-       X.View.Event.NameToID[ 'MSPointerDown' ] = X.View.Event.POINTER_START;\r
-       X.View.Event.NameToID[ 'MSPointerUp'   ] = X.View.Event.POINTER_END;\r
-       X.View.Event.NameToID[ 'MSPointerMove' ] = X.View.Event.POINTER_MOVE;\r
-} else\r
-if( window.ontouchstart || window.DocumentTouch /* && document instanceof DocumentTouch */ ){\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_START ] = 'touchstart';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_END   ] = 'touchend';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_MOVE  ] = 'touchmove';\r
-       X.View.Event.NameToID[ 'touchstart' ] = X.View.Event.POINTER_START;\r
-       X.View.Event.NameToID[ 'touchend'   ] = X.View.Event.POINTER_END;\r
-       X.View.Event.NameToID[ 'touchmove'  ] = X.View.Event.POINTER_MOVE;\r
-} else {\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_START ] = 'mousedown';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_END   ] = 'mouseup';\r
-       X.View.Event.IdToName[ X.View.Event.POINTER_MOVE  ] = 'mousemove';\r
-       X.View.Event.NameToID[ 'mousedown' ] = X.View.Event.POINTER_START;\r
-       X.View.Event.NameToID[ 'mouseup'   ] = X.View.Event.POINTER_END;\r
-       X.View.Event.NameToID[ 'mousemove' ] = X.View.Event.POINTER_MOVE;\r
-};\r
+if( navigator.msPointerEnabled || navigator.pointerEnabled ){\r
+       X.View.Event.IdToName[ X.View.Event._POINTER_DOWN   ] = navigator.msPointerEnabled ? 'MSPointerDown'   : 'pointerdown';\r
+       X.View.Event.IdToName[ X.View.Event._POINTER_UP     ] = navigator.msPointerEnabled ? 'MSPointerUp'     : 'pointerup';\r
+       X.View.Event.IdToName[ X.View.Event._POINTER_MOVE   ] = navigator.msPointerEnabled ? 'MSPointerMove'   : 'pointermove';\r
+       X.View.Event.IdToName[ X.View.Event._POINTER_CANCEL ] = navigator.msPointerEnabled ? 'MSPointerCancel' : 'pointercancel';\r
+};// else\r
+//if( window.ontouchstart !== void 0 /* || window.DocumentTouch && document instanceof DocumentTouch */ ){\r
+       X.View.Event.IdToName[ X.View.Event._TOUCH_START  ] = 'touchstart';\r
+       X.View.Event.IdToName[ X.View.Event._TOUCH_END    ] = 'touchend';\r
+       X.View.Event.IdToName[ X.View.Event._TOUCH_MOVE   ] = 'touchmove';\r
+       X.View.Event.IdToName[ X.View.Event._TOUCH_CANCEL ] = 'touchcancel';\r
+//} else {\r
+       // ToDo: cancel \r
+       X.View.Event.IdToName[ X.View.Event._MOUSE_DOWN   ] = 'mousedown';\r
+       X.View.Event.IdToName[ X.View.Event._MOUSE_UP     ] = 'mouseup';\r
+       X.View.Event.IdToName[ X.View.Event._MOUSE_MOVE   ] = 'mousemove';\r
+       X.View.Event.IdToName[ X.View.Event._MOUSE_CANCEL ] = 'mouseleave'; // ??\r
+//};\r
+\r
+( function( IdToName, NameToID ){\r
+       for( var id in IdToName ){\r
+               NameToID[ IdToName[ id ] ] = id;\r
+       };\r
+})( X.View.Event.IdToName, X.View.Event.NameToID );\r
 \r
 X.View = (function( window, document ){\r
        var view,\r
@@ -135,7 +217,7 @@ X.View = (function( window, document ){
                                delete X.View._init;\r
                                X.View.ready = true;\r
                                \r
-                               if( X.UA.IE ) X.View._view = ( document.compatMode !== "CSS1Compat" ? ( b || document.body ) : document.documentElement );\r
+                               /* if( X.UA.IE ) */ X.View._view = ( document.compatMode !== "CSS1Compat" ? document.body : document.documentElement );\r
                                size = X.View.getSize();\r
                                \r
                                X.View.dispatch( { type : X.View.Event.SYS_READY, w : size[ 0 ], h : size[ 1 ] } );\r
@@ -157,9 +239,22 @@ X.View = (function( window, document ){
                        },\r
                        Event : X.View.Event,\r
                        // _view : null, for ie\r
-                       getSize : X.UA.IE ?\r
-                               new Function( 'return [ X.View._view.clientWidth, X.View._view.clientHeight ]' ) :\r
-                               new Function( 'return [ window.innerWidth, window.innerHeight ]' )\r
+                       getSize :\r
+                               X.UA.IE ?\r
+                                       new Function( 'return [ X.View._view.clientWidth, X.View._view.clientHeight ]' ) :\r
+                                       new Function( 'return [ window.innerWidth, window.innerHeight ]' ),\r
+                       getScrollPosition :\r
+                               window.pageXOffset ?\r
+                                       new Function( 'return [window.pageXOffset,window.pageYOffset]' ) :\r
+                               window.scrollLeft  ?\r
+                                       new Function( 'return [window.scrollLeft,window.scrollTop]') :\r
+                                       new Function( 'return [X.View._view.scrollLeft,X.View._view.scrollTop]' ),\r
+                       getDocumentSize : function(){\r
+                               return [\r
+                                       X.View._view.scrollWidth  || X.View._view.offsetWidth,\r
+                                       X.View._view.scrollHeight || X.View._view.offsetHeight\r
+                               ];\r
+                       }\r
                }\r
        );\r
                \r
@@ -174,7 +269,7 @@ X.View = (function( window, document ){
 if( document.addEventListener ){\r
        X.Dom.Event.add( document, 'DOMContentLoaded', X.View._init );\r
 } else\r
-if( 5 <= X.UA.IE ){\r
+if( 5 <= X.UA.IE && X.inHead ){\r
        // if this script in Head\r
        document.write( "<script id=__ie_onload defer src=javascript:void(0)><\/script>" );\r
        X.View._script = document.getElementById( "__ie_onload" );\r
@@ -195,5 +290,4 @@ X.Dom.Event.add( window, 'load', X.View._init );
 //\r
 X.View.listen( X.View.Event.SYS_READY, function(e){ console.log( 'X.View DomReady ' + X.View.ready ) } );\r
 \r
-X.View.listen( X.View.Event.VIEW_RESIZED, function(e){ console.log( 'X.View VIEW_RESIZED ' + e.w + 'x' + e.h ) } );\r
-\r
+X.View.listen( X.View.Event.VIEW_RESIZED, function(e){ console.log( 'X.View VIEW_RESIZED ' + e.w + 'x' + e.h ) } );
\ No newline at end of file
diff --git a/0.6.x/js/ui/05_XUI_Gesture.js b/0.6.x/js/ui/05_XUI_Gesture.js
new file mode 100644 (file)
index 0000000..2f93f52
--- /dev/null
@@ -0,0 +1,1094 @@
+/* original:\r
+ *  Hammer.JS - v1.0.5 - 2013-04-07\r
+ *  http://eightmedia.github.com/hammer.js\r
+ *  Jorik Tangelder <j.tangelder@gmail.com>, MIT license\r
+ **/\r
+\r
+X.UI = X.UI || {};\r
+\r
+( function( Math, window, document, undefined ){\r
+       \r
+       var ELEENT_LIST = [],\r
+               HAMMER_LIST = [],\r
+               POINTERS    = [],\r
+               ABS = new Function( 'v', 'return v<0?-v:v' );\r
+       \r
+       X.UI.Gesture = Hammer;\r
+       \r
+       function Hammer( uinodeRoot, uinode, type ){\r
+               this.uinode  = uinode;\r
+               this.enabled = true;\r
+               \r
+               Hammer.startup && Hammer.startup( uinodeRoot );\r
+\r
+               this.options = Hammer.defaults;\r
+\r
+               // start detection on touchstart\r
+               Utils.addEvents( uinode, Hammer.EVENT_TYPES_START, this );\r
+               \r
+               this.listen( type );\r
+       };\r
+       \r
+       Hammer.defaults = {};\r
+       \r
+       Hammer.prototype.handleEvent = function( e ){\r
+               //var sourceEventType = e.type.toLowerCase();\r
+\r
+               var type       = IdToGestureID[ e.type ],\r
+                       gestures   = Detection.gestures,\r
+                       numTouches = 0,// count the total touches on the screen\r
+                       pointerType, i, l, touches, ret, active, gesture, startEv,\r
+                       deltaTime, deltaX, deltaY, velocity;\r
+               console.log( '1 : ' + type + ' .............. ' + e.type )\r
+               if( !type ) return;\r
+               \r
+               if( e.pointerType ){\r
+                       type |= POINTER;\r
+                       switch( e.pointerType ){\r
+                               case 'touch' :\r
+                               case e.MSPOINTER_TYPE_TOUCH :\r
+                                       type |= TOUCH; break;\r
+                               case 'pen' :\r
+                               case e.MSPOINTER_TYPE_PEN :\r
+                                       type |= PEN; break;\r
+                               case 'mouse' :\r
+                               case e.MSPOINTER_TYPE_MOUSE :\r
+                                       type |= MOUSE; break;\r
+                               default :\r
+                                       return;\r
+                       };\r
+               } else\r
+               if( e.touches ){\r
+                       type |= TOUCH;\r
+               } else {\r
+                       type |= MOUSE;\r
+               };\r
+               \r
+               // onmouseup, but when touchend has been fired we do nothing.\r
+               // this is for touchdevices which also fire a mouseup on touchend\r
+               if( type & MOUSE && touch_triggered ){\r
+                       return X.Callback.STOP_NOW | X.Callback.STOP_PROPAGATION | X.Callback.PREVENT_DEFAULT;\r
+               }\r
+               // mousebutton must be down or a touch event\r
+               else if (\r
+                       type & TOUCH || //sourceEventType.match(/touch/) || // touch events are always on screen\r
+                       ( type & POINTER && type & START ) || //sourceEventType.match(/pointerdown/) || // pointerevents touch\r
+                       ( type & MOUSE   && e.which === 1 ) //(sourceEventType.match(/mouse/) && e.which === 1) // mouse is pressed\r
+               ){\r
+                       enable_detect = true;\r
+               };\r
+\r
+               // we are in a touch event, set the touch triggered bool to true,\r
+               // this for the conflicts that may occur on ios and android\r
+               type & ( TOUCH | POINTER ) && ( touch_triggered = true );\r
+               //if (sourceEventType.match(/touch|pointer/)) { touch_triggered = true;}\r
+\r
+               // when touch has been triggered in this detection session\r
+               // and we are now handling a mouse event, we stop that to prevent conflicts\r
+               if( enable_detect ){\r
+                       // update pointerevent\r
+                       if( Hammer.HAS_POINTEREVENTS ){ //eventType !== Hammer.EVENT_END ){\r
+                               POINTERS[ e.identifier = e.pointerId ] = type & END ? null : e;\r
+                               touches = [];\r
+                               // we can use forEach since pointerEvents only is in IE10\r
+                               for( i = 0, l = POINTERS.length; i < l; ++i ){\r
+                                       POINTERS[ i ] && ( touches[ touches.length ] = POINTERS[ i ] );\r
+                               };\r
+                               numTouches = touches.length;\r
+                       }\r
+                       // touch\r
+                       else if ( type & TOUCH ){ //sourceEventType.match(/touch/)) {\r
+                               touches    = Hammer.DO_TOUCHES_FIX && type & END ? [] : e.touches;\r
+                               numTouches = touches.length;\r
+                       }\r
+                       // mouse\r
+                       else if( !touch_triggered ){\r
+                               numTouches = ( type & END ) ? 0 : 1;\r
+                               touches    = numTouches === 0 ? [] : [{\r
+                                       identifier : 1,\r
+                                       pageX      : e.pageX,\r
+                                       pageY      : e.pageY,\r
+                                       target     : e.target\r
+                               }];\r
+                       };\r
+\r
+                       // if we are in a end event, but when we remove one touch and\r
+                       // we still have enough, set eventType to move\r
+                       if( 0 < numTouches && type & END ){ // eventType === Hammer.EVENT_END ){\r
+                               type = type & POINTER_TYPE_MASK | MOVE;\r
+                               //eventType = Hammer.EVENT_MOVE;\r
+                       } else if( !numTouches ){\r
+                       // no touches, force the end event\r
+                               type = type & POINTER_TYPE_MASK | END;\r
+                               //eventType = Hammer.EVENT_END;\r
+                       };\r
+\r
+                       // because touchend has no touches, and we often want to use these in our gestures,\r
+                       // we send the last move event as our eventData in touchend\r
+                       ( !numTouches && last_move_event !== null ) ?\r
+                               ( e = last_move_event ):\r
+                               ( last_move_event = e ); // store the last move event\r
+\r
+                       e = {\r
+                               center      : Utils.getCenter( touches ),\r
+                               timeStamp   : Date.now ? Date.now() : +new Date,\r
+                               target      : e.target,\r
+                               touches     : touches,\r
+                               eventType   : type & EVENT_TYPE_MASK,\r
+                               pointerType : type & POINTER_TYPE_MASK\r
+                       };\r
+\r
+                       console.log( '2 : ' + type + ' .............. ' + last_move_event.type )\r
+\r
+                       if( type & START ){\r
+                               console.log( '2a : ' + type + ' .............. ' + last_move_event.type )\r
+                               if( !this.enabled ) return;\r
+                               // already busy with a Hammer.gesture detection on an element\r
+                               console.log( '2b : ' + type + ' .............. ' + last_move_event.type )\r
+                               if( Detection.current ) return;\r
+                               Detection.current = {\r
+                                       hammer     : this, // reference to HammerInstance we're working for\r
+                                       startEvent : Utils.extend( {}, e ), // start eventData for distances, timing etc\r
+                                       lastEvent  : false, // last eventData\r
+                                       name       : '' // current gesture we're in/detected, can be 'tap', 'hold' etc\r
+                               };\r
+                               Detection.stopped = false;\r
+                               hammer = this;\r
+                               active = hammer.activeGesture;\r
+                       } else\r
+                       if( !Detection.current || Detection.stopped ){\r
+                               return;\r
+                       } else {\r
+                               hammer = Detection.current.hammer;\r
+                               active = hammer.activeGesture;\r
+                       };\r
+                       \r
+                       console.log( '3 : ' + type + ' .............. ' + last_move_event.type )\r
+                       \r
+                       // ----------------------------------------------------------------------------------------------------------------\r
+                       // ret = Detection.detect( e );\r
+\r
+                       // ----------------------------------------------------------------------------------------------------------------\r
+                       // extend event data with calculations about scale, distance etc\r
+                       // e = Detection.extendEventData( e );\r
+                       startEv = Detection.current.startEvent;\r
+                       center  = e.center;\r
+\r
+                       // if the touches change, set the new touches over the startEvent touches\r
+                       // this because touchevents don't have all the touches on touchstart, or the\r
+                       // user must place his fingers at the EXACT same time on the screen, which is not realistic\r
+                       // but, sometimes it happens that both fingers are touching at the EXACT same time\r
+                       if( startEv && ( numTouches !== startEv.touches.length || touches === startEv.touches ) ){\r
+                               // extend 1 level deep to get the touchlist with the touch objects\r
+                               startEv.touches.length = i = 0;\r
+                               for( ; i < numTouches; ++i ){\r
+                                       startEv.touches[ startEv.touches.length ] = Utils.extend( {}, touches[ i ] );\r
+                               };\r
+                       };\r
+\r
+                       deltaTime = e.timeStamp  - startEv.timeStamp;\r
+                       deltaX    = center.pageX - startEv.center.pageX;\r
+                       deltaY    = center.pageY - startEv.center.pageY;\r
+                       velocity  = Utils.getVelocity( deltaTime, deltaX, deltaY );\r
+\r
+                       Utils.extend( e, {\r
+                               deltaTime  : deltaTime,\r
+\r
+                               deltaX     : deltaX,\r
+                               deltaY     : deltaY,\r
+\r
+                               velocityX  : velocity.x,\r
+                               velocityY  : velocity.y,\r
+\r
+                               distance   : Utils.getDistance( startEv.center, center ),\r
+                               angle      : Utils.getAngle( startEv.center, center ),\r
+                               direction  : Utils.getDirection( startEv.center, center ),\r
+\r
+                               scale      : Utils.getScale( startEv.touches, touches ),\r
+                               rotation   : Utils.getRotation( startEv.touches, touches ),\r
+\r
+                               startEvent : startEv\r
+                       });\r
+\r
+\r
+                       // call Hammer.gesture handlers\r
+                       for( i = 0, l = gestures.length; i < l; ++i ){\r
+                               gesture = gestures[ i ];\r
+                               if( Detection.stopped ) break;\r
+                               if( active[ gesture.name ] ) console.log( gesture.name );\r
+                               // only when the instance options have enabled this gesture\r
+                               active[ gesture.name ] &&\r
+                                       // if a handler returns false, we stop with the detection\r
+                                       ( ret |= ( gesture.handler.call( gesture, e, hammer ) || X.Callback.NONE ) );\r
+                       };\r
+\r
+                       // store as previous event event\r
+                       Detection.current.lastEvent = e;\r
+\r
+                       // endevent, but not the last touch, so dont stop\r
+                       type & END && numTouches === 0 && Detection.stopDetect();\r
+                       \r
+                       // ----------------------------------------------------------------------------------------------------------------\r
+                       // trigger the handler\r
+                       //handler.call( context, HamEvent.collectEventData( element, eventType, e ) );\r
+\r
+                       // remove pointerevent from list\r
+                       if( Hammer.HAS_POINTEREVENTS && type & END ){ // eventType === Hammer.EVENT_END ){\r
+                               numTouches = 0;\r
+                       };\r
+               };\r
+\r
+               //debug(sourceEventType +" "+ eventType);\r
+\r
+               // on the end we reset everything\r
+               if( numTouches === 0 ){\r
+                       last_move_event = null;\r
+                       enable_detect   = false;\r
+                       touch_triggered = false;\r
+                       POINTERS.length = 0;\r
+               };\r
+               \r
+               return ret;\r
+       };\r
+       \r
+       Hammer.startup = function( uinodeRoot ){\r
+               // find what eventtypes we add listeners to\r
+               /**\r
+                * we have different events for each device/browser\r
+                * determine what we need and set them in the Hammer.EVENT_TYPES constant\r
+                */\r
+               // determine the eventtype we want to set\r
+               // for non pointer events browsers and mixed browsers,\r
+               // like chrome on windows8 touch laptop         \r
+               var types, name;\r
+\r
+               // Register all gestures inside Gestures\r
+               for( name in Gestures ){\r
+                       Gestures.hasOwnProperty( name ) && Detection.register( Gestures[ name ] );\r
+               };\r
+\r
+               if( navigator.pointerEnabled || navigator.msPointerEnabled ){\r
+                       Hammer.EVENT_TYPES_START = [ X.View.Event._POINTER_DOWN ];\r
+                       types = [ X.View.Event._POINTER_MOVE, X.View.Event._POINTER_UP, X.View.Event._POINTER_CANCEL ];\r
+               } else\r
+               if( window.ontouchstart !== void 0 ){\r
+                       Hammer.EVENT_TYPES_START = [ X.View.Event._TOUCH_START ];\r
+                       types = [ X.View.Event._TOUCH_MOVE, X.View.Event._MOUSE_MOVE, X.View.Event._TOUCH_END, X.View.Event._TOUCH_CANCEL ];\r
+               } else {\r
+                       Hammer.EVENT_TYPES_START = [ X.View.Event._MOUSE_DOWN ];\r
+                       types = [ X.View.Event._MOUSE_MOVE, X.View.Event._MOUSE_UP, X.View.Event._MOUSE_CANCEL ];\r
+               };\r
+\r
+               // Add touch events on the document\r
+               Utils.addEvents( uinodeRoot, types, Hammer.prototype.handleEvent );\r
+\r
+               // Hammer is ready...!\r
+               delete Hammer.startup;\r
+       };\r
+       \r
+       Hammer.prototype.trigger = function( type, gesture ){\r
+               if( !this.types[ type ] ) return;\r
+               var e = Utils.extend( {}, gesture );\r
+               e.type = type;\r
+               console.log( 'trigger : ' + type )\r
+               return this.uinode.dispatch( e );\r
+       };\r
+       \r
+       Hammer.prototype.listen = function( type ){\r
+               var gestures = Detection.gestures,\r
+                       i = gestures.length, g;\r
+               for( ; i; ){\r
+                       g = gestures[ --i ];\r
+                       if( g.startID <= type && type <= g.endID ){\r
+                               if( !this.activeGesture ) this.activeGesture = {};\r
+                               if( !this.types ) this.types = {};\r
+                               this.activeGesture[ g.name ] = this.types[ type ] = 1;\r
+                               return;\r
+                       };\r
+               };\r
+       };\r
+       \r
+       Hammer.prototype.unlisten = function( type ){\r
+               var gestures = Detection.gestures,\r
+                       i = gestures.length, g;\r
+               if( !this.activeGesture ) return;\r
+               for( ; i; ){\r
+                       g = gestures[ --i ];\r
+                       if( g.startID <= type && type <= g.endID ){\r
+                               if( this.activeGesture[ g.name ] ){\r
+                                       if( this.types[ type ] ) delete this.types[ type ];\r
+                                       for( i = g.startID; i <= g.endID; ++i ){\r
+                                               if( this.types[ i ] ) return;\r
+                                       };\r
+                                       delete this.activeGesture[ g.name ];\r
+                               };\r
+                               return;\r
+                       };\r
+               };\r
+       };\r
+       \r
+       /*\r
+        *  "Android version < 2.2" return ev.touches.length === 1 when touchend, others return ev.touches.length === 0\r
+        */\r
+       Hammer.DO_TOUCHES_FIX = Hammer.HAS_TOUCHEVENTS && ( function( ua, i ){\r
+                               if( ( i = ua.indexOf('android') ) === -1 ) return false;\r
+                               return ( parseFloat( ua.substr( i + 8 ) ) || 0 ) < 2.2;\r
+                       })( navigator.userAgent.toLowerCase() );\r
+       \r
+       // detect touchevents\r
+       Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;\r
+\r
+       // eventtypes per touchevent (start, move, end)\r
+       // are filled by HamEvent.determineEventTypes on setup\r
+       Hammer.EVENT_TYPES_START = null;\r
+\r
+       // direction defines\r
+       Hammer.DIRECTION_DOWN  = 'down';\r
+       Hammer.DIRECTION_LEFT  = 'left';\r
+       Hammer.DIRECTION_UP    = 'up';\r
+       Hammer.DIRECTION_RIGHT = 'right';\r
+\r
+       // plugins namespace\r
+       Hammer.plugins = {};\r
+\r
+       var POINTER     = 1,\r
+               TOUCH       = 2,\r
+               PEN         = 8, //4,\r
+               MOUSE       = 8,\r
+               START       = 16,\r
+               MOVE        = 32,\r
+               END         = 64,\r
+               CANCEL      = 128,\r
+               EVENT_TYPE_MASK   = START | MOVE | END,\r
+               POINTER_TYPE_MASK = POINTER | TOUCH | MOUSE | PEN,\r
+               IdToGestureID = {};\r
+       IdToGestureID[ X.View.Event._POINTER_DOWN   ] = START;\r
+       IdToGestureID[ X.View.Event._POINTER_MOVE   ] = MOVE;\r
+       IdToGestureID[ X.View.Event._POINTER_UP     ] = END;\r
+       IdToGestureID[ X.View.Event._POINTER_CANCEL ] = END;\r
+       \r
+       IdToGestureID[ X.View.Event._TOUCH_START  ] = START;\r
+       IdToGestureID[ X.View.Event._TOUCH_MOVE   ] = MOVE;\r
+       IdToGestureID[ X.View.Event._TOUCH_END    ] = END;\r
+       IdToGestureID[ X.View.Event._TOUCH_CANCEL ] = END;\r
+       \r
+       IdToGestureID[ X.View.Event._MOUSE_DOWN   ] = START;\r
+       IdToGestureID[ X.View.Event._MOUSE_MOVE   ] = MOVE;\r
+       IdToGestureID[ X.View.Event._MOUSE_UP     ] = END;\r
+       IdToGestureID[ X.View.Event._MOUSE_CANCEL ] = END;\r
+       \r
+       Utils = {\r
+               \r
+               /**\r
+                * touch events with mouse fallback\r
+                * @param   {HTMLElement}   element\r
+                * @param   {String}        eventType        like Hammer.EVENT_MOVE\r
+                * @param   {Function}      handler\r
+                */\r
+               addEvents : function( uinode, types, context ){\r
+                       for( var i = 0; i < types.length; ++i ){\r
+                               uinode.listen( types[ i ], context );\r
+                       };\r
+               },\r
+               \r
+               /**\r
+                * extend method,\r
+                * also used for cloning when dest is an empty object\r
+                * @param   {Object}    dest\r
+                * @param   {Object}    src\r
+                * @parm        {Boolean}       merge           do a merge\r
+                * @returns {Object}    dest\r
+                */\r
+               extend : function extend( dest, src, merge ){\r
+                       for( var key in src ){\r
+                               if( dest[ key ] !== undefined && merge ) continue;\r
+                               dest[ key ] = src[ key ];\r
+                       };\r
+                       return dest;\r
+               },\r
+\r
+               /**\r
+                * find if a node is in the given parent\r
+                * used for event delegation tricks\r
+                * @param   {HTMLElement}   node\r
+                * @param   {HTMLElement}   parent\r
+                * @returns {boolean}       has_parent\r
+                */\r
+               hasParent : function( node, parent ){\r
+                       while( node && node.tagName ){ /* tagName for ie */\r
+                               if( node === parent ) return true;\r
+                               node = node.parentNode;\r
+                       };\r
+                       return false;\r
+               },\r
+\r
+               /**\r
+                * get the center of all the touches\r
+                * @param   {Array}     touches\r
+                * @returns {Object}    center\r
+                */\r
+               getCenter : function getCenter(touches) {\r
+                       var i = 0,\r
+                               l = touches.length,\r
+                               valuesX, valuesY;\r
+                       switch( l ){\r
+                               case 0 :\r
+                                       return {};\r
+                               case 1 :\r
+                                       return {\r
+                                               pageX : touches[ 0 ].pageX,\r
+                                               pageY : touches[ 0 ].pageY\r
+                                       };\r
+                               case 2 :\r
+                                       return {\r
+                                               pageX : ( touches[ 0 ].pageX + touches[ 1 ].pageX ) / 2,\r
+                                               pageY : ( touches[ 0 ].pageY + touches[ 1 ].pageY ) / 2\r
+                                       };\r
+                       };\r
+                       valuesX = [];\r
+                       valuesY = [];\r
+                       for( ; i < l; ++i ){\r
+                               valuesX[ valuesX.length ] = touches[ i ].pageX;\r
+                               valuesY[ valuesY.length ] = touches[ i ].pageY;\r
+                       };\r
+                       return {\r
+                               pageX : ( ( Math.min.apply( null, valuesX ) + Math.max.apply( null, valuesX ) ) / 2 ),\r
+                               pageY : ( ( Math.min.apply( null, valuesY ) + Math.max.apply( null, valuesY ) ) / 2 )\r
+                       };\r
+               },\r
+\r
+               /**\r
+                * calculate the velocity between two points\r
+                * @param   {Number}    deltaTime\r
+                * @param   {Number}    deltaX\r
+                * @param   {Number}    deltaY\r
+                * @returns {Object}    velocity\r
+                */\r
+               getVelocity : function getVelocity( deltaTime, deltaX, deltaY ) {\r
+                       return {\r
+                               x : ABS( deltaX / deltaTime ) || 0,\r
+                               y : ABS( deltaY / deltaTime ) || 0\r
+                       };\r
+               },\r
+\r
+               /**\r
+                * calculate the angle between two coordinates\r
+                * @param   {Touch}     touch1\r
+                * @param   {Touch}     touch2\r
+                * @returns {Number}    angle\r
+                */\r
+               getAngle : function getAngle(touch1, touch2) {\r
+                       var y = touch2.pageY - touch1.pageY,\r
+                               x = touch2.pageX - touch1.pageX;\r
+                       return Math.atan2( y, x ) * 180 / Math.PI;\r
+               },\r
+\r
+               /**\r
+                * angle to direction define\r
+                * @param   {Touch}     touch1\r
+                * @param   {Touch}     touch2\r
+                * @returns {String}    direction constant, like Hammer.DIRECTION_LEFT\r
+                */\r
+               getDirection : function getDirection( touch1, touch2 ){\r
+                       var x = touch1.pageX - touch2.pageX,\r
+                               y = touch1.pageY - touch2.pageY;\r
+                       return ABS( y ) <= ABS( x ) ?\r
+                               ( x > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT ) :\r
+                               ( y > 0 ? Hammer.DIRECTION_UP   : Hammer.DIRECTION_DOWN );\r
+               },\r
+\r
+               /**\r
+                * calculate the distance between two touches\r
+                * @param   {Touch}     touch1\r
+                * @param   {Touch}     touch2\r
+                * @returns {Number}    distance\r
+                */\r
+               getDistance : function getDistance( touch1, touch2 ){\r
+                       var x = touch2.pageX - touch1.pageX,\r
+                               y = touch2.pageY - touch1.pageY;\r
+                       return Math.sqrt( ( x * x ) + ( y * y ) );\r
+               },\r
+\r
+               /**\r
+                * calculate the scale factor between two touchLists (fingers)\r
+                * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\r
+                * @param   {Array}     start\r
+                * @param   {Array}     end\r
+                * @returns {Number}    scale\r
+                */\r
+               getScale : function getScale( start, end ){\r
+                       // need two fingers...\r
+                       return ( 2 <= start.length && 2 <= end.length ) ?\r
+                               Utils.getDistance( end[ 0 ], end[ 1 ] ) / Utils.getDistance( start[ 0 ], start[ 1 ] ) :\r
+                               1;\r
+               },\r
+\r
+               /**\r
+                * calculate the rotation degrees between two touchLists (fingers)\r
+                * @param   {Array}     start\r
+                * @param   {Array}     end\r
+                * @returns {Number}    rotation\r
+                */\r
+               getRotation : function getRotation( start, end ){\r
+                       // need two fingers\r
+                       return ( 2 <= start.length && 2 <= end.length ) ?\r
+                               Utils.getAngle( end[ 1 ], end[ 0 ] ) - Utils.getAngle( start[ 1 ], start[ 0 ] ) :\r
+                               0;\r
+               },\r
+\r
+               /**\r
+                * boolean if the direction is vertical\r
+                * @param    {String}    direction\r
+                * @returns  {Boolean}   is_vertical\r
+                */\r
+               isVertical : function isVertical( direction ){\r
+                       return direction === Hammer.DIRECTION_UP || direction === Hammer.DIRECTION_DOWN;\r
+               }\r
+       };\r
+       \r
+       /**\r
+        * this holds the last move event,\r
+        * used to fix empty touchend issue\r
+        * see the onTouch event for an explanation\r
+        * @type {Object}\r
+        */\r
+       var last_move_event = null;\r
+\r
+       /**\r
+        * when the mouse is hold down, this is true\r
+        * @type {Boolean}\r
+        */\r
+       var enable_detect = false;\r
+\r
+       /**\r
+        * when touch events have been fired, this is true\r
+        * @type {Boolean}\r
+        */\r
+       var touch_triggered = false;\r
+       \r
+       Detection = {\r
+               // contains all registred Gestures in the correct order\r
+               gestures : [],\r
+\r
+               // data of the current Hammer.gesture detection session\r
+               current : null,\r
+\r
+               // the previous Hammer.gesture session data\r
+               // is a full clone of the previous gesture.current object\r
+               previous : null,\r
+\r
+               // when this becomes true, no gestures are fired\r
+               stopped : false,\r
+\r
+               /**\r
+                * clear the Hammer.gesture vars\r
+                * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected\r
+                * to stop other Gestures from being fired\r
+                */\r
+               stopDetect : function stopDetect() {\r
+                       // clone current data to the store as the previous gesture\r
+                       // used for the double tap gesture, since this is an other gesture detect session\r
+                       Detection.previous = Utils.extend( {}, Detection.current );\r
+\r
+                       // reset the current\r
+                       Detection.current = null;\r
+\r
+                       // stopped!\r
+                       Detection.stopped = true;\r
+               },\r
+\r
+               /**\r
+                * register new gesture\r
+                * @param   {Object}    gesture object, see gestures.js for documentation\r
+                * @returns {Array}     gestures\r
+                */\r
+               register : function( gesture ){\r
+                       // add an enable gesture options if there is no given\r
+                       var options = gesture.defaults || {};\r
+                       if( options[ gesture.name ] === undefined ) options[ gesture.name ] = true;\r
+\r
+                       // extend Hammer default options with the Hammer.gesture options\r
+                       Utils.extend( Hammer.defaults, options, true );\r
+\r
+                       // set its index\r
+                       gesture.index = gesture.index || 1000;\r
+\r
+                       // add Hammer.gesture to the list\r
+                       Detection.gestures.push( gesture );\r
+\r
+                       // sort the list by index\r
+                       Detection.gestures.sort( function( a, b ){\r
+                               return\r
+                                       a.index < b.index ? -1 :\r
+                                       a.index > b.index ? 1 : 0;\r
+                       });\r
+               }\r
+       };\r
+\r
+       var Gestures = Gestures || {};\r
+\r
+       /**\r
+        * Custom gestures\r
+        * ==============================\r
+        *\r
+        * Gesture object\r
+        * --------------------\r
+        * The object structure of a gesture:\r
+        *\r
+        * { name: 'mygesture',\r
+        *   index: 1337,\r
+        *   defaults: {\r
+        *     mygesture_option: true\r
+        *   }\r
+        *   handler: function(type, e, inst) {\r
+        *     // trigger gesture event\r
+        *     inst.trigger(this.name, e );\r
+        *   }\r
+        * }\r
+\r
+        * @param   {String}    name\r
+        * this should be the name of the gesture, lowercase\r
+        * it is also being used to disable/enable the gesture per instance config.\r
+        *\r
+        * @param   {Number}    [index=1000]\r
+        * the index of the gesture, where it is going to be in the stack of gestures detection\r
+        * like when you build an gesture that depends on the drag gesture, it is a good\r
+        * idea to place it after the index of the drag gesture.\r
+        *\r
+        * @param   {Object}    [defaults={}]\r
+        * the default settings of the gesture. these are added to the instance settings,\r
+        * and can be overruled per instance. you can also add the name of the gesture,\r
+        * but this is also added by default (and set to true).\r
+        *\r
+        * @param   {Function}  handler\r
+        * this handles the gesture detection of your custom gesture and receives the\r
+        * following arguments:\r
+        *\r
+        *      @param  {Object}    eventData\r
+        *      event data containing the following properties:\r
+        *          timeStamp   {Number}        time the event occurred\r
+        *          target      {HTMLElement}   target element\r
+        *          touches     {Array}         touches (fingers, pointers, mouse) on the screen\r
+        *          pointerType {String}        kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH\r
+        *          center      {Object}        center position of the touches. contains pageX and pageY\r
+        *          deltaTime   {Number}        the total time of the touches in the screen\r
+        *          deltaX      {Number}        the delta on x axis we haved moved\r
+        *          deltaY      {Number}        the delta on y axis we haved moved\r
+        *          velocityX   {Number}        the velocity on the x\r
+        *          velocityY   {Number}        the velocity on y\r
+        *          angle       {Number}        the angle we are moving\r
+        *          direction   {String}        the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT\r
+        *          distance    {Number}        the distance we haved moved\r
+        *          scale       {Number}        scaling of the touches, needs 2 touches\r
+        *          rotation    {Number}        rotation of the touches, needs 2 touches *\r
+        *          eventType   {String}        matches Hammer.EVENT_START|MOVE|END\r
+        *          srcEvent    {Object}        the source event, like TouchStart or MouseDown *\r
+        *          startEvent  {Object}        contains the same properties as above,\r
+        *                                      but from the first touch. this is used to calculate\r
+        *                                      distances, deltaTime, scaling etc\r
+        *\r
+        *      @param  {Hammer.Instance}    inst\r
+        *      the instance we are doing the detection for. you can get the options from\r
+        *      the inst.options object and trigger the gesture event by calling inst.trigger\r
+        *\r
+        *\r
+        * Handle gestures\r
+        * --------------------\r
+        * inside the handler you can get/set Detection.current. This is the current\r
+        * detection session. It has the following properties\r
+        *      @param  {String}    name\r
+        *      contains the name of the gesture we have detected. it has not a real function,\r
+        *      only to check in other gestures if something is detected.\r
+        *      like in the drag gesture we set it to 'drag' and in the swipe gesture we can\r
+        *      check if the current gesture is 'drag' by accessing Detection.current.name\r
+        *\r
+        *      @readonly\r
+        *      @param  {Hammer.Instance}    inst\r
+        *      the instance we do the detection for\r
+        *\r
+        *      @readonly\r
+        *      @param  {Object}    startEvent\r
+        *      contains the properties of the first gesture detection in this session.\r
+        *      Used for calculations about timing, distance, etc.\r
+        *\r
+        *      @readonly\r
+        *      @param  {Object}    lastEvent\r
+        *      contains all the properties of the last gesture detect in this session.\r
+        *\r
+        * after the gesture detection session has been completed (user has released the screen)\r
+        * the Detection.current object is copied into Detection.previous,\r
+        * this is usefull for gestures like doubletap, where you need to know if the\r
+        * previous gesture was a tap\r
+        *\r
+        * options that have been set by the instance can be received by calling inst.options\r
+        *\r
+        * You can trigger a gesture event by calling inst.trigger("mygesture", event).\r
+        * The first param is the name of your gesture, the second the event argument\r
+        *\r
+        *\r
+        * Register gestures\r
+        * --------------------\r
+        * When an gesture is added to the Gestures object, it is auto registered\r
+        * at the setup of the first Hammer instance. You can also call Detection.register\r
+        * manually and pass your gesture object as a param\r
+        *\r
+        */\r
+\r
+       /**\r
+        * Hold\r
+        * Touch stays at the same place for x time\r
+        * @events  hold holdend\r
+        */\r
+       Gestures.Hold = {\r
+               name  : 'hold',\r
+               index : 10,\r
+               startID : X.View.Event.HOLD,\r
+               endID   : X.View.Event.HOLD_END,\r
+               defaults : {\r
+                       hold_timeout   : 500,\r
+                       hold_threshold : 1\r
+               },\r
+               timerID : null,\r
+               holding : false,\r
+               handler : function holdGesture( e, hammer ){\r
+                       switch( e.eventType ){\r
+                               case START :\r
+                                       // clear any running timers\r
+                                       this.timerID && X.Timer.remove( this.timerID );\r
+\r
+                                       // set the gesture so we can check in the timeout if it still is\r
+                                       Detection.current.name = this.name;\r
+                                       Gestures.Hold.holding = false;\r
+                                       \r
+                                       // set timer and if after the timeout it still is hold,\r
+                                       // we trigger the hold event\r
+                                       this.timerID = X.Timer.add( hammer.options.hold_timeout, 1, Gestures.Hold._onTimer, [ e, hammer ] );\r
+                                       return;\r
+\r
+                               // when you move or end we clear the timer\r
+                               case MOVE :\r
+                                       if( e.distance <= hammer.options.hold_threshold ) return;\r
+                               case END :\r
+                                       this.timerID && X.Timer.remove( this.timerID );\r
+                                       if( Gestures.Hold.holding === true ){\r
+                                               Gestures.Hold.holding = false;\r
+                                               return hammer.trigger( X.View.Event.HOLD_END, e );\r
+                                       };\r
+                                       break;\r
+                       };\r
+               },\r
+               _onTimer : function( e, hammer ){\r
+                       if( Detection.current.name === 'hold' ){\r
+                               hammer.trigger( X.View.Event.HOLD, e );\r
+                               Gestures.Hold.holding = true;\r
+                       };\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Tap/DoubleTap\r
+        * Quick touch at a place or double at the same place\r
+        * @events  tap, doubletap\r
+        */\r
+       Gestures.Tap = {\r
+               name     : 'tap',\r
+               index    : 100,\r
+               startID  : X.View.Event.TAP,\r
+               endID    : X.View.Event.DOUBLE_TAP,\r
+               defaults : {\r
+                       tap_max_touchtime  : 250,\r
+                       tap_max_distance   : 10,\r
+                       tap_always         : true,\r
+                       doubletap_distance : 20,\r
+                       doubletap_interval : 300\r
+               },\r
+               handler : function tapGesture( e, hammer ){\r
+                       // previous gesture, for the double tap since these are two different gesture detections\r
+                       var prev = Detection.previous;\r
+                       if( e.eventType === END ){\r
+                               // when the touchtime is higher then the max touch time\r
+                               // or when the moving distance is too much\r
+                               if( hammer.options.tap_max_touchtime < e.deltaTime || hammer.options.tap_max_distance < e.distance ) return;\r
+\r
+                               // check if double tap\r
+                               if( prev && prev.name === 'tap' && ( e.timeStamp - prev.lastEvent.timeStamp ) < hammer.options.doubletap_interval && e.distance < hammer.options.doubletap_distance ){\r
+                                       return hammer.trigger( X.View.Event.DOUBLE_TAP, e );\r
+                               } else\r
+                               // do a single tap\r
+                               if( hammer.options.tap_always ){\r
+                                       Detection.current.name = 'tap';\r
+                                       return hammer.trigger(  X.View.Event.TAP, e );\r
+                               };\r
+                       };\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Swipe\r
+        * triggers swipe events when the end velocity is above the threshold\r
+        * @events  swipe, swipeleft, swiperight, swipeup, swipedown\r
+        */\r
+       Gestures.Swipe = {\r
+               name : 'swipe',\r
+               index : 40,\r
+               startID  : X.View.Event.SWIP,\r
+               endID    : X.View.Event.SWIP_DOWN,\r
+               defaults : {\r
+                       // set 0 for unlimited, but this can conflict with transform\r
+                       swipe_max_touches : 1,\r
+                       swipe_velocity : 0.7\r
+               },\r
+               handler : function swipeGesture(e, hammer) {\r
+                       if( e.eventType === END ){\r
+                               // max touches\r
+                               if( 0 < hammer.options.swipe_max_touches && hammer.options.swipe_max_touches < e.touches.length ) return;\r
+\r
+                               // when the distance we moved is too small we skip this gesture\r
+                               // or we can be already in dragging\r
+                               if( hammer.options.swipe_velocity < e.velocityX || hammer.options.swipe_velocity < e.velocityY ){\r
+                                       // trigger swipe events\r
+                                       hammer.trigger( X.View.Event.SWIP, e );\r
+                                       hammer.trigger(\r
+                                               e.direction === Hammer.DIRECTION_UP ?\r
+                                                       X.View.Event.SWIP_UP :\r
+                                               e.direction === Hammer.DIRECTION_DOWN ?\r
+                                                       X.View.Event.SWIP_DOWN :\r
+                                               e.direction === Hammer.DIRECTION_LEFT ?\r
+                                                       X.View.Event.SWIP_LEFT :\r
+                                                       X.View.Event.SWIP_RIGHT,\r
+                                               e\r
+                                       );\r
+                               };\r
+                       };\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Drag\r
+        * Move with x fingers (default 1) around on the page. Blocking the scrolling when\r
+        * moving left and right is a good practice. When all the drag events are blocking\r
+        * you disable scrolling on that area.\r
+        * @events  drag, dragstart, dragend, drapleft, dragright, dragup, dragdown\r
+        */\r
+       Gestures.Drag = {\r
+               name : 'drag',\r
+               index : 50,\r
+               startID  : X.View.Event.DRAG,\r
+               endID    : X.View.Event.DRAG_DOWN,\r
+               defaults : {\r
+                       drag_min_distance : 10,\r
+                       // set 0 for unlimited, but this can conflict with transform\r
+                       drag_max_touches : 1,\r
+                       // prevent default browser behavior when dragging occurs\r
+                       // be careful with it, it makes the element a blocking element\r
+                       // when you are using the drag gesture, it is a good practice to set this true\r
+                       drag_block_horizontal : false,\r
+                       drag_block_vertical : false,\r
+                       // drag_lock_to_axis keeps the drag gesture on the axis that it started on,\r
+                       // It disallows vertical directions if the initial direction was horizontal, and vice versa.\r
+                       drag_lock_to_axis : false,\r
+                       // drag lock only kicks in when distance > drag_lock_min_distance\r
+                       // This way, locking occurs only when the distance has become large enough to reliably determine the direction\r
+                       drag_lock_min_distance : 25\r
+               },\r
+               triggered : false,\r
+               handler : function dragGesture( e, hammer ){\r
+                       var last_direction;\r
+                       // current gesture isnt drag, but dragged is true\r
+                       // this means an other gesture is busy. now call dragend\r
+                       if( Detection.current.name !== this.name && this.triggered ){\r
+                               hammer.trigger( X.View.Event.DRAG_END, e );\r
+                               this.triggered = false;\r
+                               return;\r
+                       };\r
+\r
+                       // max touches\r
+                       if( 0 < hammer.options.drag_max_touches && hammer.options.drag_max_touches < e.touches.length ) return;\r
+\r
+                       switch( e.eventType ){\r
+                               case START:\r
+                                       this.triggered = false;\r
+                                       break;\r
+\r
+                               case MOVE :\r
+                                       // when the distance we moved is too small we skip this gesture\r
+                                       // or we can be already in dragging\r
+                                       if( e.distance < hammer.options.drag_min_distance && Detection.current.name !== this.name ) return;\r
+\r
+                                       // we are dragging!\r
+                                       Detection.current.name = this.name;\r
+\r
+                                       // lock drag to axis?\r
+                                       if( Detection.current.lastEvent.drag_locked_to_axis || ( hammer.options.drag_lock_to_axis && hammer.options.drag_lock_min_distance <= e.distance ) ){\r
+                                               e.drag_locked_to_axis = true;\r
+                                       };\r
+                                       last_direction = Detection.current.lastEvent.direction;\r
+                                       if( e.drag_locked_to_axis && last_direction !== e.direction ){\r
+                                               // keep direction on the axis that the drag gesture started on\r
+                                               e.direction = Utils.isVertical( last_direction ) ?\r
+                                                       ( e.deltaY < 0 ? Hammer.DIRECTION_UP   : Hammer.DIRECTION_DOWN ) :\r
+                                                       ( e.deltaX < 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT );\r
+                                       };\r
+\r
+                                       // first time, trigger dragstart event\r
+                                       if( !this.triggered ){\r
+                                               hammer.trigger( X.View.Event.DRAG_START, e );\r
+                                               this.triggered = true;\r
+                                       };\r
+\r
+                                       // trigger normal event\r
+                                       hammer.trigger( X.View.Event.DRAG, e );\r
+\r
+                                       // direction event, like dragdown\r
+                                       hammer.trigger(\r
+                                               e.direction === Hammer.DIRECTION_UP ?\r
+                                                       X.View.Event.DRAG_UP :\r
+                                               e.direction === Hammer.DIRECTION_DOWN ?\r
+                                                       X.View.Event.DRAG_DOWN :\r
+                                               e.direction === Hammer.DIRECTION_LEFT ?\r
+                                                       X.View.Event.DRAG_LEFT :\r
+                                                       X.View.Event.DRAG_RIGHT,\r
+                                               e\r
+                                       );\r
+\r
+                                       // block the browser events\r
+                                       (\r
+                                               ( hammer.options.drag_block_vertical   &&  Utils.isVertical( e.direction ) ) ||\r
+                                               ( hammer.options.drag_block_horizontal && !Utils.isVertical( e.direction ) )\r
+                                       ) && e.preventDefault();\r
+                                       break;\r
+\r
+                               case END:\r
+                                       // trigger dragend\r
+                                       this.triggered && hammer.trigger( X.View.Event.DRAG_END, e );\r
+                                       this.triggered = false;\r
+                                       break;\r
+                       }\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Transform\r
+        * User want to scale or rotate with 2 fingers\r
+        * @events  transform, transformstart, transformend, pinch, pinchin, pinchout, rotate\r
+        */\r
+       Gestures.Transform = {\r
+               name : 'transform',\r
+               index : 45,\r
+               startID  : X.View.Event.TRANSFORM,\r
+               endID    : X.View.Event.ROTATE,\r
+               defaults : {\r
+                       // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1\r
+                       transform_min_scale : 0.01,\r
+                       // rotation in degrees\r
+                       transform_min_rotation : 1,\r
+                       // prevent default browser behavior when two touches are on the screen\r
+                       // but it makes the element a blocking element\r
+                       // when you are using the transform gesture, it is a good practice to set this true\r
+                       transform_always_block : false\r
+               },\r
+               triggered : false,\r
+               handler : function transformGesture( e, hammer ){\r
+                       // current gesture isnt drag, but dragged is true\r
+                       // this means an other gesture is busy. now call dragend\r
+                       if( Detection.current.name !== this.name && this.triggered ){\r
+                               hammer.trigger( X.View.Event.TRANSFORM_END, e );\r
+                               this.triggered = false;\r
+                               return;\r
+                       };\r
+\r
+                       // atleast multitouch\r
+                       if( e.touches.length < 2 ) return;\r
+\r
+                       // prevent default when two fingers are on the screen\r
+                       hammer.options.transform_always_block && e.preventDefault();\r
+\r
+                       switch(e.eventType) {\r
+                               case START:\r
+                                       this.triggered = false;\r
+                                       break;\r
+\r
+                               case MOVE:\r
+                                       var scale_threshold    = ABS( 1 - e.scale ),\r
+                                               rotation_threshold = ABS( e.rotation );\r
+\r
+                                       // when the distance we moved is too small we skip this gesture\r
+                                       // or we can be already in dragging\r
+                                       if( scale_threshold < hammer.options.transform_min_scale && rotation_threshold < hammer.options.transform_min_rotation ) return;\r
+\r
+                                       // we are transforming!\r
+                                       Detection.current.name = this.name;\r
+\r
+                                       // first time, trigger dragstart event\r
+                                       if( !this.triggered ){\r
+                                               hammer.trigger( X.View.Event.TRANSFORM_START, e );\r
+                                               this.triggered = true;\r
+                                       };\r
+\r
+                                       hammer.trigger( X.View.Event.TRANSFORM, e );\r
+                                       // basic transform event\r
+\r
+                                       // trigger rotate event\r
+                                       hammer.options.transform_min_rotation < rotation_threshold && hammer.trigger( X.View.Event.ROTATE, e );\r
+\r
+                                       // trigger pinch event\r
+                                       if( scale_threshold > hammer.options.transform_min_scale ){\r
+                                               hammer.trigger( X.View.Event.PINCH, e );\r
+                                               hammer.trigger( e.scale < 1 ? X.View.Event.PINCH_IN : X.View.Event.PINCH_OUT, e );\r
+                                       };\r
+                                       break;\r
+\r
+                               case END:\r
+                                       // trigger dragend\r
+                                       this.triggered && hammer.trigger( X.View.Event.TRANSFORM_END, e );\r
+                                       this.triggered = false;\r
+                                       break;\r
+                       };\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Touch\r
+        * Called as first, tells the user has touched the screen\r
+        * @events  touch\r
+        */\r
+       Gestures.Touch = {\r
+               name : 'touch',\r
+               index : -Infinity,\r
+               defaults : {\r
+                       // call preventDefault at touchstart, and makes the element blocking by\r
+                       // disabling the scrolling of the page, but it improves gestures like\r
+                       // transforming and dragging.\r
+                       // be careful with using this, it can be very annoying for users to be stuck\r
+                       // on the page\r
+                       prevent_default : false,\r
+\r
+                       // disable mouse events, so only touch (or pen!) input triggers events\r
+                       prevent_mouseevents : false\r
+               },\r
+               handler : function touchGesture( e, hammer ){\r
+                       if( hammer.options.prevent_mouseevents && e.pointerType === MOUSE ){\r
+                               Detection.stopDetect();\r
+                               return;\r
+                       };\r
+\r
+                       hammer.options.prevent_default && e.preventDefault();\r
+\r
+                       e.eventType === START && hammer.trigger( this.name, e );\r
+               }\r
+       };\r
+\r
+       /**\r
+        * Release\r
+        * Called as last, tells the user has released the screen\r
+        * @events  release\r
+        */\r
+       Gestures.Release = {\r
+               name : 'release',\r
+               index : Infinity,\r
+               handler : function releaseGesture( e, hammer ){\r
+                       e.eventType === END && hammer.trigger( this.name, e );\r
+               }\r
+       };\r
+       \r
+})( Math, window, document );
\ No newline at end of file
index 1749928..60e5f25 100644 (file)
@@ -12,6 +12,7 @@ var _AbstractDisplayNode = X.Class.create(
                \r
                events        : null, // X.EventDispatcher で設定される\r
                reserveEvents : null,\r
+               gesture       : null,\r
                //elmScroll     : null,\r
                //elmScroller   : null,\r
                //elmScrollbar  : null,\r
@@ -214,7 +215,7 @@ var _AbstractDisplayNode = X.Class.create(
                                return ret;\r
                        };\r
                        this.rootData.monopolyNodeData = null;\r
-                       if( xve._NO_BUBLEUP < type && this.parentData && ret & X.Callback.STOP_PROPAGATION === 0 && ret & X.Callback.STOP_NOW === 0 ) return this.parentData.dispatch( e );\r
+                       if( xve._START_BUBLEUP < type && this.parentData && ret & X.Callback.STOP_PROPAGATION === 0 && ret & X.Callback.STOP_NOW === 0 ) return this.parentData.dispatch( e );\r
                        return ret;\r
                },\r
                \r
@@ -666,16 +667,24 @@ var AbstractDisplayNode = X.EventDispatcher.inherits(
                                        events[ events.length ] = [ type, arg1, arg2 ];\r
                                        return this;\r
                                };\r
-                               root    = data.rootData;\r
-                               counter = root.eventCounter;\r
-                               if( counter[ type ] ){\r
-                                       ++counter[ type ];\r
+                               if( X.View.Event._START_XUI_EVENT < type && type < X.View.Event._END_XUI_EVENT ){\r
+                                       if( !this.gesture ){\r
+                                               this.gesture = new X.UI.Gesture( data.root, this, type );\r
+                                       } else {\r
+                                               this.gesture.listen( type );\r
+                                       };\r
                                } else {\r
-                                       counter[ type ] = 1;\r
-                                       X.Dom.Event.add( root.elmMouseCatch, X.View.Event.IdToName[ type ], eventRellay );                                      \r
+                                       root    = data.rootData;\r
+                                       counter = root.eventCounter;\r
+                                       if( counter[ type ] ){\r
+                                               ++counter[ type ];\r
+                                       } else {\r
+                                               counter[ type ] = 1;                            \r
+                                               X.Dom.Event.add( root.elmMouseCatch, X.View.Event.IdToName[ type ], eventRellay );\r
+                                       };\r
                                };\r
                        };\r
-                       return X.EventDispatcher.prototype.listen.apply( this, arguments );\r
+                       return this.Super.listen.apply( this, arguments );\r
                },\r
                unlisten : function( type, arg1, arg2 ){\r
                        var root, data, events, i, ev, counter;\r
@@ -692,13 +701,18 @@ var AbstractDisplayNode = X.EventDispatcher.inherits(
                                        }; \r
                                        return this;\r
                                };\r
-                               root    = data.rootData;\r
-                               counter = root.eventCounter;\r
-                               if( !counter[ type ] ) return this;\r
-                               --counter[ type ];\r
-                               if( counter[ type ] === 0 ){\r
-                                       X.Dom.Event.remove( root.elmMouseCatch, X.View.Event.IdToName[ type ], eventRellay );\r
-                                       delete counter[ type ];\r
+\r
+                               if( X.View.Event._START_XUI_EVENT < type && type < X.View.Event._END_XUI_EVENT ){\r
+                                       this.gesture && this.gesture.unlisten( type );\r
+                               } else {\r
+                                       root    = data.rootData;\r
+                                       counter = root.eventCounter;\r
+                                       if( !counter[ type ] ) return this;\r
+                                       --counter[ type ];\r
+                                       if( counter[ type ] === 0 ){\r
+                                               X.Dom.Event.remove( root.elmMouseCatch, X.View.Event.IdToName[ type ], eventRellay );\r
+                                               delete counter[ type ];\r
+                                       };\r
                                };\r
                        };\r
                        return X.EventDispatcher.prototype.unlisten.apply( this, arguments );\r
index 942e035..135e812 100644 (file)
@@ -10,7 +10,6 @@ var _ChromeBox = _AbstractDisplayContainer.inherits(
                        var nodes = this.nodes,\r
                                i     = nodes.length,\r
                                node;\r
-                       this.chromeNodes = [];\r
                        for( ; i; ){\r
                                node = nodes[ --i ];\r
                                if( node.forContainer === true ){\r
@@ -19,6 +18,7 @@ var _ChromeBox = _AbstractDisplayContainer.inherits(
                                        };\r
                                        this.containerNode = node;\r
                                } else {\r
+                                       if( !this.chromeNodes  ) this.chromeNodes = [];\r
                                        this.chromeNodes[ this.chromeNodes.length ] = node;\r
                                };\r
                        };\r
index 8d7889e..eb456b1 100644 (file)
@@ -10,7 +10,7 @@ function eventRellay( e ){
                sysOnly = false,
                list, ret, parent;
        if( type !== X.View.Event.POINTER_MOVE ){
-               // console.log( e.type + ' x:' + x + ', y:' + y )
+               console.log( type + ' x:' + x + ', y:' + y )
        };
        
        e.type = type;
@@ -104,7 +104,13 @@ var _PageRoot = _AbstractDisplayContainer.inherits(
                        // hover や rollover rollout のための move イベントの追加
                        // X.View.activate, X.View.deactivate ?
                        // mouseout, mouseover
-                       X.Dom.Event.add( elm, X.View.Event.IdToName[ X.View.Event.POINTER_MOVE ], eventRellay );
+                       if( navigator.msPointerEnabled || navigator.pointerEnabled ){
+                               X.Dom.Event.add( elm, X.View.Event.IdToName[ X.View.Event._POINTER_MOVE ], eventRellay );
+                       } else {
+                               X.Dom.Event.add( elm, X.View.Event.IdToName[ X.View.Event._MOUSE_MOVE ], eventRellay );
+                       };
+               
+
                        if( counter[ X.View.Event.POINTER_MOVE ] ){
                                ++counter[ X.View.Event.POINTER_MOVE ];
                        } else {
@@ -148,7 +154,12 @@ var _PageRoot = _AbstractDisplayContainer.inherits(
                },
                
                beforeRemove : function(){
-                       X.Dom.Event.remove( this.elmMouseCatch, X.View.Event.IdToName[ X.View.Event.POINTER_MOVE ], eventRellay );
+                       if( navigator.msPointerEnabled || navigator.pointerEnabled ){
+                               X.Dom.Event.remove( this.elmMouseCatch, X.View.Event.IdToName[ X.View.Event._POINTER_MOVE ], eventRellay );
+                       } else {
+                               // Android で mouse が有効の場合がある
+                               X.Dom.Event.remove( this.elmMouseCatch, X.View.Event.IdToName[ X.View.Event._MOUSE_MOVE ], eventRellay );
+                       };
                }
        }
 );