2012-08-10 31 views
7

jsf 2とglassfish 3.1.2でPrimeface 3.2を使用しています。Primefacesによる遅延問題overlayPanel - 遅延ロード

私は、ユーザーのアバターを含むユーザーのp:dataTableを持っています。ユーザーはアバターAP上にマウスを移動するたびに:overlayPanelは、ユーザーに(遅延ロード)の詳細情報が表示され、ユーザーが離れてカーソルを移動させると消える - このように:これは非常にうまく機能

<p:overlayPanel for="avatar" dynamic="true" showEvent="mouseover" hideEvent="mouseout" ...>

- ユーザーが「スローハンド」されている限り。ユーザーが多くのアバターの上でカーソルをすばやく動かすと、多くのoverlayPanelsが表示されたままになります。 たとえば、ユーザーがユーザーのアバターが表示されている位置にカーソルを合わせ、マウスのスクロールホイールを使用してユーザーテーブルを上下にスクロールします。

showEvent="mouseover"がディスパッチされたときにオーバーレイパネルが情報を動的にロードし始め(dynamic="true")、サーバーからの応答が到着した後にオーバーレイパネルが表示されると考えています。 この方法では、オーバーレイパネルが表示されたときにカーソルがすでに離れているかどうかを検出することができないため、hideEvent="mouseout"はディスパッチされません。

primefaces overlaypanelをmousover上に直接表示し、ロードGIFを表示し、応答がサーバーから来たときにオーバーレイパネルにコンテンツを更新する方法はありますか。

これは良いappraochですか、誰もこの厄介な問題を解決するために他の方法を知っていますか?

おかげでピート

+0

あなたは幸運にも1つのコンテンツを実際に取得します。私がまったく同じ問題を経験している間、私のコンテンツは完全に欠落しています。実際の行モデルへの参照を持たない単純なh:outputText(varで指定したもの)は表示されません。その素人からの開発者が非常に一般的なエンタープライズの問題(IMOでは、p:overlayPanelやp:tooltipがテーブルで使用するように設計されているように見える)を考慮していないこともわかりました。 – Paranaix

+0

Firebugでワークフローをテストしましたか? JSエラーをチェックし、サーバーからのajaxレスポンスの内容も確認します。 –

+0

はい、ajaxリクエストが送信されます。その本当に奇妙な; 3.3ではなく最新の3.4スナップショットを使用しています。新しいバグかもしれない。 – Paranaix

答えて

4

私の最初の答えはすでに非常に長く、有効な情報が含まれているので、私は最終的なアプローチを提示する新しい答えを開くことに決めました。

私は今、プライムフェースの継承パターンを使用して、コードをより洗練されたものにしています。また、私は古いイベントハンドラを削除できるので、全体のbindEvents機能を置き換える/上書きすることは必要ではないことに気づいた。最後に、このコードは経験した最新の問題を修正します:ajax到着前のhideイベント。

PrimeFaces.widget.OverlayPanel = PrimeFaces.widget.OverlayPanel 
     .extend({ 

      bindEvents : function() { 
       this._super(); 

       var showEvent = this.cfg.showEvent + '.ui-overlay', hideEvent = this.cfg.hideEvent 
         + '.ui-overlay'; 

       $(document).off(showEvent + ' ' + hideEvent, this.targetId).on(
         showEvent, this.targetId, this, function(e) { 
          var _self = e.data; 

          clearTimeout(_self.timer); 
          _self.timer = setTimeout(function() { 
           _self.hidden = false; 
           _self.show(); 
          }, 300); 
         }).on(hideEvent, this.targetId, this, function(e) { 
        var _self = e.data; 

        clearTimeout(_self.timer); 
        _self.hidden = true; 
        _self.hide(); 

       }); 
      }, 

      _show : function() { 
       if (!this.cfg.dynamic || !this.hidden) { 
        this._super(); 
       } 
      } 

     }); 

貧困層の書式設定のため申し訳ありませんイム:日食障害;私はPrimefaces 5.2のためにそれを更新するための機会を利用し、この華麗なソリューションをありがとうございました。同時に)

2

うわー、ついに長いデバッグのセッションの後、私は問題がAJAXリクエストが、イベントハンドラ自体がイマイチという認識の様々なアプローチテスト:あなたが見ることができるように

.on(hideEvent, this.targetId, this, function(e) { 
      var _self = e.data; 

      if(_self.isVisible()) { 
       _self.hide(); 
      } 
     }); 

