Remember that our applications are run in Safari, which is a web browser and events are handled in a different way than in native applications. In order to implement interfaces for our web applications that are similar to native ones, we'll need to disable the default behavior for these kind of events. This recipe explains how to prevent such behaviors.
function avoid_behavior(evt) { evt.preventDefault(); }
<body>
tag for the HTML pages of your application:<body ontouchmove="avoid_behavior(event);" ontouchstart="avoid_behavior(event);" ongesturestart="avoid_behavior(event);" ongesturechange="avoid_behavior(event);">
Safari Mobile offers a simple method for disabling the default behavior for events. We only need to handle each event calling to a function, which will invoke to this default method. Using the<body>
tag, we get to avoid this behavior when the page is loaded.
In practice, using the function of this recipe, we avoid effects such as the elastic scrolling. By default, Safari allows you to flick the content of the viewport. The problem is that native applications do not use this behavior and we need to avoid it to achieve a native look and feel similar to these ones.
The approach of this recipe is framework agnostic, so you can use it for your applications with independence of it. This means that it is possible to combine it with any frameworks described in the Chapter 1 , Frameworks Make Life Easier. For instance, you can use the iWebKit framework as used in the previous recipe.
Thanks to the hardware accelerometer incorporated in the iPhone, it is possible to rotate the content of the viewport. When the user rotates the physical device, by default, the layout of the application rotates as well. Let's see how to detect this kind of movement in our applications.
This recipe doesn't require any framework; despite this, we're going to continue using the iWebKit so we may reutilize our code.
<body>
tag to include the onorientationchange
attribute. The line should be changed to the following:<body onorientationchange="detect_orientation()">
function detect_orientation() { alert("Orientation has been changed"); }
code/ch03/orientation.html
in the code bundle provided on the Packtpub site.The code for this simple recipe captures the event, which is launched when the user rotates the device. For this purpose, the onorientationchange
handler is used inside the body tag. The detect_orientation()
callback function will be executed as a response to the event. It will display a simple alert box with a message indicating that the event was launched.
In order to test this recipe, you can load your new page directly on the iPhone. As shown in the following screenshots, each time you rotate the device, a new alert box will be displayed. The following screenshots show different messages responding to these rotations:
We can use a more sophisticated mechanism for displaying this information; despite this, we chose a common and native alert box provided by the web browser.
Maybe you're wondering why it can be useful to detect the rotation event. By default, the device autorotates the content, so for some applications you'll need to adjust the elements of the user interface. In some cases, the automatic adjustment made by the device will be sufficient and the content displayed will be indented properly. On the other hand, detecting the rotation could be required by those applications, which use the features and capabilities of the accelerometer. For instance, many games are making intensive use of this component and it is becoming very important to properly detect the rotation for responding to this action differently and then respond accordingly.
We can implement a graphic interface with drag-and-drop components from scratch, simply by detecting the different events over the screen and writing the code and responding to them. Fortunately, frameworks were designed to make our life easier, so we're going to use one of them for implementing this behavior in our web applications. Let's see how to write a small example with two rectangles. One of them will serve as an area for dropping and the other one will be the draggable component. Each will have a unique color and colors being the draggable component a smaller will be smaller. Obviously, the draggable rectangle can only be dropped inside the bigger one. This recipe explains the required code to implement this effect using the capabilities of the Sencha Touch framework.
Be sure you've installed Sencha Touch framework under the control of your web and can access it in your browser.
DocumentRoot
of your web server. This new directory will contain three different files. Let's start writing the first one called index.html
. It is a XHTML file defining the two main rectangles.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Drag and Drop</title> <linkrel="stylesheet" href="../sencha-touch/resources/css/ext -touch.css" type="text/css" /> <script type="text/javascript" src="../sencha-touch/ext-touch -debug.js"></script> <linkrel="stylesheet" href="main.css" type="text/css" /> <script type="text/javascript" src="main.js"></script> </head>
<body>
tag:<body> <div id="droppable">Drop area</div> <div id="draggable">Drag me!</div> </body> </html>
main.css
, which was referred in the XHTML file:#draggable { width: 100px; color: white; height: 100px; background-color: blue; top: 170px; left: 5px; position: absolute; padding-top: 40px; text-align: center; border-bottom: 1px solid; } #draggable.x-dragging { background-color: black; } #droppable { text-align: center; color: white; border-top: 1px solid; padding-top: 60px; height: 150px; width: 210px; background-color: red; position: absolute; left: 5px; top: 5px; }
main.js
JavaScript main file required by Sencha Touch, which defines the Sencha Touch interface. Remember that applications using this framework must define a main custom JavaScript file for initializing it and defining the initial behavior of the components. The code inside our file, named main.js
, is as follows:Ext.setup({ onReady: function(){ newExt.util.Draggable('draggable', { revert: true }); newExt.util.Droppable('droppable', { validDropMode: 'contains', listeners: { drop: function(droppable, draggable, e) { draggable.el.setHTML('Dropped!'), } } }); } });
code/ch03/drag_drop/
in the code bundle provided on the Packtpub site.The HTML interface for this recipe is pretty simple: two rectangles with different colors and with absolute positioning. The bigger rectangle represents the droppable area where the other rectangle can be dropped. The smaller rectangle is blue and located at the bottom of the page. Both of them are simple div
standard HTML elements with some CSS styles applied. We defined colors, width, and positioning in the main .CSS
file for our recipe. Apart from this, the CSS file also defines different colors to be used when the user interacts with the rectangles. For instance, if the user clicks-and-drags the smaller blue rectangle, its color changes to grey and when this element is successfully dropped inside the larger rectangle area, the larger rectangle changes its color from red to blue.
Regarding the main.js
file, it is using the Ext.setup
method to initialize the framework and for defining the behavior of our rectangles. We need to indicate which rectangle is draggable and which is droppable. It's simple, thanks to two predefined classes implemented in Sencha Touch. These are Ext.util.Draggable
and Ext.util.Droppable
. In our code, we're using the id
of each div
element as the first parameter of the constructor of each class. This means that the div
with id
equal to droppable - the bigger rectangle - will be an object of the Ext.util.Droppable
. On the other hand, the draggable element will be an instance of the Ext.util.Draggable
class and the value for the id
will be draggable
.
The constructor of the class Ext.util.Draggable
is using the property revert
to indicate that the rectangle will come back to its original position, if it isn't properly dropped inside the specific boundaries. You can change this behavior by setting the value to false
for this property. By default, the action will start when the user holds the element, but we can indicate a delay in milliseconds using the delay property.
With respect to the constructor method for the Ext.util.Droppable
, we're using a property called validDropMode
for considering how the drop is used to confirm the placement of the dropped item. With the contains
value for this property, we're indicating that the drop action will be valid only if the user places the smaller rectangle inside the bigger one. The other value for this property is intersect
, which is used when we only want to intersect both elements to execute the action. In addition to this property, we used the listener
object, which contains the event handlers to be added to the object during the initialization of the action. Our recipe simply changes the text of the draggable element to dropped! For executing this action, we're accessing the content of the div
element through the setHTML()
method provided by Sencha Touch.
The following screenshot shows the starting point:
When the users holds the small rectangle for dropping it, its color changes to grey as shown in the next screenshot:
The final result of the drag-and-drop action is shown the following screenshot:
Despite the fact that we only use two simple rectangles for implementing drag-and-drop with basic behavior, the classes provided by Sencha Touch offers a set of methods and properties for building more sophisticated interfaces.
Ext.util.Draggable
class at http://dev.sencha.com/deploy/touch/docs/?class=Ext.util.DraggableExt.util.Droppable
class at http://dev.sencha.com/deploy/touch/docs/?class=Ext.util.DroppableSometimes it can be awesome to add visual effects to our applications. Usually, these kind of effects are implemented using animations. Basically, an animation is a set of movements made by a widget on the screen. Combining these movements with color changes, we can apply visual effects to the user interface of our web applications. The most popular of these animations or effects are fade and slide. Both of them display different elements on the screen showing one element and hiding another one that is applying a transition.
In this recipe, you'll learn how to apply simple visual effects in your web applications to improve the user experience.
We're continuing with Sencha Touch because this toolkit implements some visual effects, which are ready-to-use for some elements of the user interface.
effects
inside the DocumentRoot
of our web server. Then you'll create a new XHTML file called index.html
inside this new directory.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Slide Effect</title> <linkrel="stylesheet" href="../sencha-touch/resources/css/ext-touch.css" type="text/css" /> <script type="text/javascript" src="../sencha-touch/ext-touch-debug.js"></script> <linkrel="stylesheet" href="main.css" type="text/css" /> <script type="text/javascript" src="main.js"></script> </head> <body></body> </html>
main.css
- Just for simplicity, our icon was called with the following lines:body { background: rgb(197,204,211); } .tab { background-color: #78bcf0; text-align: center; color: #204167; font-size: 1.5em; padding-top: 100px; }
Ext.setup({ onReady: function(){ newExt.TabPanel({ fullscreen: true, sortable: true, items: [ {title: 'Cu', html: '<p>Tab 1. Cube</p>', cls: 'tab', animation: { type: 'cube', duration: 400} }, {title: 'P', html: '<p>Tab 2. Pop</p>', cls: 'tab', animation: { type: 'pop', duration: 400} }, {title: 'Fa', html: '<p>Tab 3. Fade</p>', cls: 'tab', animation: { type: 'fade', duration: 600} }, {title: 'Fl', html: '<p>Tab 4. Flip</p>', cls: 'tab', animation: { type: 'flip', duration: 400} }, {title: 'Sl', html: '<p>Tab 5. Slide</p>', cls: 'tab', animation: { type: 'slide', duration: 400} } ] }); } });
code/ch03/effects/
in the code bundle provided on the Packtpub site.Sencha Touch uses a main JavaScript file for defining the user interface and its behavior. This is the reason for using an empty HTML file for this recipe. However, this file needs to load the main JavaScript and CSS files, including our application-specific JavaScript file with the required code for defining our user interface.
The CSS file for our application is very simple. It only contains a specific background color for the page and some properties for the tabs as the color, size, and alignment of the text and the background color.
Regarding the main JavaScript file for our application, it defines a widget based on five different tabs. A different visual effect is applied to change to the active tab each time the user clicks on one of them. Specifically, we're using the effects cube, pop, fade, flip
, and slide
predefined by Sencha Touch. Each of these effects is defined by the object animation
, which uses two parameters. The first one indicates the predefined effect and the second one is the duration of the transition expressed in milliseconds. We chose 400 milliseconds except for the fade
value. For this one, we're using 600, but these are arbitrary values. You can choose the ones you consider the best for your purposes. Inside each tab, we're displaying a simple text indicating the number of the tabs and the effect applied during the transition. On the other hand, the cls
property of each tab is used to indicate which style should be applied. In this recipe, we used the same value for all tabs.
We must keep in mind that these effects defined and implemented by Sencha Touch can only be applied to container objects using a CardLayout
for the layout. This is the reason for using an object of the class TabPanel
as our main container, which uses this layout by default. The advanced user can design a customized object using a layout such as this one. Also, it's possible to use whichever class defined by Sencha Touch that uses this specific kind of layout. For instance, NestedList
is another container using CardLayout.
Apart from the effects shown in this recipe, the Sencha Touch framework implements others as a different kind of slide or the wipe effect. If you're interested, you can take a look at the complete documentation offered by this framework.
We're building web applications with a native look and feel, we have to keep in mind that they are running over the Internet. This means our potential clients will need an Internet connection to access our applications. However, this is an important difference between web applications and native applications. Here is where cache comes to the rescue. The new HTML5 standard defines a new mechanism for running web applications without Internet access. Using this technique our web iPhone application will behave closer to a native application.
Let's explore the mechanism for running your web application offline.
Be sure you've installed the iWebKit framework because we're going to use it to illustrate how to cache the files of our application. Also, we need to use a web server as Apache or lighttpd.
For this recipe, we'll start from scratch instead of reusing a file previously created.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html manifest="cache-mf" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http -equiv="Content-Type" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="viewport" content="width=device-width, user -scalable=no" /> <linkhref="../iwebkit/css/style.css" rel="stylesheet" media="screen" type="text/css" /> <scriptsrc="../iwebkit/javascript/functions.js" type="text/javascript"></script> <title>Offline</title> </head> <body> <div id="topbar"> <div id="title">Offline</div> </div> </body>
offline.html
inside your DocumentRoot
directory of the web server. We suppose the required files for the iWebKit framework are inside a directory called iwebkit
, which is inside the DocumentRoot
directory. For instance, using Ubuntu Linux and Apache, we'll have the following path structure:/var/www/iwebkit/:
It is the directory containing the required files for the iWebKit framework./var/www/offline.html:
It is the main XHTML file for this recipe.cache-mf
inside the same DocumentRoot:
CACHE-MANIFEST offline.html ../iwebkit/css/style.css ../iwebkit/javascript/functions.js
We used the manifest
attribute of the<html>
tag with the cache-mf
value. It indicates to the web browser that there exits a file called cache-mf
in the same directory that the HTML file is located. You can observe we're using a standard XHTML file, but it will work with an HTML file as well.
The cache-mf
is a plain text file containing information about the file, which should be cached for the web browser. Actually, it will contain one line per file, which will be cached. Each text line is a path to the specified file. By default, the path is relative to the directory where the application is running. Also, it is possible to use absolute path using the complete URL for each file. Don't forget to include the CACHE-MANIFEST
header at the top of the file.
In this recipe, we used the iWebKit framework with a simple HTML file for the main user interface. As we don't need anything more, only style.css
and functions.js
are required and they will be cached with offline.html
. Obviously, in the real world, your application will use and require more files such as images and other CSS and JavaScript files. Caching additional files is pretty easy; just add a new line per file to cache-mf
. Maybe you want to use another name for the file, no problem. Just use a filename you prefer and set it as value
in the manifest
attribute of the<html>
tag.
It is important to keep in mind what happens when the application files are upgraded. If the application is cached, users may still be running an older version. The browser will detect new files, but it will keep running the old ones, even though the browser detects the new files. To run the new version of the application, users must relaunch it. In fact, the browser downloads the new files in the background, but it is using the old files until the user decides to relaunch the application. You can understand this behavior easily by thinking about desktop applications and updates. When you launch a desktop application, it checks if updates are available and proceeds to download them. In this scenario, your application is still running an older version. Although the updates are downloaded and installed, you need to relaunch your application to use it. The cache mechanism and behavior explained earlier for our web applications will work in a similar way.
One of the main advantages of using cache for web applications is that the mechanism is transparent for the users. They don't need to configure anything; the browser does that automatically by handling the caching for them.
The mechanism used for this recipe is not designed specifically for iPhone or for iWebKit browser; it should work on every web browser able to understand and process HTML5 content. In fact, some desktop browsers such as Firefox will ask you for confirmation before storing some files in your local drive in order to enable caching.
In addition to CACHE-MANIFEST
header, you can use another header defined by the HTML5 standard. For instance, using NETWORK
and a new list of files after it, you could indicate that these files won't be cached. This means that the browser will always ask for a new version of them to the Web when the user visits the page.
3.145.173.199