September 10, 2011

At Last!!!

Posted in Android Development, iPhone development tagged , , , , , , , , , , , , , , , at 10:29 pm by tetontech

At long last (big sigh of relief here by me) QuickConnectFamily 2.1 is finally available for download.  It involved a lot of work by many people and has come together well.  There are some big changes for both the iOS and Android platforms.  These enhancements and changes have been driven by requests from developers like you.

Both:

  • This one is BIG.  The JavaScript functions now exist inside the qc name space.  In other words where you would have used the handleRequest method it is now the qc.handleRequest method.  The old behavior is deprecated.
  • Another BIG one.  In order to make the Control Function code more readable and more easily comprehended for those new to the framework all Control Functions MUST return one of the following three values (see the documentation for more information):
    • qc.STACK_CONTINUE – This instructs the framework to execute the next control function in the stack.
    • qc.STACK_EXIT – This instructs the framework to terminate all further stack execution.
    • qc.WAIT_FOR_DATA – This instructs the framework that a call to database or remote data has been made or a call to device specific behavior such as showing a map, displaying the camera, email editor or other native behaviors.
  • Work has been done to improve the asynchronous call stability in the underlying framework.  (Thank you to the team at affinityAmp).
  • Miscellaneous bug fixes and enhancements.

Android:

  • Bug fixes
  • Expanded database support and fixes
  • A major rework of the underlying Android Java code to make it match the design changes in iOS.  This is in preparation for QC Plugins and some new features such as ‘window-in-window’ that will be part of the next release as a Plugin.  The ‘window-in-window’ code is in there now but not official until it is converted to a plugin and the same behavior is available for iOS.
  • Added a hybrid sqlite database example

iOS:

  • Bug fixes
  • Removed the native footer code since libraries for scrolling and others such as Sencha, JQTouch, etc. are now of good quality.
  • QC Family Hybrid Plugin API and design spec completed.  There is an example of how you can add to QC on your own.  If you thing these additions could be useful to others you are free to charge for them, or not, host them yourself, notify me and I will add them to the plugin list on the QC plugin site.  If you are willing to donate them to the QC community send them to me for review and I will put them into the git repository and list them on the QC plugin site.
  • Updated all the examples to use the new return values and the new qc name space.
Now that this is out I will be creating a Key/Value store for Android and presenting it at the next AnDevCon.  I’m also looking forward to adding Android build support back into the QC Hybrid build process so you can write your app once yet build and run it in the iOS simulator and the Android emulator with one click.
As always I hope this is helpful for you.  I enjoy working on QC and hope to be able to do so long into the future.  If you find any issues please let me know via the google group.
Lee
Advertisements

August 16, 2011

QC DBSync version 1.3 available

Posted in Uncategorized tagged , , , , , , , , , , at 5:24 pm by tetontech

For those of you needing a native database synchronization tool version 1.3 of QC DBSync is now available.  It includes minor functionality and API upgrades on the iOS side, an example service written in PHP is included in the download.

February 17, 2011

Android SQLite Library Example Code

Posted in Android Development tagged , , , , , , at 11:00 pm by tetontech

I have just uploaded QCDBAccess.  It is a SQLite wrapper for Android that is easy to use, thread-safe, and allows you to use transactions if you choose.  It is the same code that has been available for QCAndroid hybrid application developers for a few years.  I thought I would pull it out and give it its own life for those that want to use it on their own.

You can download it from SourceForge and find out more about it, including the API, at the QuickConnectFamily site.

As with all of the things I’m making available I have tried to make this as easy to use, highly functional, and small as possible.

The jar file is only 8k in size but the library doesn’t restrict your use of the databases in any way.

Here is a simple example of how to use the library to do a query against a SQLite database file included in your applications’ assets directory.  Notice that I’m checking to see if the user has entered a name to query against in an EditText object from the user interface.  If they have then I’m going to use a prepared statement.  The EditText object in this example has been passed into the method in which this code exists.

String sql = “SELECT * FROM user”;

String[] statementParams = null;

EditText nameInput = (EditText)methodParameters.get(1);

String name = nameInput.getEditableText().toString().trim();

if(name.length() > 0){

sql += ” WHERE name = ?”;

statementParams = new String[1];

statementParams[0] = name;

}

try {

retVal = DataAccessObject.getData(theActivity, “demo.sqlite”, sql, statementParams);

} catch (DataAccessException e) {

e.printStackTrace();

}

