Example code will be posted soon.
Well in a few weeks I'm going to submit my app, I think apple will be
hardpressed to consider it a webclipping app. I would say 50% of the
code is web dependent and the other 50 objective c. Without giving to
much away, because I'm also doing a position paper for possible
submission to Javaone. It uses a lot of phone features including
location and gps. It uses a backend server written in java to display
images from x number of upnp or bonjoir servers on your network.
It doesn't use iui or phoneGap, It uses a combination of a java
framework called icefaces tightly integrated with dashcode for the web
portion. It uses a server push technology. Clicking on the web tab
opens 1-x uiwebviews, each webview represents an independent session.
The backend uses the icefaces equivalent of comet-d to allow all the
session to "talk" to each other. That is changing a value in one
session directly affects all the other sessions. Lets say you had a
geocaching application (which is something else I am working on) and
the iphone ui has 4 open scaleable windows to your web application.
Than each window could have a different user view of the map, say as a
scatterPlot, a hyperbolic tree and an actual map showing gelogical
data. Lets say you wanted to do gecaching, than using the location and
gps functions on the phone the web application could update each of
the 4 independent views realtime. Once more as your location changes
the application could update all users who are connected to that
application as well. At the same time they can open a chat window and
talk with each other.
Meantime the same data can be pushed to a static html location on the
phone. (yes this is possible) which can be checked perodically via
objective-c, this static info can accessed via the sdk and the respose used to issue a
NSURLRequest , thus updating both gps info and the selection pick
boxes on the screen.
By my count to try to do this with safari would require 4 browser
windows simultaneously pointing at the same location, but the app
needs to know the session ids for this to work something your not
going to be able to do with safari alone.
This is just a quick capsule of the functionality, If apple calls this
a web clipping app than they need to hire testers who actually know
something about networking applications.
Also most of the above is impossible to do with iui and maybe phonegap but I need to explore that one more.
We will use this page to track progress with the icefaces/dashcode projects .
The deliverables from this project will be Tagalong and Artshow proof of concepts. and a template for dashcode that creates an icefaces project ready for import into eclipse.
-
Changes from earlier versions
-
Artshow
-
Use of UPNP mediaservers
-
bonjoir (dns-sd)
-
Developed as a plugin for a native Objective-c application. (displayed in a uiWebView
-
Native phone features , location , local saving of photos
-
Tagalong
-
Use of UPNP mediaservers
-
Bonjoir (dns-sd) both local and wideArea
-
Developed as a plugin for native Objective-c application (displayed in a uiWebView
-
Native location features
-
Deployment
-
Arshow
-
WebApplication
-
native via itunes app store.
-
Tagalong
-
Webapplication
-
possible deployment as a native application. (may be outside app store guidelines for acceptance)
-
Icefaces template
-
SourceForge
Steps for building a dashcode / icefaces application (detail will be added)
-
Create the UI in dashCode
-
Create The icefaces components (see the tutorial elsewhere on this site)
-
Add all the js files in the parts folder to the build script and run the script to create a compressed parts file
-
Add the following elements under icesoft.faces.webapps
-
Parts.js (compressed)
-
main.js
-
Any css files and images and license txt files
-
Create the backing beans and any other classes in your ide as needed.
-
code the xhtml file(s) and include as many listviewData components as needed.
Below is an annotated listing of iphoneHelper.java (builds the ui for tagalong)
package com.icesoft.faces.component.listviewdata;
import java.io.IOException;
import com.icesoft.faces.context.DOMContext;
import com.icesoft.faces.context.effects.JavascriptContext;
import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer;
import com.icesoft.faces.component.CSS_DEFAULT;
import com.icesoft.faces.renderkit.dom_html_basic.HTML;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
public class IphoneHelperRenderer extends DomBasicRenderer {
private static final String DIV_ID = "div0";
private static final Log log = LogFactory
.getLog(IphoneHelperRenderer.class);
private static final String SPACER_IMG = "/xmlhttp/css-iphone/xp/css-images/spacer.gif";
private IphoneHelper iphoneHelper;
private boolean firstElement;
public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) {
DOMContext domContext = DOMContext.attachDOMContext(facesContext,
uiComponent);
try {
// might be the issue line 36
if (!domContext.isInitialized()) {
Element root = (Element) domContext.getCursorParent();
Element browserDiv = domContext.createElement(HTML.DIV_ELEM);
browserDiv.setAttribute(HTML.ID_ATTR, "browser");
root.appendChild(browserDiv);
/*
* <div id="browser"> <div id="header"> <div id="toolBar"> <div
* id="btnEnvironment"></div> <div id="btnLocations"></div> <div
* id="btnServers"></div> </div> <div id="back_button"
* class="back_button_template dashcode-header-backbutton"
* ></div> </div>
*/
Element headerDiv = domContext.createElement(HTML.DIV_ELEM);
headerDiv.setAttribute(HTML.ID_ATTR, "header");
Element toolBarDiv = domContext.createElement(HTML.DIV_ELEM);
toolBarDiv.setAttribute(HTML.ID_ATTR, "toolBar");
Element btnEnvironmentDiv = domContext
.createElement(HTML.DIV_ELEM);
btnEnvironmentDiv.setAttribute(HTML.ID_ATTR, "btnEnvironment");
toolBarDiv.appendChild(btnEnvironmentDiv);
Element btnLocationsDiv = domContext
.createElement(HTML.DIV_ELEM);
btnLocationsDiv.setAttribute(HTML.ID_ATTR, "btnLocations");
toolBarDiv.appendChild(btnLocationsDiv);
Element btnServersDiv = domContext.createElement(HTML.DIV_ELEM);
btnServersDiv.setAttribute(HTML.ID_ATTR, "btnServers");
toolBarDiv.appendChild(btnServersDiv);
headerDiv.appendChild(toolBarDiv);
Element backButton = domContext.createElement(HTML.DIV_ELEM);
backButton.setAttribute(HTML.ID_ATTR, "back_button");
backButton.setAttribute(HTML.CLASS_ATTR,
"back_button_template dashcode-header-backbutton");
/* disable the backbutton for now */
backButton.setAttribute(HTML.STYLE_ATTR, "display:none");
headerDiv.appendChild(backButton);
browserDiv.appendChild(headerDiv);
/*
* <div id="stackLayout"> <div id="listLevel0"> <ul id="list">
* <li id="listRowTemplate" class="listRowTemplate_template"
* style="border-top-width: 0px; "> <div id="serverTitle"
* class="serverTitle_template"></div> <div id="arrow"
* class="arrow_template"> </div> </li> </ul> </div>
*/
Element stackLayout = domContext.createElement(HTML.DIV_ELEM);
stackLayout.setAttribute(HTML.ID_ATTR, "stackLayout");
browserDiv.appendChild(stackLayout);
Element listLevel0 = domContext.createElement(HTML.DIV_ELEM);
listLevel0.setAttribute(HTML.ID_ATTR, "listLevel0");
stackLayout.appendChild(listLevel0);
Element imagePanelDiv = domContext.createElement(HTML.DIV_ELEM);
Element listUL0 = domContext.createElement(HTML.UL_ELEM);
listUL0.setAttribute(HTML.ID_ATTR, "list");
listLevel0.appendChild(listUL0);
Element li0 = domContext.createElement(HTML.LI_ELEM);
li0.setAttribute(HTML.ID_ATTR, "listRowTemplate");
li0.setAttribute(HTML.CLASS_ATTR, "listRowTemplate_template");
li0.setAttribute(HTML.STYLE_ATTR, "border-top-width: 0px;");
Element titleDiv0 = domContext.createElement(HTML.DIV_ELEM);
titleDiv0.setAttribute(HTML.ID_ATTR, "serverTitle");
titleDiv0.setAttribute(HTML.CLASS_ATTR, "serverTitle_template");
li0.appendChild(titleDiv0);
Element arrowDiv0 = domContext.createElement(HTML.DIV_ELEM);
arrowDiv0.setAttribute(HTML.ID_ATTR, "arrow");
arrowDiv0.setAttribute(HTML.CLASS_ATTR, "arrow_template");
li0.appendChild(arrowDiv0);
listUL0.appendChild(li0);
/*
* <div id="listLevel"> <ul id="list2"> <li
* id="listRowTemplate2" class="listRowTemplate2_template"
* style="border-top-width: 0px; "> <div id="rowTitle"
* class="rowTitle_template"></div> <div id="arrow1"
* class="arrow1_template"> </div> </li> </ul>
*/
Element listLevel = domContext.createElement(HTML.DIV_ELEM);
listLevel.setAttribute(HTML.ID_ATTR, "listLevel");
stackLayout.appendChild(listLevel);
Element listUL = domContext.createElement(HTML.UL_ELEM);
listUL.setAttribute(HTML.ID_ATTR, "list2");
listLevel.appendChild(listUL);
Element li = domContext.createElement(HTML.LI_ELEM);
li.setAttribute(HTML.ID_ATTR, "listRowTemplate2");
li.setAttribute(HTML.CLASS_ATTR, "listRowTemplate2_template");
Element titleDiv = domContext.createElement(HTML.DIV_ELEM);
titleDiv.setAttribute(HTML.ID_ATTR, "rowTitle");
titleDiv.setAttribute(HTML.CLASS_ATTR, "rowTitle_template");
li.appendChild(titleDiv);
Element arrowDiv = domContext.createElement(HTML.DIV_ELEM);
arrowDiv.setAttribute(HTML.ID_ATTR, "arrow1");
arrowDiv.setAttribute(HTML.CLASS_ATTR, "arrow1_template");
li.appendChild(arrowDiv);
listUL.appendChild(li);
/*
* </div><div id="listLevel3"> <ul id="list1"> <li
* id="listRowTemplate1" class="listRowTemplate1_template"> <div
* id="locationTitle" class="locationTitle_template"></div> <div
* id="arrow2" class="arrow2_template"> </div> </li> </ul>
*/
Element listLevel3 = domContext.createElement(HTML.DIV_ELEM);
listLevel3.setAttribute(HTML.ID_ATTR, "listLevel3");
stackLayout.appendChild(listLevel3);
Element listUL3 = domContext.createElement(HTML.UL_ELEM);
listUL3.setAttribute(HTML.ID_ATTR, "list1");
listLevel3.appendChild(listUL3);
Element li3 = domContext.createElement(HTML.LI_ELEM);
li3.setAttribute(HTML.ID_ATTR, "listRowTemplate1");
li3.setAttribute(HTML.CLASS_ATTR, "listRowTemplate1_template");
Element title3Div = domContext.createElement(HTML.DIV_ELEM);
title3Div.setAttribute(HTML.ID_ATTR, "locationTitle");
title3Div.setAttribute(HTML.CLASS_ATTR,
"locationTitle_template");
li3.appendChild(title3Div);
Element arrow3Div = domContext.createElement(HTML.DIV_ELEM);
arrowDiv.setAttribute(HTML.ID_ATTR, "arrow2");
arrowDiv.setAttribute(HTML.CLASS_ATTR, "arrow2_template");
li3.appendChild(arrow3Div);
listUL3.appendChild(li3);
/*
* </div><div id="detailLevel"> <div id="detailBox"> <div
* id="topRectangleShape"> </div> <div id="detailTitle"></div>
* <div id="detailLocation"></div> <div
* id="detailDescription"></div> </div> </div> </div> </div>
*/
Element detailLevel = domContext.createElement(HTML.DIV_ELEM);
detailLevel.setAttribute(HTML.ID_ATTR, "detailLevel");
stackLayout.appendChild(detailLevel);
Element detailBox = domContext.createElement(HTML.DIV_ELEM);
detailBox.setAttribute(HTML.ID_ATTR, "detailBox");
detailLevel.appendChild(detailBox);
Element topRectangle = domContext.createElement(HTML.DIV_ELEM);
topRectangle.setAttribute(HTML.ID_ATTR, "topRectangleShape");
detailBox.appendChild(topRectangle);
Element detailTitle = domContext.createElement(HTML.DIV_ELEM);
detailTitle.setAttribute(HTML.ID_ATTR, "detailTitle");
detailBox.appendChild(detailTitle);
Element detailLocation = domContext
.createElement(HTML.DIV_ELEM);
detailLocation.setAttribute(HTML.ID_ATTR, "detailLocation");
detailBox.appendChild(detailLocation);
Element detailDescription = domContext
.createElement(HTML.DIV_ELEM);
detailDescription.setAttribute(HTML.ID_ATTR,
"detailDescription");
/* carryover from original design leave in for now */
detailDescription.setAttribute(HTML.STYLE_CLASS_ATTR,
"imagebox");
// detailDescription.setAttribute(HTML.ONCLICK_ATTR,
// "animatePic(this.style,0)");
detailBox.appendChild(detailDescription);
}
domContext.stepOver();
domContext.streamWrite(facesContext, uiComponent);
} catch (DOMException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
}