を、ウィジェットは、前に表示されている場合は隠されています。あなたが出て速すぎて、あなたのマウスを移動した場合、今二つのことが起こることができます。すべての

  • アニメーションで表示

    • ウィジェットイマイチをまだイベントが破棄される。この場合、

    に起こっているとパネルは表示されたままです。アニメーションがキューに入れられると、問題を解決するために単にifステートメントを削除するだけです。私は、全体のbindEvents方法を置き換えることによって、これをしなかった:

    PrimeFaces.widget.OverlayPanel.prototype.bindEvents = function() { 
        //mark target and descandants of target as a trigger for a primefaces overlay 
        this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id); 
    
        //show and hide events for target 
        if(this.cfg.showEvent == this.cfg.hideEvent) { 
         var event = this.cfg.showEvent; 
    
         $(document).off(event, this.targetId).on(event, this.targetId, this, function(e) { 
          e.data.toggle(); 
         }); 
        } 
        else { 
         var showEvent = this.cfg.showEvent + '.ui-overlay', 
         hideEvent = this.cfg.hideEvent + '.ui-overlay'; 
    
         $(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) { 
          var _self = e.data; 
    
          if(!_self.isVisible()) { 
           _self.show(); 
          } 
         }) 
         .on(hideEvent, this.targetId, this, function(e) { 
          var _self = e.data; 
    
          _self.hide(); 
    
         }); 
        } 
    
        //enter key support for mousedown event 
        this.bindKeyEvents(); 
    
        var _self = this; 
    
        //hide overlay when mousedown is at outside of overlay 
        $(document.body).bind('mousedown.ui-overlay', function (e) { 
         if(_self.jq.hasClass('ui-overlay-hidden')) { 
          return; 
         } 
    
         //do nothing on target mousedown 
         var target = $(e.target); 
         if(_self.target.is(target)||_self.target.has(target).length > 0) { 
          return; 
         } 
    
         //hide overlay if mousedown is on outside 
         var offset = _self.jq.offset(); 
         if(e.pageX < offset.left || 
          e.pageX > offset.left + _self.jq.outerWidth() || 
          e.pageY < offset.top || 
          e.pageY > offset.top + _self.jq.outerHeight()) { 
    
          _self.hide(); 
         } 
        }); 
    
        //Hide overlay on resize 
        var resizeNS = 'resize.' + this.id; 
        $(window).unbind(resizeNS).bind(resizeNS, function() { 
         if(_self.jq.hasClass('ui-overlay-visible')) { 
          _self.hide(); 
         } 
        }); 
    }; 
    

    が負荷にこのコードを実行し、問題がなくなってしなければなりません。



    あなたは、それにもかかわらず、JSコードを交換するとして、あなたは非常に便利な機能を実装するために、このoppurtunityを使用することができます。

     $(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) { 
          var _self = e.data; 
    
          _self.timer = setTimeout(function(){ 
           if(!_self.isVisible()) { 
            _self.show(); 
           } 
          }, 300); 
         }) 
         .on(hideEvent, this.targetId, this, function(e) { 
          var _self = e.data; 
    
          clearTimeout(_self.timer); 
          _self.hide(); 
    
         }); 
    

    は勿論、あなたが遅延を制御するために、グローバル変数を使用することができます。イベントハンドラでタイムアウトを使用することにより、1つだけで簡単にユーザビリティ(ポップアップのこれ以上の何千も表示されません)も減らすネットワークトラフィックを改善していない少し遅れを実装することができます時間。より柔軟なアプローチが必要な場合は、OverlayPanelRenderencodeScriptメソッドを上書きして、追加のプロパティを送信する必要があります。 _self.cfg.delayでアクセスできます。ただし、コンポーネントモデルOverlayPanelを置き換えるには余分な属性を指定する必要があります。

  • +0

    あなたの努力のおかげで、同時に良いと悪い音。私はこれをチェックし、後で戻ってきます。 –

    +0

    Primefaces 3.3またはSnapshot for 3.4を使用しましたか?私は現在、あなたのアイデアや変更をプライムフェイスに適応させようとしています。3.2 –

    +0

    3.4のスナップショットを使用しています。私はそれを10.8から考える。私はそれでもかなり確信していません。 3.3で経験したいくつかのバグは、アップデートによって修正されました。最も注目すべきはおそらくf:p:menuitemのparamサポートです。 – Paranaix

    2

    。私たちのアプリケーションでは、アップグレード後にコードが壊れました。

    Primefaces 5.2のための更新されたコードは、次のとおりです。

    PrimeFaces.widget.OverlayPanel.prototype.bindTargetEvents = function() { 
        var $this = this; 
        //mark target and descandants of target as a trigger for a primefaces overlay 
        this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id); 
    
        //show and hide events for target 
        if(this.cfg.showEvent === this.cfg.hideEvent) { 
         var event = this.cfg.showEvent; 
    
         this.target.on(event, function(e) { 
          $this.toggle(); 
         }); 
        } 
        else { 
         var showEvent = this.cfg.showEvent + '.ui-overlaypanel', 
         hideEvent = this.cfg.hideEvent + '.ui-overlaypanel'; 
    
         this.target 
          .off(showEvent + ' ' + hideEvent) 
          .on(showEvent, function(e) { 
           clearTimeout($this.timer); 
    
           $this.timer = setTimeout(function() { 
            $('.ui-overlaypanel').hide(); 
            $this.hidden = false; 
            $this.show(); 
           }, 500); 
          }) 
          .on(hideEvent, function(e) { 
    
           clearTimeout($this.timer); 
    
           $this.timer = setTimeout(function() { 
            // don't hide if hovering overlay 
            if(! $this.jq.is(":hover")) { 
             $this.hide(); 
            } 
           }, 100); 
          }); 
        } 
    
        $this.target.off('keydown.ui-overlaypanel keyup.ui-overlaypanel').on('keydown.ui-overlaypanel', function(e) { 
         var keyCode = $.ui.keyCode, key = e.which; 
    
         if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) { 
          e.preventDefault(); 
         } 
        }) 
        .on('keyup.ui-overlaypanel', function(e) { 
         var keyCode = $.ui.keyCode, key = e.which; 
    
         if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) { 
          $this.toggle(); 
          e.preventDefault(); 
         } 
        }); 
    }; 
    

    私はまた、ユーザーがそれを隠すことなく、オーバーレイの上にマウスを移動することができます余分な機能を追加しました。マウスを動かすと隠れるはずです。

    <p:overlayPanel .... onShow="onShowOverlayPanel(this)" ...> 
    
    function onShowOverlayPanel(ovr) { 
        ovr.jq.on("mouseleave", function(e) { 
         ovr.jq.hide(); 
        }); 
    } 
    

    お楽しみください!