incubator-callback-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fil...@apache.org
Subject [17/19] [CB-606] Added create script for unix and windows
Date Wed, 13 Jun 2012 17:09:08 GMT
http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/templates/project/www/index.html
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/index.html b/bin/templates/project/www/index.html
new file mode 100644
index 0000000..92537b1
--- /dev/null
+++ b/bin/templates/project/www/index.html
@@ -0,0 +1,976 @@
+<!-- 
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <meta name="viewport" id="viewport" content="width=device-width,height=device-height,initial-scale=1.0,user-scalable=no">
+    <script src="json2.js" type="text/javascript"></script>
+    <script src="cordova.js" type="text/javascript"></script>
+    <script type="text/javascript">
+
+        //---------------------------------------------------------------------
+        // Cordova event listeners
+        //---------------------------------------------------------------------
+
+        // invoked when device is ready 
+        function deviceInfo() {
+            document.getElementById('window.device.platform').innerHTML = 'window.device.platform = ' + window.device.platform;
+            document.getElementById('window.device.version').innerHTML  = 'window.device.version  = ' + window.device.version;
+            document.getElementById('window.device.uuid').innerHTML     = 'window.device.uuid     = ' + window.device.uuid;
+            document.getElementById('window.device.cordova').innerHTML = 'window.device.cordova = ' + window.device.cordova;
+
+            setNetworkType();
+        }
+        
+        // invoked when application is resumed (brought to foregroud)
+        function doResume() {
+            console.log('doResume()');
+        }
+      
+        // invoked when application is paused (sent to background)
+        function doPause() {
+            console.log('doPause()');
+        }
+
+        // invoked when application is online
+        function doOnline() {
+            console.log('Event: online\n' + 'Network Type: ' + navigator.network.connection.type + '\n');
+            setNetworkType();
+        }
+
+        // invoked when application is offline
+        function doOffline() {
+            console.log('Event: offline\n' + 'Network Type: ' + navigator.network.connection.type + '\n');
+            setNetworkType();
+        }
+
+        // register Cordova event listeners when DOM content loaded
+        function init() {
+            console.log('init()');
+            document.addEventListener("deviceready", deviceInfo, true); 
+            document.addEventListener("resume", doResume, false);
+            document.addEventListener("pause", doPause, false);
+            document.addEventListener("online", doOnline, false);
+            document.addEventListener("offline", doOffline, false);
+        }
+
+        function unload() {
+            console.log('unload()'); 
+        }
+      
+        function fail(error) {
+            navigator.notification.alert(error, null, "Error");
+        }
+        
+        //---------------------------------------------------------------------
+        // Notification
+        //---------------------------------------------------------------------
+
+        function callBeep() {
+            navigator.notification.beep(2);
+        }
+
+        function callVibrate() {
+            navigator.notification.vibrate(1000);
+        }
+      
+        function alertDismissed() {
+            alert('Alert dialog dismissed.');
+        }
+      
+        function callAlert() {
+            navigator.notification.alert(
+            "You rock!", 
+            alertDismissed,
+            "Woohoo!", 
+            "Thanks");
+        }
+
+        function confirmResult(button) {
+            console.log('Confirm: you pressed button ' + button);
+        }
+
+        function callConfirm() {
+            navigator.notification.confirm(
+            "Please confirm", 
+            confirmResult,
+            "Are you sure?", 
+            "Yes,No,Maybe");
+        }
+
+        //---------------------------------------------------------------------
+        // Network
+        //---------------------------------------------------------------------
+        function setNetworkType() {
+            var states = {};
+            states[Connection.UNKNOWN]  = 'Unknown connection';
+            states[Connection.ETHERNET] = 'Ethernet connection';
+            states[Connection.WIFI]     = 'WiFi connection';
+            states[Connection.CELL_2G]  = 'Cell 2G connection';
+            states[Connection.CELL_3G]  = 'Cell 3G connection';
+            states[Connection.CELL_4G]  = 'Cell 4G connection';
+            states[Connection.NONE]     = 'No network connection';
+            document.getElementById('networkStatus').innerHTML = 'Connection type = ' + states[navigator.network.connection.type];
+        }
+
+        //---------------------------------------------------------------------
+        // Accelerometer
+        //---------------------------------------------------------------------
+        function showAcceleration(acceleration) {
+            alert('Acceleration X: ' + acceleration.x + '\n' +
+                  'Acceleration Y: ' + acceleration.y + '\n' +
+                  'Acceleration Z: ' + acceleration.z + '\n');
+        }
+
+        var accelWatchId = null;
+        var watchAcceleration = function() {
+            var success = function(a) {
+                document.getElementById('x').innerHTML = a.x;
+                document.getElementById('y').innerHTML = a.y;
+                document.getElementById('z').innerHTML = a.z;
+            };
+            var options = {};
+            options.frequency = 200;
+            accelWatchId = navigator.accelerometer.watchAcceleration(success, fail, options);
+        }
+      
+        function clearAccelWatch() {
+            if (accelWatchId != null) {
+                navigator.accelerometer.clearWatch(accelWatchId);
+                accelWatchId = null;
+            }
+        }
+
+        function getAcceleration() {
+            navigator.accelerometer.getCurrentAcceleration(showAcceleration, fail);
+        }
+
+        //---------------------------------------------------------------------
+        // Geolocation
+        //---------------------------------------------------------------------
+        function getLocation() {
+            var success = function(p) {
+                alert('Latitude: '  + p.coords.latitude + '\n' + 
+                      'Longitude: ' + p.coords.longitude);
+            };
+            var options = {};
+            options.enableHighAccuracy = true;
+            var timeout = new Number(document.getElementById('geo_timeout').value);
+            if (isNaN(timeout) === false) {
+                options.timeout = timeout*1000;
+            }
+            var maxage = new Number(document.getElementById('geo_maxage').value);
+            if (isNaN(maxage) === false) {
+                options.maximumAge = maxage*1000;
+            }
+            navigator.geolocation.getCurrentPosition(success, onLocationFail, options);
+        }
+
+        var locationWatchId = null;
+        var watchLocation = function() {
+            var success = function(p) {
+                document.getElementById('lat').innerHTML = p.coords.latitude;
+                document.getElementById('long').innerHTML = p.coords.longitude;
+            };
+            var options = {};
+            options.enableHighAccuracy = true;
+            var timeout = new Number(document.getElementById('geo_timeout').value);
+            if (isNaN(timeout) === false) {
+                options.timeout = timeout*1000;
+            }
+            var maxage = new Number(document.getElementById('geo_maxage').value);
+            if (isNaN(maxage) === false) {
+                options.maximumAge = maxage*1000;
+            }
+            locationWatchId = navigator.geolocation.watchPosition(success, onLocationFail, options);
+        }
+
+        function clearLocationWatch() {
+            if (locationWatchId != null) {
+                navigator.geolocation.clearWatch(locationWatchId);
+                locationWatchId = null;
+            }
+            document.getElementById('lat').innerHTML = "";
+            document.getElementById('long').innerHTML = "";
+        }
+      
+        function onLocationFail(error) {
+            alert('code: ' + error.code + '\n' +
+                  'message: ' + error.message + '\n');
+        }
+      
+        //---------------------------------------------------------------------
+        // Camera
+        //---------------------------------------------------------------------
+        function onCapturePhotoSuccess(imageData) {
+            if (imageData != null) {
+                var smallImage = document.getElementById('cameraImage');
+
+                // hide upload button
+                var uploadButton = document.getElementById('uploadButton');
+                uploadButton.style.display = 'none';
+
+                // Unhide image element
+                smallImage.style.display = 'block';
+
+                // Show the captured photo
+                // The inline CSS rules are used to resize the image
+                smallImage.src = "data:image/jpeg;base64," + imageData;
+            }
+        }
+
+        function onCapturePhotoURISuccess(imageURI) {
+            if (imageURI != null) {
+                var smallImage = document.getElementById('cameraImage');
+                var uploadButton = document.getElementById('uploadButton');
+
+                // Unhide image elements
+                smallImage.style.display = 'block';
+                uploadButton.style.display = 'block';
+          
+                // Show the captured photo
+                // The inline CSS rules are used to resize the image
+                smallImage.src = imageURI;
+            }
+        }
+      
+        function capturePhoto() {
+            navigator.camera.getPicture(onCapturePhotoSuccess, fail, 
+                { destinationType: Camera.DestinationType.DATA_URL, quality: 50 });
+        }
+
+        function capturePhotoURI() {
+            navigator.camera.getPicture(onCapturePhotoURISuccess, fail, 
+                { destinationType: Camera.DestinationType.FILE_URI, quality: 50 });
+        }
+
+        function uploadImage() {
+            var smallImage = document.getElementById('cameraImage');
+            if (smallImage.src && smallImage.src !== "") {
+                var f = new FileTransfer();
+                f.upload(
+                    // file path
+                    smallImage.src,
+                    // server URL - update to your own, and don't forget to 
+                    // include your domain in an access element in config.xml      
+                    "http://192.168.1.1/upload.php",
+                    // success callback
+                    function(result) {
+                        document.getElementById('uploadProgress').innerHTML =
+                            result.bytesSent + ' bytes sent';
+                        alert(result.responseCode + ": " + result.response);
+                    },
+                    // error callback
+                    function(error) {
+                        alert('error uploading file: ' + error.code);
+                    },
+                    // options
+                    { fileName: 'myImage.jpg', 
+                      params: { 'username':'jtyberg' } 
+                    });
+            }
+        }
+
+        //---------------------------------------------------------------------
+        // Contacts
+        //---------------------------------------------------------------------
+        function onContactSaved(contact) {
+            var msg = "Contact " + contact.id + " saved.";
+            navigator.notification.alert(msg, null, "Success");      
+        }
+
+        function onContactUpdated(contact) {
+            var msg = 'Contact ' + contact.id + ' updated.';
+            navigator.notification.alert(msg, null, "Success");      
+        }
+
+        function onContactRemoved(contact) {
+            var msg = "Contact " + contact.id + " removed.";      
+            navigator.notification.alert(msg, null, "Success");      
+        }
+
+        function createContact() {
+            var myContact = navigator.contacts.create({"displayName": "fitness instructor"});
+            myContact.note = "Workout queen.";
+            myContact.birthday = new Date("May 11, 1979 05:32:00");
+        
+            // add name
+            var myName = new ContactName();
+            myName.givenName = "Shoshana";
+            myName.familyName = "Lowenstein";
+            myName.honorificPrefix = "Miss";
+            myContact.name = myName;
+
+            // add email
+            var emails = [];
+            emails[0] = new ContactField("work","im@work.com");
+            emails[1] = new ContactField("home","im@home.com",true);
+            emails[2] = new ContactField(null,"im@other.com");
+            emails[3] = new ContactField(null,"im@aloss.com"); // 4th will be ignored
+            myContact.emails = emails;
+
+            // add phone numbers
+            var phoneNumbers = [];
+            phoneNumbers[0] = new ContactField("work","555-111-1111");
+            phoneNumbers[1] = new ContactField("home","555-222-1111");
+            phoneNumbers[2] = new ContactField("home","555-222-2222");
+            phoneNumbers[3] = new ContactField(null,"555-333-1234");
+            phoneNumbers[4] = new ContactField("fax","555-444-1234");
+            phoneNumbers[5] = new ContactField("work","555-111-2222");
+            phoneNumbers[6] = new ContactField("mobile","555-555-5555",true);
+            phoneNumbers[7] = new ContactField("work","555-111-3333"); // 3rd 'work' phone will be ignored
+            phoneNumbers[8] = new ContactField("pager","555-666-1111");
+            myContact.phoneNumbers = phoneNumbers;
+        
+            // add address
+            var addresses = [];
+            addresses[0] = new ContactAddress(null, "home", null, "123 Astor Place", "Phoenix", "AZ", "58392", "United States");
+            addresses[1] = new ContactAddress(null, "work", null, "290 Farmers Mills Rd", "Riverdale", "AZ", "58399", "United States");
+            myContact.addresses = addresses;
+
+            // add urls
+            var urls = [];
+            urls[0] = new ContactField(null,"http://my.domain.com");
+            myContact.urls = urls;
+                
+            // add company info
+            var orgs = [];
+            orgs[0] = new ContactOrganization(null, null, "Beach Fitness", null, "Instructor", null);
+            myContact.organizations = orgs;
+        
+            // add categories
+            var categories = [];
+            categories[0] = "Business";
+            categories[1] = "Family"; // DOH! BlackBerry only supports 'Personal' and 'Business'
+            myContact.categories = categories;
+            
+            // add photo
+            var smallImage = document.getElementById('cameraImage');
+            if (smallImage.src && smallImage.src !== "") {
+                var photos = [];
+                photos[0] = new ContactField(null, smallImage.src);
+                myContact.photos = photos;
+            }
+            
+            // saves the contact to device
+            myContact.save(onContactSaved);
+        } 
+
+        function updateContact() {
+            // find a contact to update
+            navigator.contacts.find(
+                ['name','emails'],
+                function(contacts) {
+                    var now = new Date();         
+                    
+                    // we did not specify any filter, so all contacts will be returned
+                    // update first contact and save
+                    if (contacts[0]) {
+                        var c = contacts[0];
+
+                        // update attributes
+                        c.categories = [ 'Personal' ];
+                        c.emails[0].value = "sl@bf.com";
+                        c.note = 'updated: ' + now;
+                        console.log('contact: ' + c.id + ' ' + c.note);
+                    
+                        // remove phone numbers
+                        c.phoneNumbers = [];
+                    
+                        // set field to non-null value to remove from database
+                        c.birthday = "";
+                    
+                        // save changes
+                        c.save(onContactUpdated);
+                    }
+                },
+                fail
+            );
+        }
+      
+        function findContacts() {
+            var filterText = document.getElementById('filterText').value;
+            navigator.contacts.find(
+                ['name', 'emails', 'addresses', 'organizations'], 
+                function(contacts) {
+                    var msg = 'Found ' + contacts.length + ' contacts.';
+                    navigator.notification.alert(msg, null, 'Success');
+                }, 
+                fail,
+                { 
+                    multiple: true, filter: filterText
+                }
+            );
+        }
+
+        function removeContact() {
+            // find a contact to remove
+            navigator.contacts.find(
+                ["*"],
+                // remove first contact
+                function(contacts) {
+                    if (contacts[0]) {
+                        contacts[0].remove(onContactRemoved);
+                    }
+                },
+                fail);
+        }
+
+        //---------------------------------------------------------------------
+        // File
+        //---------------------------------------------------------------------
+        
+        // retrieves root file system entry
+        var getFileSystemRoot = (function() {
+
+            // private
+            var root;
+            
+            // one-time retrieval of the root file system entry
+            var init = function() {
+                window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
+                    function(fileSystem) {
+                        root = fileSystem.root;
+                    }, 
+                    onFileSystemError);
+            };
+            document.addEventListener("deviceready", init, true); 
+
+            // public function returns private root entry
+            return function() {
+                return root;
+            };
+        }()); // execute immediately
+
+        // file system error handler
+        function onFileSystemError(error) {
+            var msg = 'file system error: ' + error.code;
+            navigator.notification.alert(msg, null, 'File System Error');
+        }
+
+        // logs file events
+        function onFileEvent(event) {
+            console.log('file event: ' + event.target.fileName + ' ' + event.type);
+        }
+      
+        // called when error reading file
+        function onFileError(event) {
+            console.log('file error: ' + event.target.error.code);
+        }
+      
+        // called when file is loaded
+        function onFileLoaded(event) {
+            onFileEvent(event);
+            console.log(event.target.result);
+            alert('FileReader.result: ' + event.target.fileName + ': ' + event.target.result);  
+        }
+      
+        // reads a text file
+        function readFileAsText()
+        {   
+            var fileReader = new FileReader(),
+                root = getFileSystemRoot(),
+                file;
+          
+            // set the callbacks
+            fileReader.onloadstart = onFileEvent;
+            fileReader.onprogress = onFileEvent;
+            fileReader.onload = onFileLoaded;
+            fileReader.onloadend = onFileEvent;
+            fileReader.onabort = onFileEvent;
+            fileReader.onerror = onFileError;
+          
+            // read the file
+            file = new File();
+            file.fullPath = root.toURI() + '/cordova.txt';
+            fileReader.readAsText(file);
+        }
+
+        // reads a text file and encodes to Base64
+        function readFileAsDataURL()
+        {   
+            var fileReader = new FileReader(),
+                root = getFileSystemRoot(),
+                file;
+            // set the callbacks
+            fileReader.onloadstart = onFileEvent;
+            fileReader.onload = onFileLoaded;
+            fileReader.onprogress = onFileEvent;
+            fileReader.onloadend = onFileEvent;
+            fileReader.onabort = onFileEvent;
+            fileReader.onerror = onFileError;
+          
+            // read the file
+            file = new File();  
+            file.fullPath = root.toURI() + '/cordova.txt';
+            fileReader.readAsDataURL(file);
+        }
+
+        // called when file is written
+        function onFileWrite(event) {
+            onFileEvent(event);
+            console.log('FileWriter position=' + 
+                event.target.position + ", length=" + event.target.length);
+        }
+
+        // writes a text file to the device
+        function writeFile() 
+        {
+                // root file system entry
+            var root = getFileSystemRoot(),
+            
+                // writes a file
+                write_file = function(writer) {
+                    var lineCount = 1;
+                              
+                    // set the callbacks
+                    writer.onwritestart = onFileEvent;
+                    writer.onprogress = onFileEvent;
+                    writer.onwrite = onFileWrite;
+                    writer.onabort = onFileEvent;
+                    writer.onerror = onFileError;
+                    writer.onwriteend = function(event) {
+                        onFileEvent(event);
+                        lineCount += 1;
+                        if (lineCount <= 3) {
+                            // append a new line   
+                            writer.write('Line ' + lineCount + '.\r\n');  
+                        } 
+                        else {
+                            alert(writer.fileName + 
+                                ' length=' + writer.length + 
+                                ', position=' + writer.position);
+                        }
+                    }
+                    
+                    // append
+                    writer.seek(writer.length);
+          
+                    // write to file
+                    writer.write('Line ' + lineCount + '.\r\n');   
+                },
+                
+                // creates a FileWriter object
+                create_writer = function(fileEntry) {
+                    fileEntry.createWriter(write_file, onFileSystemError);
+                };
+            
+            // create a file and write to it
+            root.getFile('cordova.txt', {create: true}, create_writer, onFileSystemError);
+        }
+      
+        // truncates a file
+        function truncateFile() {
+                // root file system entry
+            var root = getFileSystemRoot(),
+
+                // truncates a file
+                truncate_file = function(writer) {
+                    // set the callbacks
+                    writer.onwritestart = onFileEvent;
+                    writer.onprogress = onFileEvent;
+                    writer.onwrite = onFileWrite;
+                    writer.onabort = onFileEvent;
+                    writer.onerror = onFileError;
+                    writer.onwriteend = function(event) {
+                        onFileEvent(event);
+                        alert(writer.fileName + 
+                            ' length=' + writer.length + 
+                            ', position=' + writer.position);
+                    }
+
+                    // strip off the last 3 bytes of the file
+                    writer.truncate(writer.length-3);
+                },
+                
+                // creates a FileWriter object
+                create_writer = function(fileEntry) {
+                    fileEntry.createWriter(truncate_file, onFileSystemError);
+                };
+                
+            // retrieve a file and truncate it
+            root.getFile('cordova.txt', {create: false}, create_writer, onFileSystemError);
+        }
+        
+        // retrieve root file system
+        function getFileSystem(type, success, error)
+        {
+            var type = type || parseInt(document.getElementById('fsType').value),
+                success = success || function(fileSystem) {
+                    // get the root file system entry
+                    var root = fileSystem.root;
+                    
+                    // display file system path
+                    document.getElementById('fsURI').value = root.toURI();    
+                    
+                    // display root file system entry
+                    displayEntry(root);
+                },
+                fail = error || onFileSystemError;
+            
+            // get file system    
+            window.requestFileSystem(type, 0, success, fail);
+        }
+        
+        // get file system path from input
+        function getFileSystemURI() 
+        {
+            return document.getElementById('fsURI').value;        
+        }
+        
+        // retrieve file system entry from URI
+        function resolveFileSystemURI() 
+        {
+            window.resolveLocalFileSystemURI(getFileSystemURI(), displayEntry, onFileSystemError);
+        }
+        
+        // display file system entry
+        function displayEntry(entry) {
+            navigator.notification.alert(entry, null, 'File System Entry');                    
+        }       
+
+        // retrieve file system entry metadata        
+        function getMetadata()
+        {
+            var displayMetadata = function(metadata) {
+                    navigator.notification.alert(metadata, null, 'Metadata');
+                },
+                callback = function(entry) {
+                    entry.getMetadata(displayMetadata, onFileSystemError);
+                };
+            
+            // look up file system entry and display its metadata
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        } 
+        
+        // retrieve parent directory
+        function getParent() 
+        {
+            var callback = function(entry) {
+                    entry.getParent(displayEntry, onFileSystemError);
+                };
+            
+            // look up file system entry and display its parent
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+        
+        // remove file system entry
+        function removeFileEntry() 
+        {
+            var callback = function(entry) {
+                    entry.remove(function() {
+                        navigator.notification.alert(entry.toURI(), null, 'Entry deleted');                    
+                    }, onFileSystemError);
+                };
+
+            // look up file system entry and attempt to delete it
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        } 
+      
+        // remove directory recursively
+        function removeDirectory(entry) 
+        {
+            var callback = function(entry) {
+                    if (entry.constructor === DirectoryEntry) {
+                        entry.removeRecursively(function() {
+                            navigator.notification.alert(entry.toURI(), null, 'Entry deleted');                    
+                        }, onFileSystemError);
+                    }
+                    else {
+                        navigator.notification.alert(entry.toURI(), null, 'Not a directory');                
+                    }
+                };
+
+            // look up directory entry and recursively remove it
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+        
+        // retrieve or create a file on the file system
+        function getFile() 
+        {
+                // file path to append to file system root
+            var filePath = document.getElementById('filePath').value,
+                // get file entry
+                callback = function(entry) {
+                    entry.getFile(
+                        // file path
+                        filePath,
+                        // options
+                        { create: true },
+                        // success callback
+                        displayEntry,
+                        // error callback
+                        onFileSystemError);
+                };
+
+            // look up file system entry 
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        } 
+        
+        // retrieve or create a directory on the file system
+        function getDirectory() 
+        {
+                // file path
+            var filePath = document.getElementById('filePath').value,
+                // get directory entry
+                callback = function(entry) {
+                    entry.getDirectory(
+                        // file path
+                        filePath,
+                        // options
+                        { create: true },
+                        // success callback
+                        displayEntry,
+                        // error callback
+                        onFileSystemError);
+                };
+
+            // look up file system entry 
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+
+        // list the contents of a directory        
+        function readEntries() 
+        {
+                // file path
+            var filePath = document.getElementById('filePath').value,
+                // list directory entries
+                callback = function(entry) {
+                    var reader = entry.createReader();
+                    reader.readEntries(
+                        function(entries) {
+                            entries[0].getParent(displayEntry, onFileSystemError);
+                        },
+                        onFileSystemError);
+                };
+
+            // look up file system entry 
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+
+        // copy file system entry
+        function copyTo() 
+        {
+                // copy file system entry
+            var callback = function(srcEntry) {
+                    var parent = document.getElementById('parent').value,
+                        newName = document.getElementById('newName').value,
+                        parentEntry = new Entry({fullPath: parent});
+                        srcEntry.copyTo(parentEntry, newName, displayEntry, onFileSystemError);
+                };
+                
+            // look up file system entry and copy it to destination path
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+
+        // move file system entry
+        function moveTo() 
+        {
+                // move file system entry
+            var callback = function(srcEntry) {
+                    var parent = document.getElementById('parent').value,
+                        newName = document.getElementById('newName').value,
+                        parentEntry = new Entry({fullPath: parent});
+                        srcEntry.moveTo(parentEntry, newName, displayEntry, onFileSystemError);
+                };
+
+            // look up file system entry and move it to destination path
+            window.resolveLocalFileSystemURI(getFileSystemURI(), callback, onFileSystemError);
+        }
+
+        //---------------------------------------------------------------------
+        // Media Capture
+        //---------------------------------------------------------------------
+        
+        (function() {
+            // display capture modes
+            var displayCaptureModes = function() {
+                var i, len, mode, modes = "Audio:\n";
+                for (i = 0; len = navigator.device.capture.supportedAudioModes.length, i < len; i += 1) {
+                    mode = navigator.device.capture.supportedAudioModes[i];
+                    modes += mode.type + ';\n';
+                }
+                document.getElementById('supportedAudioModes').innerHTML = modes;
+                modes = "Image:\n";
+                for (i = 0; len = navigator.device.capture.supportedImageModes.length, i < len; i += 1) {
+                    mode = navigator.device.capture.supportedImageModes[i];
+                    modes += mode.type + ',' + mode.width + 'x' + mode.height + ';\n';
+                }
+                document.getElementById('supportedImageModes').innerHTML = modes;
+                modes = "Video:\n";
+                for (i = 0; len = navigator.device.capture.supportedVideoModes.length, i < len; i += 1) {
+                    mode = navigator.device.capture.supportedVideoModes[i];
+                    modes += mode.type + ',' + mode.width + 'x' + mode.height + ';\n';
+                }
+                document.getElementById('supportedVideoModes').innerHTML = modes;
+            };
+            document.addEventListener("deviceready", displayCaptureModes, true); 
+        }());
+        
+        function startAudioCapture() 
+        {
+            navigator.device.capture.captureAudio(function(mediaFiles) {
+                var i, file, len, msg = '';
+                for (i = 0, len = mediaFiles.length; i < len; i += 1) {
+                    msg += mediaFiles[i].fullPath + '\n';
+                }
+                navigator.notification.alert(msg, null, 'Captured audio clips');
+            }, function(error) {
+                navigator.notification.alert('Error code: ' + error.code, null, 'Capture Error');
+            }, {limit:2});
+        }
+        
+        function stopCaptures() 
+        {
+            navigator.device.capture.stopCaptures();
+        }
+        
+        function startImageCapture() 
+        {
+            navigator.device.capture.captureImage(function(mediaFiles) {
+                var i, file, len, msg = '';
+                for (i = 0, len = mediaFiles.length; i < len; i += 1) {
+                    msg += mediaFiles[i].fullPath + '\n';
+                }
+                navigator.notification.alert(msg, null, 'Captured images');
+            }, function(error) {
+                navigator.notification.alert('Error code: ' + error.code, null, 'Capture Error');
+            }, {limit:2});
+        }
+                
+        function startVideoCapture() 
+        {
+            navigator.device.capture.captureVideo(function(mediaFiles) {
+                var i, file, len, msg = '';
+                for (i = 0, len = mediaFiles.length; i < len; i += 1) {
+                    msg += mediaFiles[i].fullPath + '\n';
+                }
+                navigator.notification.alert(msg, null, 'Captured video clips');
+            }, function(error) {
+                navigator.notification.alert('Error code: ' + error.code, null, 'Capture Error');
+            }, {limit:2});
+        }
+
+    </script>
+    <title>Cordova API Sample</title>
+  </head>
+  <body onload="init()" onunload="unload()">
+  
+    <h3>window.device</h3>
+    <p id="window.device.platform">[window.device.platform]</p>
+    <p id="window.device.version">[window.device.version]</p>
+    <p id="window.device.uuid">[window.device.uuid]</p>
+    <p id="window.device.cordova">[window.device.cordova]</p>
+
+    <h3>window.notification</h3>
+    <input type="button" value="Beep" onclick="callBeep();return false;" />
+    <input type="button" value="Vibrate" onclick="callVibrate();return false;" />
+    <input type="button" value="Alert" onclick="callAlert();return false;" />
+    <input type="button" value="Confirm" onclick="callConfirm();return false;" />
+    
+    <h3>navigator.network</h3>
+    <p id="networkStatus">[navigator.network.connection.type]</p>
+
+    <h3>navigator.geolocation</h3>
+    <dl id="location-data">
+      <dt>Latitude:</dt><dd id="lat">&nbsp;</dd>
+      <dt>Longitude:</dt><dd id="long">&nbsp;</dd>
+    </dl>
+    <p>Timeout:<input type="text" id="geo_timeout" /></p>
+    <p>Max age:<input type="text" id="geo_maxage" /></p>
+    <input type="button" value="Get Location" onclick="getLocation();return false;" /> 
+    <input type="button" value="Watch Location" onclick="watchLocation();return false;" /> 
+    <input type="button" value="Clear Geo" onclick="clearLocationWatch();return false;" /> 
+
+    <h3>navigator.accelerometer</h3>
+    <dl id="accel-data">
+      <dt>X:</dt><dd id="x">&nbsp;</dd>
+      <dt>Y:</dt><dd id="y">&nbsp;</dd>
+      <dt>Z:</dt><dd id="z">&nbsp;</dd>
+    </dl>
+    <input type="button" value="Get Acceleration" onclick="getAcceleration();return false;" /> 
+    <input type="button" value="Watch Acceleration" onclick="watchAcceleration();return false;" /> 
+    <input type="button" value="Clear Watch" onclick="clearAccelWatch();return false;" /> 
+    
+    <h3>navigator.camera</h3>
+    <input type="button" value="Get Photo (Data)" onclick="capturePhoto();return false;" /> 
+    <input type="button" value="Get Photo (URI)" onclick="capturePhotoURI();return false;" /> 
+    <img style="display:none;width:120px;height:120px;" id="cameraImage" src="" />
+    <p id="uploadProgress"></p>
+    <input style="display:none;" id="uploadButton" type="button" value="Upload" onclick="uploadImage();return false;" />     
+
+    <h3>navigator.contacts</h3>
+    <input type="button" value="Create Contact" onclick="createContact();return false;" /> 
+    <input type="button" value="Update Contact" onclick="updateContact();return false;" /> 
+    <input type="button" value="Remove Contact" onclick="removeContact();return false;" />
+    <p>
+    <input type="text" id="filterText" />
+    <input type="button" value="Find Contacts" onclick="findContacts();return false;" />
+    </p>
+
+    <h3>FileReader</h3>
+    <input type="button" value="Read File (Text)" onclick="readFileAsText();return false;" /> 
+    <input type="button" value="Read File (Base64)" onclick="readFileAsDataURL();return false;" /> 
+    <h3>FileWriter</h3>
+    <input type="button" value="Write File" onclick="writeFile();return false;" />
+    <input type="button" value="Truncate File" onclick="truncateFile();return false;" />
+    <h3>File and Directory</h3>
+    <p>    
+    <select id="fsType">
+        <option value="0">Temporary</option>
+        <option value="1">Persistent</option>
+        <option value="-1">Test</option>
+    </select>
+    <input type="button" value="Get File System" onclick="getFileSystem();return false;" />    
+    </p>    
+    <p>    
+    <label>URI:</label><input type="text" id="fsURI"/>
+    <input type="button" value="Resolve URI" onclick="resolveFileSystemURI();return false;" />    
+    <input type="button" value="Get MetaData" onclick="getMetadata();return false;" />    
+    <input type="button" value="Get Parent" onclick="getParent();return false;" />    
+    <input type="button" value="Remove" onclick="removeFileEntry();return false;" />
+    <input type="button" value="Remove Dir" onclick="removeDirectory();return false;" />
+    </p>    
+    <p>
+    <label id="uriLabel">&lt;URI&gt;/</label>
+    <input type="text" id="filePath" />
+    <input type="button" value="Get File" onclick="getFile();return false;" />    
+    <input type="button" value="Get Dir" onclick="getDirectory();return false;" />    
+    <input type="button" value="List" onclick="readEntries();return false;" />    
+    </p>
+    <p>
+    <label>parent:</label>
+    <input type="text" id="parent" />
+    <label>newName:</label>
+    <input type="text" id="newName" />
+    <input type="button" value="Copy To" onclick="copyTo();return false;" />    
+    <input type="button" value="Move To" onclick="moveTo();return false;" />    
+    </p>
+    
+    <h3>Media Capture</h3>
+    <p id="supportedAudioModes">[supportedAudioModes]</p>
+    <p id="supportedImageModes">[supportedImageModes]</p>
+    <p id="supportedVideoModes">[supportedVideoModes]</p>
+    <input type="button" value="Audio" onclick="startAudioCapture();return false;" />
+    <input type="button" value="Image" onclick="startImageCapture();return false;" />
+    <input type="button" value="Video" onclick="startVideoCapture();return false;" />
+
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/templates/project/www/json2.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/json2.js b/bin/templates/project/www/json2.js
new file mode 100644
index 0000000..c52b92a
--- /dev/null
+++ b/bin/templates/project/www/json2.js
@@ -0,0 +1,482 @@
+/*
+    http://www.JSON.org/json2.js
+    2010-03-20
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+
+
+    This file creates a global JSON object containing two methods: stringify
+    and parse.
+
+        JSON.stringify(value, replacer, space)
+            value       any JavaScript value, usually an object or array.
+
+            replacer    an optional parameter that determines how object
+                        values are stringified for objects. It can be a
+                        function or an array of strings.
+
+            space       an optional parameter that specifies the indentation
+                        of nested structures. If it is omitted, the text will
+                        be packed without extra whitespace. If it is a number,
+                        it will specify the number of spaces to indent at each
+                        level. If it is a string (such as '\t' or '&nbsp;'),
+                        it contains the characters used to indent at each level.
+
+            This method produces a JSON text from a JavaScript value.
+
+            When an object value is found, if the object contains a toJSON
+            method, its toJSON method will be called and the result will be
+            stringified. A toJSON method does not serialize: it returns the
+            value represented by the name/value pair that should be serialized,
+            or undefined if nothing should be serialized. The toJSON method
+            will be passed the key associated with the value, and this will be
+            bound to the value
+
+            For example, this would serialize Dates as ISO strings.
+
+                Date.prototype.toJSON = function (key) {
+                    function f(n) {
+                        // Format integers to have at least two digits.
+                        return n < 10 ? '0' + n : n;
+                    }
+
+                    return this.getUTCFullYear()   + '-' +
+                         f(this.getUTCMonth() + 1) + '-' +
+                         f(this.getUTCDate())      + 'T' +
+                         f(this.getUTCHours())     + ':' +
+                         f(this.getUTCMinutes())   + ':' +
+                         f(this.getUTCSeconds())   + 'Z';
+                };
+
+            You can provide an optional replacer method. It will be passed the
+            key and value of each member, with this bound to the containing
+            object. The value that is returned from your method will be
+            serialized. If your method returns undefined, then the member will
+            be excluded from the serialization.
+
+            If the replacer parameter is an array of strings, then it will be
+            used to select the members to be serialized. It filters the results
+            such that only members with keys listed in the replacer array are
+            stringified.
+
+            Values that do not have JSON representations, such as undefined or
+            functions, will not be serialized. Such values in objects will be
+            dropped; in arrays they will be replaced with null. You can use
+            a replacer function to replace those with JSON values.
+            JSON.stringify(undefined) returns undefined.
+
+            The optional space parameter produces a stringification of the
+            value that is filled with line breaks and indentation to make it
+            easier to read.
+
+            If the space parameter is a non-empty string, then that string will
+            be used for indentation. If the space parameter is a number, then
+            the indentation will be that many spaces.
+
+            Example:
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}]);
+            // text is '["e",{"pluribus":"unum"}]'
+
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+            text = JSON.stringify([new Date()], function (key, value) {
+                return this[key] instanceof Date ?
+                    'Date(' + this[key] + ')' : value;
+            });
+            // text is '["Date(---current time---)"]'
+
+
+        JSON.parse(text, reviver)
+            This method parses a JSON text to produce an object or array.
+            It can throw a SyntaxError exception.
+
+            The optional reviver parameter is a function that can filter and
+            transform the results. It receives each of the keys and values,
+            and its return value is used instead of the original value.
+            If it returns what it received, then the structure is not modified.
+            If it returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. Values that look like ISO date strings will
+            // be converted to Date objects.
+
+            myData = JSON.parse(text, function (key, value) {
+                var a;
+                if (typeof value === 'string') {
+                    a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+                    if (a) {
+                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+                            +a[5], +a[6]));
+                    }
+                }
+                return value;
+            });
+
+            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+                var d;
+                if (typeof value === 'string' &&
+                        value.slice(0, 5) === 'Date(' &&
+                        value.slice(-1) === ')') {
+                    d = new Date(value.slice(5, -1));
+                    if (d) {
+                        return d;
+                    }
+                }
+                return value;
+            });
+
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+    lastIndex, length, parse, prototype, push, replace, slice, stringify,
+    test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+    this.JSON = {};
+}
+
+(function () {
+
+    function f(n) {
+        // Format integers to have at least two digits.
+        return n < 10 ? '0' + n : n;
+    }
+
+    if (typeof Date.prototype.toJSON !== 'function') {
+
+        Date.prototype.toJSON = function (key) {
+
+            return isFinite(this.valueOf()) ?
+                   this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z' : null;
+        };
+
+        String.prototype.toJSON =
+        Number.prototype.toJSON =
+        Boolean.prototype.toJSON = function (key) {
+            return this.valueOf();
+        };
+    }
+
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        gap,
+        indent,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        rep;
+
+
+    function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+        escapable.lastIndex = 0;
+        return escapable.test(string) ?
+            '"' + string.replace(escapable, function (a) {
+                var c = meta[a];
+                return typeof c === 'string' ? c :
+                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            }) + '"' :
+            '"' + string + '"';
+    }
+
+
+    function str(key, holder) {
+
+// Produce a string from holder[key].
+
+        var i,          // The loop counter.
+            k,          // The member key.
+            v,          // The member value.
+            length,
+            mind = gap,
+            partial,
+            value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+        if (value && typeof value === 'object' &&
+                typeof value.toJSON === 'function') {
+            value = value.toJSON(key);
+        }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+        if (typeof rep === 'function') {
+            value = rep.call(holder, key, value);
+        }
+
+// What happens next depends on the value's type.
+
+        switch (typeof value) {
+        case 'string':
+            return quote(value);
+
+        case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+            return isFinite(value) ? String(value) : 'null';
+
+        case 'boolean':
+        case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+            return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+        case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+            if (!value) {
+                return 'null';
+            }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+            gap += indent;
+            partial = [];
+
+// Is the value an array?
+
+            if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                length = value.length;
+                for (i = 0; i < length; i += 1) {
+                    partial[i] = str(i, value) || 'null';
+                }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+                v = partial.length === 0 ? '[]' :
+                    gap ? '[\n' + gap +
+                            partial.join(',\n' + gap) + '\n' +
+                                mind + ']' :
+                          '[' + partial.join(',') + ']';
+                gap = mind;
+                return v;
+            }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+            if (rep && typeof rep === 'object') {
+                length = rep.length;
+                for (i = 0; i < length; i += 1) {
+                    k = rep[i];
+                    if (typeof k === 'string') {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+            v = partial.length === 0 ? '{}' :
+                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                        mind + '}' : '{' + partial.join(',') + '}';
+            gap = mind;
+            return v;
+        }
+    }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+    if (typeof JSON.stringify !== 'function') {
+        JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+            var i;
+            gap = '';
+            indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+            if (typeof space === 'number') {
+                for (i = 0; i < space; i += 1) {
+                    indent += ' ';
+                }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+            } else if (typeof space === 'string') {
+                indent = space;
+            }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+            rep = replacer;
+            if (replacer && typeof replacer !== 'function' &&
+                    (typeof replacer !== 'object' ||
+                     typeof replacer.length !== 'number')) {
+                throw new Error('JSON.stringify');
+            }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+            return str('', {'': value});
+        };
+    }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+    if (typeof JSON.parse !== 'function') {
+        JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+            var j;
+
+            function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+                var k, v, value = holder[key];
+                if (value && typeof value === 'object') {
+                    for (k in value) {
+                        if (Object.hasOwnProperty.call(value, k)) {
+                            v = walk(value, k);
+                            if (v !== undefined) {
+                                value[k] = v;
+                            } else {
+                                delete value[k];
+                            }
+                        }
+                    }
+                }
+                return reviver.call(holder, key, value);
+            }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+            text = String(text);
+            cx.lastIndex = 0;
+            if (cx.test(text)) {
+                text = text.replace(cx, function (a) {
+                    return '\\u' +
+                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                });
+            }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+            if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+                return typeof reviver === 'function' ?
+                    walk({'': j}, '') : j;
+            }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+            throw new SyntaxError('JSON.parse');
+        };
+    }
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/templates/project/www/plugins.xml
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/plugins.xml b/bin/templates/project/www/plugins.xml
new file mode 100644
index 0000000..eed2e5b
--- /dev/null
+++ b/bin/templates/project/www/plugins.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-->
+<plugins>
+  <plugin name="App"            value="org.apache.cordova.app.App"/>
+  <plugin name="Device"         value="org.apache.cordova.device.Device"/>
+  <plugin name="Camera"         value="org.apache.cordova.camera.Camera"/>
+  <plugin name="NetworkStatus"  value="org.apache.cordova.network.Network"/>
+  <plugin name="Notification"   value="org.apache.cordova.notification.Notification"/>
+  <plugin name="Accelerometer"  value="org.apache.cordova.accelerometer.Accelerometer"/>
+  <plugin name="Geolocation"    value="org.apache.cordova.geolocation.Geolocation"/>
+  <plugin name="File"           value="org.apache.cordova.file.FileManager"/>
+  <plugin name="FileTransfer"   value="org.apache.cordova.http.FileTransfer"/>
+  <plugin name="Contacts"       value="org.apache.cordova.pim.Contact"/>
+  <plugin name="Capture"        value="org.apache.cordova.capture.MediaCapture"/>
+  <plugin name="Battery"        value="org.apache.cordova.battery.Battery"/>
+  <plugin name="Media"          value="org.apache.cordova.media.Media"/>
+</plugins>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/templates/project/www/resources/icon.png
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/resources/icon.png b/bin/templates/project/www/resources/icon.png
new file mode 100644
index 0000000..4d27634
Binary files /dev/null and b/bin/templates/project/www/resources/icon.png differ

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/templates/project/www/resources/loading_foreground.png
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/resources/loading_foreground.png b/bin/templates/project/www/resources/loading_foreground.png
new file mode 100644
index 0000000..b548bdc
Binary files /dev/null and b/bin/templates/project/www/resources/loading_foreground.png differ

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/test
----------------------------------------------------------------------
diff --git a/bin/test b/bin/test
new file mode 100755
index 0000000..bc95cc1
--- /dev/null
+++ b/bin/test
@@ -0,0 +1,41 @@
+#! /bin/sh
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+#
+#
+set -e
+
+VERSION=$(cat ./VERSION)
+
+# get the latest mobile-spec
+git clone https://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec.git
+
+# clobber test if it exists
+if [ -e ./test ]
+then
+    rm -rf ./test
+fi
+
+# generate a working proj
+./bin/create ./test CordovaTest
+
+# kill the default app and replace it w/ mobile-spec
+rm ./test/www/index.html
+mv ./incubator-cordova-mobile-spec/* ./test/www/.
+
+# build it, launch it and start logging on stdout
+cd ./test && ./cordova/debug && ./cordova/log

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/tests/autotest.coffee
----------------------------------------------------------------------
diff --git a/bin/tests/autotest.coffee b/bin/tests/autotest.coffee
new file mode 100644
index 0000000..1ee4c39
--- /dev/null
+++ b/bin/tests/autotest.coffee
@@ -0,0 +1,24 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+
+exports['you are sane'] = (test) ->
+  test.expect 1
+  test.ok true, "this assertion should always pass"
+  test.done()

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/tests/create.coffee
----------------------------------------------------------------------
diff --git a/bin/tests/create.coffee b/bin/tests/create.coffee
new file mode 100644
index 0000000..6c87af4
--- /dev/null
+++ b/bin/tests/create.coffee
@@ -0,0 +1,40 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+util = require 'util'
+exec = require('child_process').exec
+path = require 'path'
+
+exports['default example project is generated'] = (test) ->
+  test.expect 1
+  exec './bin/create', (error, stdout, stderr) ->
+    test.ok true, "this assertion should pass" unless error?
+    test.done()
+
+exports['default example project has a ./.cordova folder'] = (test) ->
+  test.expect 1
+  path.exists './example/.cordova', (exists) ->
+    test.ok exists, 'the cordova folder exists'
+    test.done()
+
+exports['default example project has a /cordova folder'] = (test) ->
+  test.expect 1
+  path.exists './example/cordova', (exists) ->
+    test.ok exists, 'the other cordova folder exists'
+    test.done()

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/tests/debug.coffee
----------------------------------------------------------------------
diff --git a/bin/tests/debug.coffee b/bin/tests/debug.coffee
new file mode 100644
index 0000000..a5d9eba
--- /dev/null
+++ b/bin/tests/debug.coffee
@@ -0,0 +1,18 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/bin/tests/test.coffee
----------------------------------------------------------------------
diff --git a/bin/tests/test.coffee b/bin/tests/test.coffee
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index ae13d67..be849fc 100644
--- a/build.xml
+++ b/build.xml
@@ -27,8 +27,8 @@
     
     <!-- LOAD PROPERTIES -->
     
-    <property name="template.project.dir" location="template/project" />
-    <property name="template.dist.dir"    location="template/dist" />
+    <property name="template.project.dir" location="bin/templates/project" />
+    <property name="template.dist.dir"    location="bin/templates/dist" />
     
     <property name="build.dir"            location="build" />
     <property name="update.dir"           value="lib/cordova.${version}" />

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/5f3fbff2/template/dist/README.md
----------------------------------------------------------------------
diff --git a/template/dist/README.md b/template/dist/README.md
deleted file mode 100644
index 35a8393..0000000
--- a/template/dist/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-Cordova BlackBerry Distribution
-===============================
-
-Cordova BlackBerry is a framework that allows for Cordova based projects to be built for the [BlackBerry WebWorks Platform](https://bdsc.webapps.blackberry.com/html5/). Cordova based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.  The Cordova BlackBerry project allows web developers to develop applications targeting BlackBerry OS 5.0+ and PlayBook devices using the common [Cordova API](http://docs.phonegap.com).
-
-Apache Cordova is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator project. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.
-
-Pre-requisites
---------------
-
-- Windows XP (32-bit) or Windows 7 (32-bit and 64-bit) or Mac OSX 10.6.4+
-- Java JDK 1.5
-- Apache ANT
-- [BlackBerry WebWorks SDK](https://bdsc.webapps.blackberry.com/html5/download/sdk)
-- PlayBook development requires [Adobe Air SDK](http://www.adobe.com/devnet/air/air-sdk-download.html)
-
-Directory Structure
--------------------
-
-    sample/ ... Ready-to-run sample project
-    www/ ...... Barebones project assets
-
-### Ready-to-Run Sample Project
-
-The quickest way to get started with Cordova BlackBerry is to make a copy of the `sample` folder. The `sample` folder is a complete Cordova BlackBerry project including build scripts. Copy the `sample` folder to a desired location to create a new Cordova BlackBerry project.
-
-#### Building and Deploying a Project
-
-The build scripts included in the `sample` folder automate common tasks, such as compiling your project, and deploying it to simulators or devices.  To see what options are available, use:
-
-    $ cd C:\development\my_new_project
-    $ ant help
-
-Every command is in the form `ant TARGET COMMAND [options]`, where
-target is either `blackberry` or `playbook`.
-
-To build your project into a deployable application (.cod/.jad) file:
-
-    $ ant TARGET build
-
-To build your project and load it in a BlackBerry simulator:
-
-    $ ant TARGET load-simulator
-
-To build your project and load it onto a USB-attached device:
-
-    $ ant TARGET load-device
-
-### Barebones Project Assets
-
-The `www` folder contains the Cordova specific assets that must be available in a BlackBerry WebWorks project.  If you have an existing BlackBerry WebWorks project, copy/merge these files into your project to enable the project for Cordova.
-
-    ext/cordova.jar     - Native Cordova API implementations for smartphones.
-    ext-air/            - PlayBook Adobe Air extensions for Cordova API.
-    playbook/cordova.js - PlayBook Cordova JavaScript API.
-    cordova.js          - Smartphone Cordova JavaScript API.
-    config.xml          - BlackBerry WebWorks configuration file.
-    plugins.xml         - Cordova plugin configuration file.
-
-`config.xml` is a sample that you are free to alter or merge with an existing BlackBerry WebWorks configuration file. The necessary Cordova sections are contained in the `<feature>` and `<access>` sections:
-
-    <!-- Cordova API -->
-    <feature ... />
-    <feature ... />
-    
-    <!-- Cordova API -->
-    <access ... />
-    <access ... />
-
-Frequently Asked Questions
---------------------------
-
-__Q: My simulator screen is not refreshing and I see blocks on a clicked position.__
-
-__A:__ Windows 7 and the simulator's graphics acceleration do not mix. On the simulator, set View -> Graphics Acceleration to Off.
-
-__Q: When I use the Cordova [Camera.getPicture API](http://docs.phonegap.com/phonegap_camera_camera.md.html#camera.getPicture) on my device, the camera never returns to my application.  Why does this happen?__
-
-__A:__ Cordova uses a JavaScript Extension to invoke the native camera application so the user can take a picture.  When the picture is taken, Cordova will close the native camera application by emulating a key injection (pressing the back/escape button).  On a physical device, users will have to set permissions to allow the application to simulate key injections.  Setting application permissions is device-specific.  On a Storm2 (9550), for example, select the BlackBerry button from the Home screen to get to All Applications screen, then Options > Applications > Your Application.  Then select Edit Default Permissions > Interactions > Input Simulation and set it to 'Allow'.  Save your changes.
-
-__Q: None of the Cordova APIs are working, why is that?__
-
-__A:__ You probably need to update your plugins.xml file in the root of your application.
-
-Additional Information
-----------------------
-- [Cordova home](http://incubator.apache.org/cordova/)
-- [Cordova Documentation](http://docs.phonegap.com)
-- [Cordova Issue Tracker](https://issues.apache.org/jira/browse/CB)
-- [BlackBerry WebWorks Framework](https://bdsc.webapps.blackberry.com/html5/)


Mime
View raw message