The DataAccessResult variable retVal is going to be returned from this method later.  This DataAccessResult is a Bean that contains resultant field names, the records returned from the query, and a database error description if and only if a database error happened.

the getData method is passed the Activity with which the database is associated with.  This is usually the main Activity in an Android Application.  The second parameter is the name of the SQLite database file to be used.  The third parameter is SQLite SQL assembled either as a standard or prepared statement.  The last parameter is an array of Objects that are to be bound to the ? characters if the SQL is a prepared statement or null if it is not a prepared statement.

Inserting data is done in very much the same fashion.  Once again I have an EditText object in the UI from which I’m getting the name to be inserted into the table.  I’m also generating a unique identifier just to make this a little more interesting.  You could do an auto incremented id in your table if you want.

EditText nameInput = (EditText)parameters.get(1);

String nameToAdd = nameInput.getEditableText().toString().trim();

String[]statementParams = {UUID.randomUUID().toString(), nameToAdd};

DataAccessResult aResult = null;

try {

aResult = DataAccessObject.setData(theActivity, “demo.sqlite”,

“INSERT INTO user VALUES(?,?)”,

statementParams);

return aResult;

} catch (Exception e) {

e.printStackTrace();

}

Notice that once again I have chosen to use a prepared statement.  I’m doing this to avoid SQL insertion attacks.  It never hurts to avoid those.

If you are going to do several insertions you should use transactions to make sure you data stays clean.  There is a startTransaction method and an endTransaction method in the DataAccessObject.  Use those before and after multiple setData calls and you will be safe.

January 25, 2011

QCJSON Now Thread Safe

Posted in Android Development, misc tagged , , , , , , , , , , , , at 7:25 am by tetontech

The changes described here are found in QCJSON v. 1.0.2 available on sourceForge .  The license is BSD.  You can get the source code from the git repository on sourceForge using the command:

git clone git://qcjson.git.sourceforge.net/gitroot/qcjson/qcjson

or look at it online.

I’ve been pondering how to make QCJSON thread safe meaning that you could read and write to the same stream from separate threads safely without impacting any other streams that may be being used in the same or other threads.

The problem description is that you don’t want to start a read when one is part way complete.  Nor do you want to start a write in the middle of another write.  Both of these situations plus mixing read and write can cause serious data corruption.

I briefly played with the idea of creating a Class that would contain a static semaphore.  This static semaphore would control access to the reading and writing behavior of the existing code.  The problem is that with this approach reading or writing to one stream on one thread would cause any other threads to wait at the semaphore claim location even if the stream that it wished to write to was in no way associated with the stream that was currently being used.  In other words reading or writing on one stream would block reading and writing on all streams until it was complete.  Obviously this is an unacceptable solution.  You might as well just write in one thread.

Since there is no way of interrogating an input our output stream object in Java it isn’t possible to hide the threading locks from the programmer using the QCJSON library and allow independent streams to work in independent threads.

While I’ve thought through several options the one that seems the best is to allow you, the developer, to pair input and output streams and include a semaphore in this pairing.  This is going to require a new class.

For lack of a better name I am calling this new class org.quickconnect.json.JSONStreamProtector.  It has a default constructor that takes no parameters and has one public method, protectJSONStream(JSONStream aStream).

If you instantiate a JSONStreamProtector you can pass the protectJSONStream method any number of JSONInputStreams and JSONOutputStreams.  Any streams that you pass as a parameter to this method will share the same semaphore.  Thus when you call readObject or writeObject on the protected streams any threads that would be using these streams will block in their readObject or writeObject methods until it is safe to proceed.

Using JSONStreamProtector

Changes have been made in the JSONInputStream and JSONOutputStream classes so that  if a protector has been set for them the stream will claim or wait until it is able to claim the semaphore in its defined protector.

You needn’t put the protector in a collection or some other class’ attributes in order for it to not be garbage collected.  Passing one JSONStream to the protectJSONStream method is sufficient.

In Example 1 the code shows how to protect a single output stream from three separate threads trying to write to the stream simultaneously.  Input streams work the same way.  Protecting an input/output stream pair that work on the same underlying resource would just mean using the same protector for both streams.

Any stream can only have one protector at a time.  This keeps your code from accidentally getting in a cross-locking situation.  You can switch the protector is is using at any time by calling the new protectors’ protectJSONStream method.

Example 1:

