2012-03-08 3 views
1

標準(mojarra)JSFコンポーネントのみを使用し、ネストされた複合体を大量に使用するJSF2(glassfish 3.1では+ EJB3.1 + JPA2)そしてajax-calls。JSF2 + AJAX:スクロールバーの位置を維持するプレーンmojarra

私はすべてのスクロールバーを保存し、ajax呼び出しが発生するたびにその位置を復元します。

私は別のアプローチを試みたが、どれも私には本当に良いようだ、私はいくつかのヒントに行くにはどの方法が必要です。

1)はJavaScript:

は、どちらかのすべてのスクロールバーの位置を読み込み、JavaScriptを追加します。スクロールが発生します(element.onScrollはjavascriptで設定する必要があります。原因はXHTML4では使用できません)、ajax-requestが発生したときです(jsf.ajax.addOnEvent(savePositions))。 スクロールバーの位置を非表示の入力フィールドまたはクッキーに保存します。 ajax応答が発生したときにそれらを復元します(jsf.ajax.addOnEvent(restorePositions))。

コントラクッキーを使用していない場合:AJAX要求が発生する前に

-Theスクロール位置が隠し入力フィールドに格納されている必要があり、そうelement.onScroll-属性は、ここで使用する必要があります。それほど素晴らしいわけではありません。なぜなら、各Ajaxリクエストの前に1回は十分ですが、何度もポジションを保存するからです。

すべての非表示の入力フィールドは、ajaxコールで転送する必要があります。 JSFサイトはいくつかのフォームを使用しているので、自動的にすべてのajaxコールにそれらを追加する方法はないようです。代わりに、すべての要素は、実行属性に追加された隠し入力フィールドを必要とします。

すべてのスクロール可能な要素に1つの隠し入力フィールドが必要です。

コントラクッキーを使用している場合:

型ウェルを、クッキーは、ウェブサイトのために有効にする必要があります。一般的には

コントラ:

-JavaScriptコードが知っているか、スクロールバーを持っているすべての要素、を反復処理する必要があります。

- コンポーネントが再レンダリングされ、onScroll属性セットが必要な場合は、JavaScriptコードを再度実行する必要があります。

2)のJavaScript +コンポジット:

だから、スクロールバーを有する素子、のJSF-IDを指している、複合scrollStateSaveを書き込む考え。コンポジットには隠し入力フィールド(またはクッキー)とjavascriptが含まれていますので、スクロールバーを持つ要素ごとにコンポジットの "インスタンス"を1つ追加するだけです。 javascriptはクロージャを使用して1つのサイトの複数の要素を処理します。

コントラ:複合内部

-TheのJavaScriptは、AJAX呼び出し後の再レンダリングでは実行されません。これには回避策がありますが、私にとっては醜いものに見えます。

3)のMyFacesは、オプションAUTO_SCROLLがあります

それが正確に動作しない方法は?それは非myfaces-jsf-componentsで動作しますか?

4)トマホークはトンを提供しています:自動スクロール行動:

私にとってはOKだろう標準クロサギ科-JSF2・コンポーネント用トマホーク・代替品を使用します。しかし、t:autoscrollのドキュメントは属性 "イベント"を表し、実装は属性 "値"を必要とします。 autoScrolllが動作するようにするには、この属性に何を入れてください。

答えて

3

いいえ、私は解決策2を完了し、それは非常にうまく動作しています。他の開発者にいくつかの助けを与え、ヒントを得るためには、私のソリューションのどの部分が改善できるか、私はコードを投稿します。

コンポジット/WebContent/resources/components/scrollbarStateSaver.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:composite="http://java.sun.com/jsf/composite"> 

<h:body> 

<composite:interface> 
    <composite:attribute name="for"/> 
</composite:interface> 

<composite:implementation> 
    <h:outputScript name="scrollbars.js" library="js"/> 
    <script type="text/javascript"> 
     saveScrollbarPos("#{cc.attrs.for}"); 
    </script> 
</composite:implementation> 
</h:body> 
</html> 

Javascriptを/WebContent/resources/js/scrollbar.js:

function saveScrollbarPos(id) { 
var scrollbarid = id; 

function savePos() { 
    var scrollbar = document.getElementById(scrollbarid); 
    document.cookie = scrollbarid+".scrolltop="+scrollbar.scrollTop+"; path=/"; 
} 

function readCookie(name) { 
    var nameEQ = name + "="; 
    var ca = document.cookie.split(';'); 
    for(var i=0;i < ca.length;i++) { 
     var c = ca[i]; 
     while (c.charAt(0)==' ') c = c.substring(1,c.length); 
     if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); 
    } 
    return null; 
} 

function restorePos() { 
    var scrollbar = document.getElementById(scrollbarid); 
    scrollbar.scrollTop = readCookie(scrollbarid+".scrolltop"); 
} 

function onStatusChange(data) { 
    var status = data.status; 
    if (status == "begin") { 
     savePos(); 
    } 
    else { 
     restorePos(); 
    } 
}; 

var scrollbar = document.getElementById(scrollbarid); 
if (scrollbar != null) { 
    jsf.ajax.addOnEvent(onStatusChange); 
    jsf.ajax.addOnError(onStatusChange); 
} 
}; 

小さな例のXHTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:c="http://java.sun.com/jsf/composite/components"> 

<h:head> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    <title>Title</title> 
</h:head> 

<h:body> 
    <h:form id="form"> 
     <div id="panel" style="overflow:auto;"> 
      long content with ajax-calls in it 
     </div> 
     <c:scrollbarStateSaver for="panel"/> 

     <h:panelGroup id="panel" style="overflow:auto;"> 
      long content with ajax-calls in it 
     </h:panelGroup> 
     <c:scrollbarStateSaver for="form:panel"/> 
    </h:form> 
</h:body> 
</html> 

もちろん、#{cc.parent}経由でjsf-idを計算するようにコンポジットを拡張することもできます。 #{cc.clientId}自体の場合、コンポジットがh:panelGroupと同じレベルに挿入されている場合、コンポジットのfor-attributeはjsf-idsを処理できます。

JavaScriptはおそらくもっとうまく解決することができますが、実際にはこれまでの私の最初のJavaScriptでした。

関連する問題