2012-03-08 80 views
1

我有一個JSF2(+ glassfish 3.1上的+ EJB3.1 + JPA2 +)更復雜的webapp,它只使用標準(mojarra)JSF組件,並大量使用嵌套複合材料和ajax調用。JSF2 + AJAX:保持滾動條的位置,簡單的mojarra

我希望我的所有滾動條在發生ajax調用時保存並恢復其位置。

我嘗試了不同的方法,但沒有一個似乎真的對我很好,所以我需要一些提示哪個方向走:

1)的JavaScript:

添加一個JavaScript讀取所有的滾動條位置既可以當發生滾動(element.onScroll必須由javascript設置,導致此屬性在XHTML4中不可用)或發生ajax請求時(jsf.ajax.addOnEvent(savePositions))。 將滾動條的位置保存在隱藏的輸入字段或cookie中。 當發生ajax響應時(jsf.ajax.addOnEvent(restorePositions))還原它們。

反政府如果不使用Cookie:

-The滾動位置必須被存儲在隱藏的輸入字段中的AJAX請求發生之前,所以element.onScroll-屬性必須在這裏使用。不是很好,因爲它會多次保存位置,雖然在每個ajax請求前一次就足夠了。

- 必須在ajax調用中傳輸所有隱藏的輸入字段。由於JSF網站使用多種形式,似乎沒有辦法自動將它們添加到所有ajax調用中。相反,每個元素都需要添加到execute-attribute的隱藏輸入字段。

- 每個可滾動元素都需要一個隱藏的輸入字段。

魂鬥羅,如果使用cookie:

- 嗯,餅乾需要爲網站啓用。

魂鬥羅一般:

-JavaScript代碼必須知道或者通過所有的元素,其中有滾動條迭代。

-JavaScript代碼必須再次執行,如果組件被重新渲染並且需要onScroll屬性集。

2)的JavaScript +複合:

所以我想寫入的複合sc​​rollStateSave,它指向元件,其具有滾動條的JSF-ID的。該組合包含隱藏的輸入字段(或cookie)和JavaScript並處理所有內容,所以我只需要爲每個元素添加一個「實例」,該元素具有滾動條。 JavaScript使用閉包爲一個網站上的多個元素工作。

魂鬥羅:一個AJAX調用後

-The複合內部JavaScript是不是在執行重新渲染。這有些解決方法,但它們看起來很醜。

3)MyFaces的有一個選項AUTO_SCROLL:

它是如何工作完全?它是否適用於非myfaces-jsf-components?

4)戰斧提供T:自動滾動行爲:

使用戰斧,替代標準,鑽嘴魚科,JSF2組件將是確定的我。但是t:autoscroll的文檔提到屬性「事件」,而實現需要屬性「值」。我應該在這個屬性中使t: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-id。

JavaScript也可能更好地解決,但它實際上是我有史以來第一個JavaScript。