try {
/*
* Add three output streams to the same file and then have each of them send
* json to the stream. Make sure that no data corruption occurs.
*/
JSONStreamProtector aProtector = new JSONStreamProtector();
FileOutputStream testOut = new FileOutputStream(aFile);
/*
* stuff to write to file
*/
int[] testIntArray = {7,10,0,-789};
String[] testStringArray = {"What","is","happening?"};
TestObject anObject = new TestObject("Hello there.", 7, new Date(1067899));

 

/*
* do the running
*/
JSONOutputStream jsonTestOut1 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut1);

Thread testThread1 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testIntArray));

JSONOutputStream jsonTestOut2 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut2);

Thread testThread2 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testStringArray));

JSONOutputStream jsonTestOut3 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut3);

Thread testThread3 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, anObject));
testThread1.start();
testThread2.start();
testThread3.start();

 

} catch (Exception e) {
e.printStackTrace();
}

 

The source code for the protector class is simple so I’ll just put it here.


package org.quickconnect.json;

import java.util.concurrent.Semaphore;

public class JSONStreamProtector{
private Semaphore semaphore = new Semaphore(1, true);
public void protectJSONStream(JSONStream aJsonStream){

aJsonStream.setProtector(this);

}
protected void claim() throws InterruptedException{
semaphore.acquire(1);
}
protected void free(){
semaphore.release(1);
}
}

 

January 15, 2011

QuickConnectFamily 1.6.7 Available

Posted in Android Development, iPhone development tagged , , , , , , , , , , , , , , at 11:14 pm by tetontech

QC 1.6.7 has been uploaded.  It includes a complete rewrite of the way your QCAndroid apps are compiled from within xCode.  I think you will find compiling much better.  It also includes a native Android template that allows you to build QC applications in Androids’ native Java along side the Objective-C native template for iOS apps.

Just like in QC Native for iOS apps created using this QC Native for Android template ‘pre-threads’ your application for you.  This means that any code that you write that is not directly related to updating the view is run in helper threads.  Any code you write that updates the view will run in the main view thread just like the native QC iOS apps.

Build your Control stacks in either language and your Validation and Business Control Objects, including db and server/service access, will be run on background, helper threads and then when the View Control Objects are executed they will be run in the main-view thread.

This means that your applications’ user experience is snappier since the main-view thread is only blocked when the view is being updated.

I will be covering the basic structure of Android Native QC apps and how to write them at the Android Developer Conference in March.

I will be covering the basic structure of iOS Native and Hybrid QC apps at the iPhone Developers Conference in April.

More tutorials, when I get them done, will be available on the wiki.

I have also uploaded QuickConnectFamilyPC_1.6.7 for those of you who want to develop using Eclipse rather than Xcode.  It includes a few examples of hybrid apps and instructions for how to use QC in Eclipse.

I’d love to see you at the developer conferences and get feedback in addition to what I receive via the Google group and this blog.

Thanks,

 

Lee

December 23, 2010

QuickConnect 1.6.4 Now Available

Posted in Uncategorized tagged , , , , , , , , , , , , , , , at 8:44 am by tetontech

I have just posted the 1.6.4 version of QC on SourceForge.  It includes some defect fixes and some minor additions, and a few big changes.  QC 1.6.4 requires the iOS 4.2 SDK.

The big changes are regarding the native application templates.  You can now use the same design to create Objective-C iPhone, iPad, and Universal iPhone/iPad apps that you have been using to create your hybrid applications.

These native iOS apps come ‘pre-threaded’.  Every time you call handleRequest your command stack is executed on a worker thread.  Any of your ViewControlObjects that you create for your control Stack are executed in the main  thread since it is the only one that is allowed to update the User Interface.  All other behavior is done on a worker thread and you don’t have to worry about how to set it up, make it go, or make it stop.

Just as with the hybrid apps you’ve been creating with QC all of your async calls to HTTP servers, portals, etc. are linearized for you.  You never need to write another callback function!

In addition to making your remote HTTP calls easier all of the templates for native QuickConnect applications also include support for both direct SQLite access and CoreData.

With a little time working in Interface Builder and putting together some CoreData objects your app is up and running.

Examples are already in the download for all of these native iOS templates.  Check them out and see how easy native iOS apps can be.

The next release will have native multi-threaded Android applications as well.

One other change is  that the PHP template has been updated.  Take a look at the example in the download.

Lee

July 30, 2010

iAdds and File Download available in new QuickConnect Release

Posted in Android Development, iPhone development tagged , , , , , , , , at 2:49 am by tetontech

