16

クエリパラメータ値が挿入されるのと同じ方法で、URLのフラグメント(#)からbean(JSF)に値を挿入する方法を探しています。私はBenAlmanのBookmarkablejQueryプラグイン(http://benalman.com/projects/jquery-bbq-plugin/)を使用してURLフラグメントを作成しています。私はprettyFacesのカスタム正規表現パターンが私の問題を解決する方法になることを望んでいましたが、今まで私は成功していませんでした。

http://ocpsoft.com/docs/prettyfaces/snapshot/en-US/html_single/#config.pathparams.regext

ここで私の状況を定義したいと思います。誰かがアイデアを持っているなら、私はそれらを試してみたいと思います。

私は
RichFaces:3.3.3、
Spring:3.0.2.RELEASE、
Hibernate:3.5.3-Final、
JSF:2.0.2-FCS、
PrettyFaces:3.0.1を使用しています。

Webアプリケーションは、次の種類のURLを生成します。ここで、パラメーターはハッシュ(#)の後にリストされます。アイデアは、ajaxベースのブックマーク可能なURLを持つことです。そのため、システムの状態を変更する要素をクリックするたびに、ハッシュが書き換えられた後、値がajaxとURLを介してサーバーに送信されます。ハッシュの後に1〜3個のパラメーターを含めることができ、パラメーターの数はオプションです。

私の目標は、ユーザーがURLを(ハッシュを使用して)ブックマークし、保存されたページに再度アクセスしたときに、ページがシステムに正しい値を挿入し、以前の状態(クエリパラメーターなど)でページを視覚化することです。

以下に、ハッシュの後のすべてのパラメーターをキャッチする正規表現があります。

//URL:   
http://localhost:8080/nymphaea/workspace/#node=b48dd073-145c-4eb6-9ae0-e1d8ba90303c&lod=75e63fcd-f94a-49f5-b0a7-69f34d4e63d7&ln=en

//Regular Expression:    
\#(\w*\=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}))|\&(\w*\=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}))|\&(\w*\=\w{2})

URLフラグメントをサーバー側のロジックに送信するWebサイトがあることを私は知っています。

URLフラグメントからサーバー側のBeanに値を挿入する方法はありますか?

4

5 に答える 5

8

window.onhashchangeこれは、入力フィールドが変更されたときに非同期で送信される非表示のフォームの入力フィールドに入力することで実行できます。

Faceletsページのキックオフの例を次に示します。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>SO question 3475076</title>
        <script>
            window.onload = window.onhashchange = function() {
                var fragment = document.getElementById("processFragment:fragment");
                fragment.value = window.location.hash;
                fragment.onchange();
            }
        </script>
        <style>.hide { display: none; }</style>
    </h:head>
    <h:body>
        <h:form id="processFragment" class="hide">
            <h:inputText id="fragment" value="#{bean.fragment}">
                <f:ajax event="change" execute="@form" listener="#{bean.processFragment}" render=":showFragment" />
            </h:inputText>
        </h:form>
        <p>Change the fragment in the URL. Either manually or by those links:
            <a href="#foo">foo</a>, <a href="#bar">bar</a>, <a href="#baz">baz</a>
        </p>
        <p>Fragment is currently: <h:outputText id="showFragment" value="#{bean.fragment}" /></p>
    </h:body>
</html>

適切なBeanは次のようになります。

package com.stackoverflow.q3475076;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.AjaxBehaviorEvent;

@ManagedBean
@RequestScoped
public class Bean {

    private String fragment;

    public void processFragment(AjaxBehaviorEvent event) {
        // Do your thing here. This example is just printing to stdout.
        System.out.println("Process fragment: " + fragment);
    }

    public String getFragment() {
        return fragment;
    }

    public void setFragment(String fragment) {
        this.fragment = fragment;
    }

}

それで全部です。

このonhashchangeイベントは比較的新しく、古いブラウザではサポートされていないことに注意してください。ブラウザのサポートがない場合(未定義など)、代わりにwindow.location.hashを使用して定期的に確認する必要がありますsetInterval()。上記のコード例は、少なくとも良いキックオフを与えるはずです。少なくともFF3.6とIE8で動作します。

于 2010-08-13T13:34:26.897 に答える
3

構文的に有効なURL/URIからフラグメントを抽出する最も信頼できる方法は次のとおりです。

 URI uri = new URI(someString);
 String fragment = uri.getFragment();

これをBeanに注入する方法は、使用しているサーバー側フレームワーク、およびXMLまたはアノテーションを使用して注入を実行するか、プログラムで実行するかによって異なります。

于 2010-08-13T08:29:04.273 に答える
1

この質問と特に回答を見てください:JSPサーブレットアンカー

  • サーバー側ではフラグメントを確認できません。
  • クライアント側でフラグメントを抽出し、変換して、Ajax経由でサーバーに送信できます。
于 2010-08-13T10:33:04.693 に答える
1

フラグメントはサーバー側からは見ることができず、クライアント側のスクリプトからのみアクセスできます。通常行われる方法は、サーバー側がパラメーター化されていないページを生成し、フラグメントパラメーターに従ってスクリプトによって変更されることです。スクリプトは、クエリパラメータを使用してAJAX要求を行うことができます。この場合、AJAX応答は、パラメータによって制御されるBeanを使用してJSFによって生成されます。

ページ自体をレンダリングするときにサーバー側がフラグメントパラメータにアクセスできるようにしたい場合は、代わりにクエリパラメータとしてパラメータを使用してページをリロードする必要があります。

編集:ページをリロードするには、次のコードを使用できます:

if (window.location.hash != '') {
  var newsearch = window.location.search;
  if(newsearch != '') {
    newsearch += '&';
  }
  newsearch += window.location.hash.match(/#?(.*)/)[1];
  window.location.hash = '';
  window.location.search = newsearch;
}
于 2010-08-13T09:25:25.480 に答える
0

あなたのアイデアと特にBalusCに感謝します(あなたに多くの称賛を送ります)。私の最終的な解決策はわずかな突然変異でした。皆さんと共有したいと思います。

私はrichfaces3.3.3を使用しているので、jsf1.2を使用しているようなものです。したがって、<f:ajax>

従来の状況では、内部リンクを指すhrefが付いたリンクをクリックする必要があります<a id='internalLink'href='#internalLink'>。クリック可能なすべてのアイテムがリンクであるとは限らない、多くのパッケージ済みコンポーネントを使用しています<a>。任意のhtml要素にすることができます。BenAlmanのBookmarkablejQueryプラグイン(http://benalman.com/projects/jquery-bbq-plugin/)を使用すると非常に便利でした。

以下の点に注意してください。onclickはプログラムでフラグメントの値をキー/値として設定でき、次のコードでは古い値を新しい値に置き換えますjQuery.bbq.pushState(state,2)(または単に古い値の後ろに追加することもできますjQuery.bbq.pushState(state))。

私の場合、ws->md->ndは階層データであり、そのうちの1つがあれば十分であり、その親はサーバー上で計算されるため、親の値を子の値に置き換えます。

<ui:repeat value="#{workspaceController.modulesForWorkspace}" var="item">  
 <a4j:commandLink onclick="var state = {}; state['md'] = '#{item.uuid}';
  jQuery.bbq.pushState( state, 2 );"    
  action="#{workspaceController.setSelectedModule}"
  reRender="localesList" 
  oncomplete="selectNavigationElement(this.parentNode>
    <f:param name="selectedModule" value="#{item.uuid}"/>
  </a4j:commandLink>
</ui:repeat>

リッチフェイスでは、これはパラメーターを使用してブラウザーからセッターメソッドを呼び出すための優れた方法です。これは、5つのパラメーターを持つJSメソッドとして扱われ、値がサーバーに渡されることに注意してくださいsendURLFragment(これは非常に優れています)。

<h:form id="processFragment" prependId="false" style="display: none">
  <h:inputText id="fragment" value="#{workspaceController.selectedWorkspace}">                                  
   <a4j:support event="onchange"/>
  </h:inputText>    
<a4j:jsFunction name="sendURLFragment" reRender="workspaces">
 <a4j:actionparam name="ws" assignTo="#{workspaceController.selectedWorkspace}"/>
 <a4j:actionparam name="md" assignTo="#{workspaceController.selectedModule}"/>
 <a4j:actionparam name="nd" assignTo="#{workspaceController.selectedContentNode}"/>
 <a4j:actionparam name="ld" assignTo="#{workspaceController.selectedLOD}"/>
 <a4j:actionparam name="ln" assignTo="#{workspaceController.contentNodeTreeLocale}"  
 converter="localeConverter"/>                              
</a4j:jsFunction>
</h:form>

新しいURLをコピーして貼り付け、ページを読み込むときに、この作業を行います。

window.onload = function(){
if(window.location.hash != ""){  
    //Parse the fragment (hash) from a URL, deserializing it into an object            
    var deparamObj = jQuery.deparam.fragment();
    var ws= '', md= '', nd= '', ld= '', ln = '';            
    jQuery.each(deparamObj, function(key, value) {              
        switch(key){
            case 'ws':
                ws = value;
                break;
            case 'md':
                md = value;
                break;
            case 'nd':
                nd = value;
                break;
            case 'ld':
                ld = value;
                break;
            case 'ln':
                ln = value;
                break;
            default:
                break;          
        }

    });
    sendURLFragment(ws,md,nd,ld,ln);
}   };  
于 2010-08-20T09:47:11.517 に答える