2010-08-13 2 views
16

같은 방식으로 쿼리 매개 변수와 마찬가지로 URL의 프래그먼트 (#) 값을 bean (JSF)에 삽입하는 방법을 찾고 있습니다. 값이 주입됩니다. Ben Alman의 북마크 가능한 jQuery 플러그인 (http://benalman.com/projects/jquery-bbq-plugin/)을 사용하여 URL 조각을 만듭니다. prettyFaces의 Custom regex 패턴이 내 문제를 해결할 수있는 방법이 될 수 있기를 기대했지만 지금까지는 실패했습니다.URL에서 단편 (해시)을 가져 와서 그 값을 빈에 삽입하십시오.

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

여기 내 상황을 정의하고 하나가 생각이 있다면, 내가 을 시도 싶어요 싶습니다. 3.3.3,
봄 : 3.0.2.RELEASE,
최대 절전 모드 : 3.5.3-최종,
JSF : 2.0.2-FCS,
PrettyFaces

나는
RichFaces을 사용하고 있습니다 : 3.0.1

웹 응용 프로그램은 해시 (#) 뒤에 매개 변수가 나열된 URL 유형을 생성합니다. 아이디어는 ajax를 기반으로합니다. Bookmarkable URL. 따라서 시스템의 상태를 변경하는 요소를 클릭 할 때마다 값은 해시가 다시 작성된 후 ajax 및 URL을 통해 서버로 전송됩니다. 해시 후 1 ~ 3 개의 매개 변수가있을 수 있으며 매개 변수의 수는 선택 사항입니다. 사용자가 (해시) URL을 북마크 및 가 저장된 페이지를 다시 방문보다 페이지가 시스템에 올바른 값을 를 주입해야하며, 같은 (이전 상태로 질의 -이 페이지를 시각화 할 때

내 목표이며, 매개 변수).

아래에는 해시 후 모든 매개 변수 을 catch하는 정규식이 있습니다.

//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 조각을 보내 서버 쪽 콩에 URL 조각?

답변

8

window.onhashchange의 도움으로이 작업을 수행 할 수 있습니다.이 필드는 입력 필드가 변경 될 때 비동기 적으로 제출되는 숨겨진 양식의 입력 필드를 채 웁니다.

다음은 Facelets의 페이지의 킥오프 예제 : 전부

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; 
    } 

} 

:

<!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> 

여기에 해당하는 콩의 모양 방법입니다.

onhashchange 이벤트는 비교적 새롭고 구형 브라우저에서 지원되지 않습니다. 브라우저 지원이 제공되지 않는 경우 (정의되지 않은 경우 등) setInterval()을 사용하여 간격을두고 window.location.hash을 확인하고 싶습니다. 위 코드 예제는 적어도 좋은 시작을 제공해야합니다. 적어도 FF3.6과 IE8에서 작동합니다.

+1

와우, 그건 정말 멋진데, 공유 주셔서 감사합니다. 이제 JSF 2를 살펴볼 필요가 있습니다. – clacke

+1

IE6/7 브라우저의 경우 jQuery Hashchange 플러그인을 고려하십시오. http://stackoverflow.com/questions/5911899/ie6-7-back-forward-button-dont-change-window-location-hash도 참조하십시오. – BalusC

3

구문 적으로 유효한 URL/URI에서 단편을 추출하는 가장 신뢰할 수있는 방법은 다음과 같습니다.

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

어떻게 당신은 당신이 사용하고있는 서버 측 프레임 워크에 의존하는 콩이 점을 주입, 당신은 XML 또는 주석을 사용하여 주입하고, 또는 programmaticaly을하고 있습니다 여부.

+0

의견을 보내 주셔서 감사합니다. 페이지 리로드 (GET)가 있고 getFragment()보다 URL을 잡는 방법을 찾고 있는데, 올바르게 파싱하여 값을 가져오고 해당 변수를 설정하는 것입니다. – tchoesang

+0