As promised QCFamily 1.6.2 is now available.  It includes the ability to show and hide iAdds from within JavaScript.  Take a look at the new exmaple app.

It also includes the ability to download files.  When you download a file from a server the framework stores it on the device it then sends the full file path to your javascript code.  See the new example.  It downloads an image file and then sets the source of an img tag to be the file.  Presto!  Image updates from your server.

A feature to build on top of this download would be displaying office docs that you download.  Would you like that feature?

Be careful with this download feature.  If you download JavaScript Apple will probably reject your app.

June 22, 2010

QuickConnect 1.6 beta 18 available

Posted in Uncategorized tagged , , , , , , at 2:48 pm by tetontech

beta 18 was posted last friday and is now available.  It includes several new user interface behaviors and examples.

If you just updated to the 4.0 development environment you should know that Apple has removed 3.1 development support.  You will need to update the example’s base SDK to 3.2.  This is done by:

  1. opening the example
  2. selecting the project in the left-hand, project explorer view
  3. clicking the info icon in the xcode window header
  4. selecting the General option in the new dialog
  5. setting the ‘base SDK for all options’ found at the bottom of the dialog to 3.2.

I’ll get the examples all updated to 3.2 for the beta coming out this weekend.

March 26, 2010

Using HTML Links to Trigger Activity in Hybrid Applications

Posted in Android Development, Blackberry development, iPhone development, mac development tagged , , , , , , , , , , , at 5:28 pm by tetontech

For those of you who are wanting to use <a> link tags to trigger behavior I have put together an example of how to make these work.

The main problem when you want to use a link rather than a button, div, image, or some other HTML element is to stop the standard behavior of loading the new page.  This is readily accomplished using QuickConnect since the framework includes a method with the signature ‘stopDefault(event)’.

Any time you call this method the default behavior of any type of event whether it be load a page, scroll, etc. is not executed.  The code behind this method is very strait forward as you can see here.

//stop an event from doing its’ default behavior

function stopDefault(event){

if(event){

event.preventDefault();

}

}

The fully working QuickConnect example code is seen below.  This example will also be included in the next beta download and the first QC v1.6 release.  This example is built off of the ViewSwapping example and includes an addition of how to interact with the in-app map QuickConnect behavior.  Because of this the index.html file code is very similar to that seen in my previous post.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” http://www.w3.org/TR/html4/strict.dtd>

<html>

<head>

<title>QCXcodeTemplate</title>

<base href=“mobile/”>

<meta http-equiv=“content-type” content=“text/html; charset=utf-8”>

<meta name=“viewport” content=“width=device-width, minimum-scale=1.0, maximum-scale=1.6”>

<meta name=“apple-mobile-web-app-capable” content=“YES”>

<link rel=“stylesheet” href=“main.css”>

<script type=“text/javascript” src=“Parts/parts.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“../QCJSLib/setupQC.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“main.js” charset=“utf-8”></script>

</head>

<body onload=“load();”>

<div id=‘view1’ class=‘view’>

<a href=“” onclick=‘showView(2)’ >Show View 2</a>

<p>Here is some text for display in View 1.</p>

</div>

<div id=‘view2’ class=‘view’ style=‘background-color:lightgreen;’>

<a href=“” onclick=‘showView(1)’ >Show View 1</a>

<p>Here is some text for display in View 2.</p>

</div>

<a href=“” onclick=‘triggerShowMap()’>Show Map</a>

</body>

</html>

The main difference shown here is that the buttons have been replaced by link (anchor) tags.  Notice that the src attribute is set to an empty string.  It can be set to anything but what ever it is set to is ignored because of a call to the stopDefault method described above.

Additionally I have included a link that activates the in-app map behavior.  This new map activation link is the last element shown in the body tag.

Since the CSS hasn’t changed between this example and the previous one I will not provide it again.  You can see it in my previous post.

The Javascript is very similar.  As you can see here the only difference between the ShowView example code and the UsingLinksAsTriggers is the inclusion of a call to the stopDefault method.

function load()

{

showView(1);

}

var currentView = null;

function showView(viewNumber){

//stop the loading of the new page since this is triggered by a link

stopDefault(window.event);

var nextView = document.getElementById(‘view’+viewNumber);

//if there is a view to change to

if(nextView){

//if at least one view has been displayed

if(currentView){

currentView.style.zIndex = 0;

currentView.style.opacity = 0;

}

nextView.style.zIndex = 10;

nextView.style.opacity = 1.0

//reset currentView

currentView = nextView;

}

}

