I write desktop apps!
So how do I choose?
Html 5 Web App → Native App
hideURLBar: function() {
//hide the url bar on mobile devices
setTimeout(scrollTo, 100, 0, 1)
}
/* portrait screen width */
@media screen and (max-width: 480px) {
.portrait {
}
.landscape {
display:none;
}
}
/* landscape/desktop device widths */
@media screen and (min-width: 481px) {
.portrait {
display:none;
}
.landscape {
}
}
.page {
...
-webkit-transform: translate3d(0, 0, 0);
}
<section>
<h2>The plan</h2>
<ul>
<li>Why the Mobile Web?</li>
<li>Why JSF?</li>
<li>Why RichFaces?</li>
</ul>
</section>
Standardized as part of Java EE
Ajax is baked-in
to the framework
Component-oriented
programming model
Facelets:
A powerful templating mechanism
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5
public class UAgentInfo implements Serializable {
...
public void initDeviceScan() {
this.isIphone = detectIphoneOrIpod();
this.isAndroidPhone = detectAndroidPhone();
this.isTierTablet = detectTierTablet();
this.isTierIphone = detectTierIphone();
this.isTierRichCss = detectTierRichCss();
this.isTierGenericMobile = detectTierOtherPhones();
}
...
@Model
public class UserAgent {
private UAgentInfo uAgentInfo;
@PostConstruct
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)
context.getExternalContext().getRequest();
String userAgentStr = request.getHeader("user-agent");
String httpAccept = request.getHeader("Accept");
uAgentInfo = new UAgentInfo(userAgentStr, httpAccept);
}
public Configuration getConfiguration(final ServletContext context) {
return ConfigurationBuilder.begin()
.defineRule()
.when(Direction.isInbound()
.and(Path.matches("/").or(Path.matches("/index.jsf")))
.and(UserAgent.isMobile())
).perform(Forward.to("/mobile/"));
}
For mobile JSF apps
Facelet Source
<a4j:push address="pushCdi"
ondataavailable="jQuery('<li/>').text(event.rf.data)
.prependTo('#messages')" />
<ul id="messages" />
Java Source
@Inject
@Push(topic = "pushCdi")
Event<String> pushEvent;
public void sendMessage() {
pushEvent.fire("My Message");
}
JBW 2011 Keynote
<a4j:jsFunction name="updateName" render="showname">
<a4j:param name="name" assignTo="#{functionBean.text}" />
</a4j:jsFunction>
A collection of lightweight CSS and Javascript assets
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition template="/WEB-INF/templates/mobile.xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<ui:define name="content">
<h:outputStylesheet name="mobile.css" library="css"/>
<h:outputScript>
//initialize mobile RichFaces with slidfast
slidfast({
defaultPageID:'home-page',
callback: 'handleHashChange',
backButtonID: 'back-button'
});
</h:outputScript>
<div id="browser">
<header>
<div>
<div id="back-button" class="hide-button">Home</div>
<div id="info-button" class="right-header-button info-link">
<a href="#about">i</a>
</div>
<p>Mobile JSF</p>
</div>
</header>
<h:form id="mobileForm">
<div id="page-container">
<div id="home-page" class="page stage-left">
<ui:include src="/mobile/home.xhtml"/>
</div>
<div id="new" class="page stage-right">
<ui:include src="/mobile/new.xhtml"/>
</div>
<div id="list" class="page stage-right">
<ui:include src="/mobile/list.xhtml"/>
</div>
<div id="about" class="page stage-right">
<ui:include src="/mobile/about.xhtml"/>
</div>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>
<h:form id="mobileForm">
<div id="page-container">
<div id="home-page" class="page stage-left">
<ui:include src="/mobile/home.xhtml"/>
</div>
<div id="new" class="page stage-right">
<ui:include src="/mobile/new.xhtml"/>
</div>
<div id="list" class="page stage-right">
<ui:include src="/mobile/list.xhtml"/>
</div>
<div id="about" class="page stage-right">
<ui:include src="/mobile/about.xhtml"/>
</div>
</div>
</h:form>
Directly, using html links
<a href="#about">i</a>
Using javascript
<rich:panelMenuItem label="Add Member"
onclick="location.hash='new'"
mode="client" />
<div id="page-container">
<div id="home-page" class="page stage-left">
<ui:include src="/mobile/home.xhtml"/>
</div>
<div id="app-page" class="page stage-right">
<ui:include src="#{pageBean.page}"/>
</div>
</div>
<h:inputHidden id="page" value="#{pageBean.location}" />
<h:outputScript >
var handleHashChange = function (page) {
var hiddenInput = 'mobileForm:page';
$(document.getElementById(hiddenInput)).val(page);
var options = {
execute: hiddenInput,
render : '@form',
onevent : function(event) {
if(event.status == 'success') {
slidfast.core.slideTo('app-page');
}
}
}
jsf.ajax.request(hiddenInput, null, options);
}
</h:outputScript>
<h:outputScript target="head">
<a4j:jsFunction name="handleHashChange"
render="@form"
oncomplete="slidfast.core.slideTo('app-page')">
<a4j:param name="page" assignTo="#{pageBean.location}"/>
</a4j:jsFunction>
<slidfast:pageChanger activePage="#{pageBean.location}" render="app-page" />
<slidfast:page id="app-page" stage="right">
<ui:include src="#{pageBean.page}"/>
</slidfast:page>
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition template="/WEB-INF/templates/mobile.xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:slidfast="http://richfaces.org/slidfast">
<ui:define name="content">
<h:outputStylesheet name="app.css" library="css"/>
<h:outputStylesheet name="mobile.css" library="css"/>
<div id="browser">
<header>
<div>
<div id="back-button" class="hide-button">Home</div>
<div id="info-button" class="right-header-button info-link">
<a href="#about">i</a>
</div>
<p>Richfaces Mobile</p>
</div>
</header>
<h:form id="mobileForm">
<slidfast:pageChanger id="pageChanger" activePage="#{pageBean.location}" render="app-page" />
<slidfast:pageContainer id="pageContainer">
<slidfast:page id="home-page" stage="left">
<ui:include src="/mobile/home.xhtml"/>
</slidfast:page>
<slidfast:page id="app-page" stage="right">
<ui:include src="#{pageBean.page}"/>
</slidfast:page>
</slidfast:pageContainer>
</h:form>
</div>
<h:outputStylesheet library="org.richfaces" name="rf-mobile-skin.css" />
</ui:define>
</ui:composition>
Source code:
Articles:
Later today: