2012-05-08 2 views
0

mouseover/mouseout에서 버튼의 메뉴 표시/숨기기를 가능하게하는 Ext.Button의 확장 작업을하고 있습니다. 그것은 바로 버튼의 직접적인 자식 메뉴를 위해 완벽하게 작동하지만, 2 차/3 차/ect 메뉴에 대해 제대로 작동하는 문제가 있습니다.ExtJS 4.1 "HoverButton"확장 문제

바로 가기 메뉴를 포함하는 최상위 메뉴에서 사용자가 이동하면 메뉴가 열리고 사용자는 커서를 아무 문제없이 이동할 수 있으며 모든 것이 계속 열려 있습니다. 그런 다음 사용자가 커서를 보조 메뉴 밖으로 열린 공간으로 이동하면 모든 메뉴가 올바르게 닫힙니다. 하지만 사용자가 보조 메뉴로 이동 한 다음 부모 메뉴로 돌아 가면 모든 메뉴가 닫히고 커서가 지금 끝난 상태의 부모 메뉴가 열려 있어야합니다. .

제 초기 디버깅에서 이벤트가 발생하는 방식과 타이밍에 문제가있는 것으로 보입니다. 자식 메뉴에서 부모 메뉴로 다시 이동할 때 부모 메뉴에 대한 mouseenter 이벤트가 발생하지 않는 것으로 보입니다. 둘째로 나에게 메뉴 mouseover 이벤트가 자식 메뉴의 mouseleave 이벤트가 시작된 후 지연된 숨기기 작업을 취소하기에 충분히 안정적으로 또는 자주 불이 들지 않는 것처럼 보입니다. 문제의

데모 : 여기 http://qs1724.pair.com/users/autod1nx/EMPLOYEE/BDAMI/hoverbutton/index.html

그리고는 눈에 띄는 코드의 그것과 근본적으로 뭔가 잘못입니까?

Ext.define('Ext.HoverButton', {  
    extend: 'Ext.Button', 
    alias: 'widget.hoverButton', 
    isOver: false, 
    hideDelay: 250, 
    showDelay: 200, 

    applyListeners: function(menu, cfg) { 
     Ext.apply(menu, cfg); 
     Ext.each(menu.items, function(item, idx, allItems) { 
      if(item.menu) this.applyListeners(item.menu, cfg); 
     }, this); 
    }, 

    initComponent: function() { 
     var config = {}, 
      menuConfig = {}, 
      me = this; 

     me.delayedShowMenu = new Ext.util.DelayedTask(function() { 
      if(!me.isOver) return; 
      me.showMenu(); 
     }, this); 

     me.delayedHideMenu = new Ext.util.DelayedTask(function() { 
      if(me.isOver) return; 
      me.hideMenu(); 
     }); 

     if(Ext.isDefined(this.initialConfig.menu)) { 
      config = { 
       listeners: { 
        mouseover: { 
         scope: me, 
         fn: function(b) { 
          me.isOver = true; 
          me.delayedShowMenu.delay(me.showDelay); 
         } 
        }, 
        mouseout: { 
         scope: me, 
         fn: function(b) { 
          me.isOver = false; 
          me.delayedHideMenu.delay(me.hideDelay); 
         } 
        } 
       } 
      }; 

      menuConfig = { 
       listeners: { 
        mouseover: { 
         scope: me, 
         fn: function(menu, item, e) { 
          me.delayedHideMenu.cancel(); 
         } 
        }, 
        mouseenter: { 
         scope: me, 
         fn: function(menu, e) { 
          me.delayedHideMenu.cancel(); 
         } 
        }, 
        mouseleave: { 
         scope: me, 
         fn: function(menu, e) { 
          me.delayedHideMenu.delay(me.hideDelay); 
         } 
        } 
       } 
      }; 


      //apply mouseover/leave listeners to all submenus recursively 
      me.applyListeners(me.menu, menuConfig);  
     } 

     Ext.apply(me, Ext.apply(me.initialConfig, config)); 
     Ext.HoverButton.superclass.initComponent.apply(me, arguments); 
    } 
}); 
+0

menuConfig 수신기 이벤트에'me.isOver = true/false'를 추가 했습니까? –

+0

나는 그래, 어떤 차이를 만들 것 같지 않았어. 테스트가 끝나면 마우스 오버 이벤트가 발생하는 방식에 문제가있는 것처럼 보입니다. 그것은 실제로 하위 메뉴를 떠날 때 mouseleave 이벤트가 발생한 후 delayedHideMenu에서 .cancel()을 호출하기에 충분하거나 일관되게 실행되지 않습니다. –

답변

1

내가 조금 비슷한 일을 봤는데 내가 http://www.quirksmode.org/dom/events/mouseover.html

DOM의 이벤트 순서는 마우스 오버해야한다는 것 엿봄을 촬영 한 후 문제를 해결했습니다 -> mouseenter ->로 마우스 -> mouseleave 이는 delay()가 설정되기 전에 cancel()이 호출되는 경우가 있음을 의미합니다. 문제를 해결하기 위해 변수에 마지막으로 입력 한 것을 보관합니다.

mouseenter: { 
scope: me, 
fn: function(menu, e) { 
    presentlyInside = menu; /* << */ 
    me.delayedHideMenu.cancel(); 
} 
}, 
mouseleave: { 
scope: me, 
fn: function(menu, e) { 
    if(presentlyInside==menu) /* << */ 
    me.delayedHideMenu.delay(me.hideDelay); 
} 
} 

희망이 있습니다.

+0

흥미 롭다. 잠시 동안이 코드를 만지기 시작 했으므로, 다음번에이 코드를 시도해 봐야 할 것이다. 응답 주셔서 감사합니다! –

+0

저는 anwser를 게시하기 전에 몇 분 밖에 작동하지 않았지만, 지금까지는 구현과 (Chrome에서) 어떤 결함도 발견하지 못했습니다. –

+0

나는이 응답이 매우 늦었다는 것을 알고 있지만, 마침내 수정 사항을 사용하여 확장을 업데이트했으며 챔피언처럼 작동합니다! 다시 한 번 감사드립니다 !! –

4

이 작품이 더 간단하고 더 간단하다는 것을 알았습니다.

Ext.define('Ext.HoverButton', { 
extend : 'Ext.Button', 
alias  : 'widget.hoverButton', 
listeners : { 
     mouseover : function() { 
      this.showMenu(); 
     }, 
     menushow : function() { 
      this.mouseLeaveMonitor = this.menu.el.monitorMouseLeave(100, this.hideMenu, this); 
     }, 
     destroy : function(combo) { 
      combo.menu.el.un(combo.mouseLeaveMonitor); 
     } 
    } 
});