The method for showing a map inside your application, triggerShowMap, is much like the method in the ShowMap example.  The difference is once again the addition of the call to stopDefault.

function triggerShowMap(event)

{

//stop the loading of the new page since this is triggered by a link

stopDefault(window.event);

//a location consists of a latitude, a longitude, and a description

var locationsArray = new Array();

var rexburg = new Array();

rexburg.push(43.82211);

rexburg.push(-111.76860);

rexburg.push(“County Court House”);

locationsArray.push(rexburg);

var wyoming = new Array();

wyoming.push(42.86);

wyoming.push(-109.45);

wyoming.push(“Wyoming Place”);

locationsArray.push(wyoming);

var wilderness = new Array();

wilderness.push(45.35);

wilderness.push(-115);

wilderness.push(“River of No Return Wilderness”);

locationsArray.push(wilderness);

var sandwichShop = new Array();

sandwichShop.push(42.86);

sandwichShop.push(-112.45);

sandwichShop.push(“Somewhere Sandwiches”);

locationsArray.push(sandwichShop);

/*

*  possible map types are standard, satelite, hybrid

*  The showMap method call is part of the QuickConnect Framework.

*  It is not a standard call

*/

var showDeviceLocation = true;

showMap(locationsArray, showDeviceLocation, ‘standard’);

}

The examples shown here don’t use the QuickConnect mappings and stacks but the same call to stopDefault would need to be made if you were calling the standard ‘handleRequest’ method.  I usually put the stopDefault call in the first control function executed for the given command.

Hopefully this clears up how to use a link within hybrid applications.

March 25, 2010

Swapping View Divs

Posted in Android Development, Blackberry development, iPhone development, misc tagged , , , , , , , , at 10:44 pm by tetontech

Let’s say you want to display multiple information views in your app.  I’ll describe here how to to this with very few lines of code using HTML 5 principles.  These examples can also be found in the latest QuickConnectFamily download as hybrid applications.

There will be two examples.  The first is fading between views.  The second is sliding views over the top of others.  These examples work for both hybrid and web apps.

When a hybrid app is created it is often the case that you need to display several different views with different data being displayed.  This may be due to some sort of ‘drill down’ behavior you need in your app or for some other reason such as a display of some sort of a login or configuration view.

You could use Dashcode and it’s Stack part but that has a lot of overhead in both code size and execution speed or you could do something like is described here.

The first example shows how to display multiple divs and then fade from one div to another without any change of position for the divs.

We start by adding the divs and navigation buttons to the HTML.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” http://www.w3.org/TR/html4/strict.dtd>

<html>

<head>

<title>QCXcodeTemplate</title>

<base href=“mobile/”>

<meta http-equiv=“content-type” content=“text/html; charset=utf-8”>

<meta name=“viewport” content=“width=device-width, minimum-scale=1.0, maximum-scale=1.6”>

<meta name=“apple-mobile-web-app-capable” content=“YES”>

<link rel=“stylesheet” href=“main.css”>

<script type=“text/javascript” src=“Parts/parts.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“../QCJSLib/setupQC.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“main.js” charset=“utf-8”></script>

</head>

<body onload=“load();”>

<div id=‘view1’ class=‘view’>

<input type=‘button’ value=‘Show View 2’ onclick=‘showView(2)’ />

<p>Here is some text for display in View 1.</p>

</div>

<div id=‘view2’ class=‘view’ style=‘background-color:lightgreen;’>

<input type=‘button’ value=‘Show View 1’ onclick=‘showView(1)’/>

<p>Here is some text for display in View 2.</p>

</div>

</body>

</html>

Nothing special in this HTML code.  Notice the onclick handler ‘showView’.  We’ll look at that in a minute, but first lets look at the CSS for the divs.
Here is the CSS from main.css

body {

margin: 0px;

min-height: 356px;

font-family: Helvetica;

background-repeat: repeat;

}

.view{

position:absolute;

top: 50px;

left: 20px;

background-color:lightBlue;

z-index:0;

opacity:0;

-webkit-transition: opacity 1s linear;

}

You can see some very standard CSS in the view class that is applied to each of the view divs.  The only item that is different is the HTML 5 transition element.  It states that every time the opacity is changed by some Javascript call that the opacity change should be applied over one second and that the change should change consistently.
There are other transition types available other than linear such as ease-in, ease-out, ease-in-out, etc. but we will stick with linear for now.
Notice that the opacity of all of the divs is set to zero initially.  This means that all of the divs will be transparent when the application starts.  Also notice that the z-index of the divs are all set to zero.  Zero is the default value but this is added for clarity in the CSS.
The Javascript is very small.  When doing fading we need to track the current view so that we can cause it to fade out while the new view fades in.  This is why the currentView global variable is created and used.