이 메서드는 존재하지만 브라우저는 조각 정보를 서버로 보내지 않습니다. HTTP 트래픽을 로깅하여 볼 수 있습니다. – pcjuzer

+1

기술적으로는 올바르지 만이 답변은 실질적이고 근본적으로 잘못되었습니다. webbrowser [** will not **] (http://en.wikipedia.org/wiki/Fragment_identifier#Processing)에 의해 설정된 조각이 웹 서버에 도착합니다. – BalusC

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; 
} 
+0

페이지 재로드시 프래그먼트 매개 변수가 쿼리 매개 변수로 변환되는 페이스 북에서이 기법을 사용하는 것을 보았습니다. 나는이 아이디어를 시험해보고 싶다. 페이지를 다시로드 할 때 조각을 포함하는 URL을 쿼리 매개 변수가있는 URL로 변환 할 수 있습니까? 즉 http://url.com/#a=1&b=2 -> http://url.com/?a=1&b=2 – tchoesang

+0

예제 코드가 추가되었습니다. 그러나, 대신 매개 변수를 구문 분석하고 북마크 된 상태를 재구성하기위한 적절한 AJAX 요청을 작성하는 코드를 작성하는 것이 좋습니다. 또한, 내 코드 예제는 사용자의 요구에 너무 간단합니다. 예를 들어 확인하지 않습니다. 따라서 사용자가 주위를 클릭하기 시작하고 조각을 다시 추가하기 시작할 때 문제가 발생합니다. – clacke

+0

코드 예제가 번거 롭습니다. 단지'window.location.hash'는 당신에게 이미 조각을주고'window.location.search' 쿼리 문자열을줍니다. ['window.location'] (https://developer.mozilla.org/en/window.location) 문서를 읽으십시오. – BalusC

1

시계이 질문에 특히 답변 : JSP Servlet anchor

  • 조각이 서버 측에서 볼 수없는 페이지를 다시로드하려면이 코드를 사용할 수 있습니다.
  • 클라이언트 쪽에서 조각을 추출하고 변환하여 Ajax를 통해 서버 에게 보낼 수 있습니다.
+0

훌륭한 참조. 특히 [ajax 패턴] (http://ajaxpatterns.org/Unique_URLs) 링크. – clacke

0

귀하의 아이디어에 대해 대단히 감사합니다. & 특별히 BalusC (많은 칭호). 내 마지막 해결책은 약간의 돌연변이 였고 나는 너와 함께 나누고 싶다. 내가 richfaces 3.3.3을 사용하고 있기 때문에

, 그것은 기존의 상황에 따라서 더 <f:ajax>

을 JSF1.2을 사용하지 않는 것처럼, 당신은 내부 연결 <a id='internalLink'href='#internalLink'>에 HREF 가리키는 링크를 클릭 할 것으로 예상된다 . 나는 모든 클릭 가능한 항목이 링크 <a>이 아닌 많은 미리 포장 된 구성 요소를 사용하고 있습니다. 모든 html 요소가 될 수 있습니다. Ben Alman의 북마크 가능한 jQuery 플러그인 (http://benalman.com/projects/jquery-bbq-plugin/)을 사용하는 것이 매우 유용했습니다.

아래 코드에서 keyclature 값을 프로그래밍 방식으로 설정할 수 있으며 다음 코드에서 이전 값을 새 값으로 바꿉니다. 값 jQuery.bbq.pushState(state,2) (또는 단순히 이전 값인 jQuery.bbq.pushState(state) 뒤에 추가했을 수 있습니다.)

필자의 경우 ws->md->nd은 계층 적 데이터로, 그 중 하나를 가질 정도로 충분하고 부모가 서버에서 계산되므로 상위 값을 하위 값으로 바꿉니다.

<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> 

부자면에서 이것은 매개 변수가있는 브라우저에서 setter 메소드를 호출하는 멋진 방법입니다. sendURLFragment은 5 개의 매개 변수로 JS 메서드로 처리되며 값은 서버로 전달됩니다 (매우 멋지다).

<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); 
} }; 
관련 문제