diff options
author | elmot <elmot@vaadin.com> | 2015-09-25 16:40:44 +0300 |
---|---|---|
committer | elmot <elmot@vaadin.com> | 2015-09-25 16:40:44 +0300 |
commit | a1b265c318dbda4a213cec930785b81e4c0f7d2b (patch) | |
tree | b149daf5a4f50b4f6446c906047cf86495fe0433 /documentation/advanced/advanced-urifu.asciidoc | |
parent | b9743a48a1bd0394f19c54ee938c6395a80f3cd8 (diff) | |
download | vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.tar.gz vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.zip |
Framework documentation IN
Change-Id: I767477c1fc3745f9e1f58075fe30c9ac8da63581
Diffstat (limited to 'documentation/advanced/advanced-urifu.asciidoc')
-rw-r--r-- | documentation/advanced/advanced-urifu.asciidoc | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/documentation/advanced/advanced-urifu.asciidoc b/documentation/advanced/advanced-urifu.asciidoc new file mode 100644 index 0000000000..709d6c4bd3 --- /dev/null +++ b/documentation/advanced/advanced-urifu.asciidoc @@ -0,0 +1,191 @@ +--- +title: Managing URI Fragments +order: 11 +layout: page +--- + +[[advanced.urifu]] += Managing URI Fragments + +A major issue in AJAX applications is that as they run in a single web page, +bookmarking the application URL (or more generally the __URI__) can only +bookmark the application, not an application state. This is a problem for many +applications, such as product catalogs and discussion forums, in which it would +be good to provide links to specific products or messages. Consequently, as +browsers remember the browsing history by URI, the history and the +[guibutton]#Back# button do not normally work. The solution is to use the +__fragment identifier__ part of the URI, which is separated from the primary +part (address + path + optional query parameters) of the URI with the hash (#) +character. For example: + + +---- +http://example.com/path#myfragment +---- + +The exact syntax of the fragment identifier part is defined in RFC 3986 +(Internet standard STD 66) that defines the URI syntax. A fragment may only +contain the regular URI __path characters__ (see the standard) and additionally +the slash and the question mark. + +Vaadin offers two ways to enable the use of URI fragments: the high-level +[classname]#Navigator# utility described in +<<dummy/../../../framework/advanced/advanced-navigator#advanced.navigator,"Navigating +in an Application">> and the low-level API described here. + +[[advanced.urifu.setting]] +== Setting the URI Fragment + +You can set the current fragment identifier with the +[methodname]#setUriFragment()# method in the [classname]#Page# object. + + +[source, java] +---- +Page.getCurrent().setUriFragment("mars"); +---- + +Setting the URI fragment causes an [interfacename]#UriFragmentChangeEvent#, +which is processed in the same server request. As with UI rendering, the URI +fragment is changed in the browser after the currently processed server request +returns the response. + +Prefixing the fragment identifier with an exclamation mark enables the web +crawler support described in <<advanced.urifu.crawling>>. + + +[[advanced.urifu.reading]] +== Reading the URI Fragment + +The current URI fragment can be acquired with the [methodname]#getUriFragment()# +method from the current [classname]#Page# object. The fragment is known when the +[methodname]#init()# method of the UI is called. + + +[source, java] +---- +// Read initial URI fragment to create UI content +String fragment = getPage().getUriFragment(); +enter(fragment); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.urifragment.basic[on-line example, window="_blank"]. + +To enable reusing the same code when the URI fragment is changed, as described +next, it is usually best to build the relevant part of the UI in a separate +method. In the above example, we called an [methodname]#enter()# method, in a +way that is similar to handling view changes with [classname]#Navigator#. + + +[[advanced.urifu.listening]] +== Listening for URI Fragment Changes + +After the UI has been initialized, changes in the URI fragment can be handled +with a [interfacename]#UriFragmentChangeListener#. The listeners are called when +the URI fragment changes, but not when the UI is initialized, where the current +fragment is available from the page object as described earlier. + +For example, we could define the listener as follows in the [methodname]#init()# +method of a UI class: + + +[source, java] +---- +public class MyUI extends UI { + @Override + protected void init(VaadinRequest request) { + getPage().addUriFragmentChangedListener( + new UriFragmentChangedListener() { + public void uriFragmentChanged( + UriFragmentChangedEvent source) { + enter(source.getUriFragment()); + } + }); + + // Read the initial URI fragment + enter(getPage().getUriFragment()); + } + + void enter(String fragment) { + ... initialize the UI ... + } +} +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.urifragment.basic[on-line example, window="_blank"]. + +<<figure.advanced.urifu>> shows an application that allows specifying the menu +selection with a URI fragment and correspondingly sets the fragment when the +user selects a menu item. + +[[figure.advanced.urifu]] +.Application State Management with URI Fragment Utility +image::img/urifu-1.png[] + + +[[advanced.urifu.crawling]] +== Supporting Web Crawling + +Stateful AJAX applications can not normally be crawled by a search engine, as +they run in a single page and a crawler can not navigate the states even if URI +fragments are enabled. The Google search engine and crawler +link:http://googlewebmastercentral.blogspot.fi/2009/10/proposal-for-making-ajax-crawlable.html[support +a convention] where the fragment identifiers are prefixed with exclamation mark, +such as [literal]#++#!myfragment++#. The servlet needs to have a separate +searchable content page accessible with the same URL, but with a +[literal]#++_escaped_fragment_++# parameter. For example, for +[literal]#++/myapp/myui#!myfragment++# it would be +[literal]#++/myapp/myui?_escaped_fragment_=myfragment++#. + +You can provide the crawl content by overriding the [methodname]#service()# +method in a custom servlet class. For regular requests, you should call the +super implementation in the [classname]#VaadinServlet# class. + + +[source, java] +---- +public class MyCustomServlet extends VaadinServlet + @Override + protected void service(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + String fragment = request + .getParameter("_escaped_fragment_"); + if (fragment != null) { + response.setContentType("text/html"); + Writer writer = response.getWriter(); + writer.append("<html><body>"+ + "<p>Here is some crawlable "+ + "content about " + fragment + "</p>"); + + // A list of all crawlable pages + String items[] = {"mercury", "venus", + "earth", "mars"}; + writer.append("<p>Index of all content:</p><ul>"); + for (String item: items) { + String url = request.getContextPath() + + request.getServletPath() + + request.getPathInfo() + "#!" + item; + writer.append("<li><a href='" + url + "'>" + + item + "</a></li>"); + } + writer.append("</ul></body>"); + } else + super.service(request, response); + } +} +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.urifragment.basic[on-line example, window="_blank"]. + +The crawlable content does not need to be human readable. It can provide an +index of links to other application states, as we did in the example above. The +links should use the " [literal]#++#!++#" notation, but can not be relative to +avoid having the [literal]#++_escaped_fragment_++# parameter. + +You need to use the custom servlet class in the [filename]#web.xml# deployment +descriptor instead of the normal [classname]#VaadinServlet# class, as described +in +<<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using +a web.xml Deployment Descriptor">>. + + + + |