function load()

{

showView(1);

}

var currentView = null;

function showView(viewNumber){

var nextView = document.getElementById(‘view’+viewNumber);

//if there is a view to change to

if(nextView){

//if at least one view has been displayed

if(currentView){

currentView.style.zIndex = 0;

currentView.style.opacity = 0;

}

nextView.style.zIndex = 10;

nextView.style.opacity = 1.0

//reset currentView

currentView = nextView;

}

}

In the showView method  we change the opacity.  This triggers the transition defined in the CSS.  The zIndex is also changed.  If the zIndecies of the divs being switched are not changed then the transparent div can end up still being on top of the opaque div.  If this is the case then the touches or clicks will not be registered by the visible div.
That’s it.  No more code needed.  That is a lot less code than Apple generates in Dashcode.
Example 2 pushes divs over each other and then pops them off.  It does this by moving the divs using CSS 5 abilities.
The HTML for this example is very similar but contains 4 divs.  The first div is a container I’m calling ‘stack’ and holds a ‘stack’ of the divs that are used as view divs.  The other three divs are view divs.  I created three instead of two divs to make it easier to see how you could use this functionality.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” http://www.w3.org/TR/html4/strict.dtd>

<html>

<head>

<title>QCXcodeTemplate</title>

<base href=“mobile/”>

<meta http-equiv=“content-type” content=“text/html; charset=utf-8”>

<meta name=“viewport” content=“width=device-width, minimum-scale=1.0, maximum-scale=1.6”>

<meta name=“apple-mobile-web-app-capable” content=“YES”>

<link rel=“stylesheet” href=“main.css”>

<script type=“text/javascript” src=“Parts/parts.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“../QCJSLib/setupQC.js” charset=“utf-8”></script>

<script type=“text/javascript” src=“main.js” charset=“utf-8”></script>

</head>

<body onload=“load();”>

<div class=“stack”>

<div id=‘view1’ class=‘view’>

<input type=‘button’ value=‘Show View 2’ onclick=‘slideIn(2)’ />

<br/>

<input type=‘button’ value=‘Show View 3’ onclick=‘slideIn(3)’ />

<p>This is View 1.</p>

</div>

<div id=‘view2’ class=‘view’ style=‘background-color:lightgreen;’>

<input type=‘button’ value=‘Done’ onclick=‘slideOff()’/>

<p>This is View 2.</p>

</div>

<div id=‘view3’ class=‘view’ style=‘background-color:lightyellow;’>

<input type=‘button’ value=‘Done’ onclick=‘slideOff()’/>

<p>This is View 2.</p>

</div>

</div>

</body>

</html>

The CSS is also very similar to the previous example.  The major difference is that I have defined the width and height of the view and stack divs.  This allows me to move the view divs outside the viewable portion of the stack div.  Thus it appears that they disappear when they move.

body {

margin: 0px;

min-height: 356px;

font-family: Helvetica;

background-repeat: repeat;

}

.stack{

position:absolute;

top: 50px;

left: 20px;

width: 200px;

height:200px;

border: solid 1px black;

overflow: hidden;

}

.view{

position:absolute;

left: 320px;

width:100%;

height: 100%;

background-color:lightBlue;

-webkit-transition: left .5s linear;

}

Notice that the transition is now activated when the left CSS value is changed.
The JavaScript is also very similar to what you saw before.  Instead of Changing the opacity and the z-index all that has to be changed is the left value.  This triggers the CSS 5 transition and the div moves to the new location in .5 seconds.

function load()

{

slideIn(1);

}

var viewStack = new Array();

function slideIn(viewNumber){

var nextView = document.getElementById(‘view’+viewNumber);

//if there is a view to change to

if(nextView){

nextView.style.zIndex = viewStack.length;

nextView.style.left = ‘0px’;

//add the displayed view to the stack

viewStack.push(nextView);

}

}

function slideOff(){

var currentView = viewStack.pop();

currentView.style.left = ‘320px’;

}

You can see that it doesn’t take much to do some very interesting stuff using the HTML 5 transitions.
I hope this helps those who want to improve their user interfaces.

Next page

%d bloggers like this: