Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

The 2.3.1 version of the BB SDK for Smartphone

  • Loading branch information...
commit 1352a619a296bffdd94b1d4aa7c2e682f6f879b8 1 parent d9013cd
Daniel Mateescu authored
2  api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java
View
@@ -41,7 +41,7 @@ public Object execute( Object thiz, Object[] args ) throws Exception {
ScriptableFunction callback = (ScriptableFunction) args[ 1 ];
// create dialog
- Runnable dr = DialogRunnableFactory.getColorPickerRunnable( initialColor, callback, thiz );
+ Runnable dr = DialogRunnableFactory.getColorPickerRunnable( initialColor, callback );
// queue
UiApplication.getUiApplication().invokeLater( dr );
79 api/dialog/src/main/java/blackberry/ui/dialog/CustomAskAsyncFunction.java
View
@@ -0,0 +1,79 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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.
+*/
+package blackberry.ui.dialog;
+
+import net.rim.device.api.script.Scriptable;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.ui.UiApplication;
+import blackberry.core.FunctionSignature;
+import blackberry.core.ScriptableFunctionBase;
+
+/**
+ * Implementation of asynchronous custom ask function (blackberry.ui.dialog.customAskAsync)
+ *
+ * @author dmateescu
+ *
+ */
+public class CustomAskAsyncFunction extends ScriptableFunctionBase {
+
+ public static final String NAME = "customAskAsync";
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[])
+ */
+ public Object execute( Object thiz, Object[] args ) throws Exception {
+ String message;
+ String[] buttons;
+ // the default value of the default choice. The developer cannot change it.
+ final int defaultChoice = 0;
+ // callback function
+ ScriptableFunction callback = (ScriptableFunction) args[ 2 ];
+ // the default value of the global status. The developer cannot change it.
+ final boolean global = false;
+ // message
+ message = (String) args[ 0 ];
+ // choices & values
+ Scriptable stringArray = (Scriptable) args[ 1 ];
+ int count = stringArray.getElementCount();
+ buttons = new String[ count ];
+ for( int i = 0; i < count; i++ ) {
+ buttons[ i ] = stringArray.getElement( i ).toString();
+ }
+
+ Runnable dr = DialogRunnableFactory.getCustomAskRunnable( message, buttons, defaultChoice, global, callback );
+ // queue
+ UiApplication.getUiApplication().invokeLater( dr );
+ // return value
+ return Scriptable.UNDEFINED;
+ }
+
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures()
+ */
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature fs = new FunctionSignature( 3 );
+ // message
+ fs.addParam( String.class, true );
+ // choices
+ fs.addParam( Scriptable.class, true );
+ // callback
+ fs.addParam( ScriptableFunction.class, true );
+ // filler
+ fs.addParam( Object.class, false );
+ return new FunctionSignature[] { fs };
+ }
+}
2  api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java
View
@@ -47,7 +47,7 @@ public Object execute(Object thiz, Object[] args) throws Exception {
String min = (String)options.getField("min");
String max = (String)options.getField("max");
- Runnable dr = DialogRunnableFactory.getDateTimeRunnable(type, value, min, max, callback, thiz);
+ Runnable dr = DialogRunnableFactory.getDateTimeRunnable(type, value, min, max, callback);
// queue
UiApplication.getUiApplication().invokeLater(dr);
3  api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java
View
@@ -17,7 +17,6 @@
import java.util.Hashtable;
-import net.rim.device.api.script.ScriptEngine;
import net.rim.device.api.script.Scriptable;
import net.rim.device.api.ui.component.Dialog;
@@ -52,7 +51,9 @@ public DialogNamespace() {
_fields = new Hashtable();
_fields.put( StandardAskFunction.NAME, new StandardAskFunction() );
+ _fields.put( StandardAskAsyncFunction.NAME, new StandardAskAsyncFunction());
_fields.put( CustomAskFunction.NAME, new CustomAskFunction() );
+ _fields.put(CustomAskAsyncFunction.NAME, new CustomAskAsyncFunction());
_fields.put( SelectAsyncFunction.NAME, new SelectAsyncFunction() );
_fields.put( DateTimeAsyncFunction.NAME, new DateTimeAsyncFunction() );
_fields.put( ColorPickerAsyncFunction.NAME, new ColorPickerAsyncFunction() );
119 api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java
View
@@ -18,37 +18,92 @@
import java.util.Vector;
-import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.script.ScriptableFunction;
import net.rim.device.api.script.ScriptableImpl;
-
+import net.rim.device.api.system.DeviceInfo;
+import net.rim.device.api.ui.component.Dialog;
+import blackberry.ui.dialog.color.ColorPickerDialog;
import blackberry.ui.dialog.datetime.DateTimeDialog;
-import blackberry.ui.dialog.IWebWorksDialog;
import blackberry.ui.dialog.select.SelectDialog;
-import blackberry.ui.dialog.color.ColorPickerDialog;
+/**
+ * Factory class for running dialogs asynchronously
+ *
+ */
public class DialogRunnableFactory {
- public static Runnable getDateTimeRunnable( String type, String value, String min, String max, ScriptableFunction callback,
- Object thiz ) {
+ /**
+ * Factory method for running an asynchronous DateTime dialog
+ * @param type the dialog's type
+ * @param value the value
+ * @param min the minimum value
+ * @param max the maximum value
+ * @param callback the callback function
+ * @return the Runnable responsible for opening the dialog
+ */
+ public static Runnable getDateTimeRunnable( String type, String value, String min, String max, ScriptableFunction callback) {
IWebWorksDialog d = new DateTimeDialog( type, value, min, max );
- return new DialogRunnable( d, callback, thiz );
+ return new DialogRunnable( d, callback );
}
- public static Runnable getColorPickerRunnable( int initialColor, ScriptableFunction callback, Object thiz ) {
+ /**
+ * Factory method for running an asynchronous ColorPicker dialog
+ * @param initialColor the initial color
+ * @param callback the callback function
+ * @return the Runnable responsible for opening the dialog
+ */
+ public static Runnable getColorPickerRunnable( int initialColor, ScriptableFunction callback ) {
ColorPickerDialog d = new ColorPickerDialog( initialColor );
- return new DialogRunnable( d, callback, thiz );
+ return new DialogRunnable( d, callback );
}
- public static Runnable getSelectRunnable(boolean allowMultiple, String[] labels, boolean[] enabled, boolean[] selected, int[] types, ScriptableFunction callback, Object thiz) {
+ /**
+ * Factory method for running an asynchronous Select dialog
+ * @param allowMultiple flag indicating whether multiple values are allowed
+ * @param labels the labels
+ * @param enabled the enabled values
+ * @param selected the selected values
+ * @param types the types of the values
+ * @param callback the callback function
+ * @return the Runnable responsible for opening the dialog
+ */
+ public static Runnable getSelectRunnable(boolean allowMultiple, String[] labels, boolean[] enabled, boolean[] selected, int[] types, ScriptableFunction callback) {
IWebWorksDialog d = new SelectDialog(allowMultiple, labels, enabled, selected, types);
- return new DialogRunnable(d, callback, thiz);
+ return new DialogRunnable(d, callback);
+ }
+
+ /**
+ * Factory method for running an asynchronous CustomAsk dialog
+ * @param message the message to be displayed in the dialog
+ * @param buttons the choices presented as buttons
+ * @param values the values of the choices
+ * @param defaultChoice the default choice
+ * @param global the global status
+ * @param callback the callback function
+ * @return the Runnable responsible for opening the dialog
+ */
+ public static Runnable getCustomAskRunnable(String message, String[] buttons, int defaultChoice, boolean global /* style, false */, ScriptableFunction callback) {
+ Dialog d = new Dialog( message, buttons, null, defaultChoice, null /* bitmap */, global ? Dialog.GLOBAL_STATUS : 0 /* style */);
+ return new DialogAsyncRunnable( d, callback );
+ }
+
+ /**
+ * Factory method for running an asynchronous StandardAsk dialog
+ * @param message the message to be displayed in the dialog
+ * @param type the dialog's type
+ * @param defaultChoice
+ * @param global the global status
+ * @param callback the callback function
+ * @return the Runnable responsible for running the dialog
+ */
+ public static Runnable getStandardAskRunnable(String message, int type, int defaultChoice, boolean global /* style, false */, ScriptableFunction callback) {
+ Dialog d = new Dialog( type, message, defaultChoice, null /* bitmap */, global ? Dialog.GLOBAL_STATUS : 0 /* style */);
+ return new DialogAsyncRunnable(d, callback);
}
private static class DialogRunnable implements Runnable {
private IWebWorksDialog _dialog;
private ScriptableFunction _callback;
- private Object _context;
/**
* Constructs a <code>DialogRunnable</code> object.
@@ -57,13 +112,10 @@ public static Runnable getSelectRunnable(boolean allowMultiple, String[] labels,
* The dialog
* @param callback
* The callback
- * @param context
- * The context in which the callback executes (its "this" object)
*/
- DialogRunnable( IWebWorksDialog dialog, ScriptableFunction callback, Object context ) {
+ DialogRunnable( IWebWorksDialog dialog, ScriptableFunction callback ) {
_dialog = dialog;
_callback = callback;
- _context = context;
}
@@ -106,4 +158,39 @@ public void run() {
}
}
}
+
+ private static class DialogAsyncRunnable implements Runnable {
+ private Dialog _dialog;
+ private ScriptableFunction _callback;
+ private Integer _dialogValue;
+
+ /**
+ * Constructs a <code>DialogRunnable</code> object.
+ *
+ * @param dialog
+ * The dialog
+ * @param callback
+ * The callback
+ */
+ DialogAsyncRunnable( Dialog dialog, ScriptableFunction callback ) {
+ _dialog = dialog;
+ _callback = callback;
+ }
+
+ /**
+ * Run the dialog.
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ _dialogValue = new Integer( _dialog.doModal() );
+ // get object's string as all ecma primitives will return a valid string representation of themselves
+ Object retVal = _dialogValue.toString();
+ try {
+ _callback.invoke( null, new Object[] { retVal } );
+ } catch( Exception e ) {
+ throw new RuntimeException( "Invoke callback failed: " + e.getMessage() );
+ }
+ }
+ }
}
7 api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java
View
@@ -15,17 +15,12 @@
*/
package blackberry.ui.dialog;
-import net.rim.device.api.script.ScriptEngine;
import net.rim.device.api.script.Scriptable;
import net.rim.device.api.script.ScriptableFunction;
import net.rim.device.api.ui.UiApplication;
-import blackberry.common.util.json4j.JSONArray;
import blackberry.core.FunctionSignature;
import blackberry.core.ScriptableFunctionBase;
-import blackberry.ui.dialog.DialogRunnableFactory;
-import blackberry.ui.dialog.select.SelectDialog;
-
/**
* Implementation of asynchronous selection dialog
*
@@ -56,7 +51,7 @@ public Object execute( Object thiz, Object[] args ) throws Exception {
populateChoiceStateArrays( choices, labels, enabled, selected, types, allowMultiple );
- Runnable dr = DialogRunnableFactory.getSelectRunnable(allowMultiple, labels, enabled, selected, types, callback, thiz);
+ Runnable dr = DialogRunnableFactory.getSelectRunnable(allowMultiple, labels, enabled, selected, types, callback);
// queue
UiApplication.getUiApplication().invokeLater(dr);
77 api/dialog/src/main/java/blackberry/ui/dialog/StandardAskAsyncFunction.java
View
@@ -0,0 +1,77 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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.
+*/
+package blackberry.ui.dialog;
+
+import net.rim.device.api.script.Scriptable;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.ui.UiApplication;
+import net.rim.device.api.ui.component.Dialog;
+import blackberry.core.FunctionSignature;
+import blackberry.core.ScriptableFunctionBase;
+
+/**
+ * Implementation of asynchronous standard ask function (blackberry.ui.dialog.standardAskAsync)
+ *
+ * @author dmateescu
+ *
+ */
+public class StandardAskAsyncFunction extends ScriptableFunctionBase {
+
+ public static final String NAME = "standardAskAsync";
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[])
+ */
+ public Object execute( Object thiz, Object[] args ) throws Exception {
+ String message;
+ int type;
+ final boolean global = false;
+
+ // message
+ message = (String) args[ 0 ];
+ // type
+ type = ( (Integer) args[ 1 ] ).intValue();
+ if( type < Dialog.D_OK || type > Dialog.D_OK_CANCEL ) {
+ throw new IllegalArgumentException();
+ }
+ // default choice
+ final int defaultChoice = DialogNamespace.getDefaultChoice( type );
+ //callback function
+ ScriptableFunction callback = (ScriptableFunction) args[ 2 ];
+
+ Runnable dr = DialogRunnableFactory.getStandardAskRunnable(message, type, defaultChoice, global, callback);
+ // queue
+ UiApplication.getUiApplication().invokeLater(dr);
+ // return value
+ return Scriptable.UNDEFINED;
+ }
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures()
+ */
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature fs = new FunctionSignature( 3 );
+ // message
+ fs.addParam( String.class, true );
+ // type
+ fs.addParam( Integer.class, true );
+ // callback
+ fs.addParam( ScriptableFunction.class, true );
+ // filler
+ fs.addParam( Object.class, false );
+ return new FunctionSignature[] { fs };
+ }
+}
59 api/system.event/src/main/java/blackberry/system/event/KeyPressHandler.java
View
@@ -19,6 +19,7 @@
import net.rim.device.api.system.Application;
import net.rim.device.api.system.KeyListener;
import net.rim.device.api.ui.Keypad;
+import net.rim.device.api.ui.UiApplication;
/**
* Key listener implementation. Proxy for system key listener that
@@ -40,6 +41,9 @@
private KeyListener _keyMonitor;
+ private UiApplication _app;
+ private boolean _dialogUp;
+
private boolean[] _listenerForKey = new boolean[] { false, false, false, false, false, false, false, false};
KeyPressHandler(ISystemEventListener manager) {
@@ -53,13 +57,13 @@
* @param forKey the key code to listen for
*/
public void listen(String forKey) {
- int keyToListenFor = Integer.parseInt(forKey);
-
- if(keyToListenFor < 0 || keyToListenFor > _listenerForKey.length) {
- throw new IllegalArgumentException("Invalid key code requested [" + keyToListenFor + "]");
+ int keyToListenFor = Integer.parseInt( forKey );
+
+ if( keyToListenFor < 0 || keyToListenFor > _listenerForKey.length ) {
+ throw new IllegalArgumentException( "Invalid key code requested [" + keyToListenFor + "]" );
}
-
- if(_keyMonitor == null) {
+
+ if( _keyMonitor == null ) {
//Anonymous implementation of the net.rim.device.api.system.KeyListener interface
_keyMonitor = new KeyListener() {
@@ -70,7 +74,8 @@ public void listen(String forKey) {
public boolean keyDown( int keycode, int time ) {
int keyPressed = Keypad.key( keycode );
int event;
-
+ _dialogUp = false;
+
switch( keyPressed ) {
case Keypad.KEY_CONVENIENCE_1:
event = IKEY_CONVENIENCE_1;
@@ -80,6 +85,7 @@ public boolean keyDown( int keycode, int time ) {
break;
case Keypad.KEY_MENU:
event = IKEY_MENU;
+ isDialogUp();
break;
case Keypad.KEY_SEND:
event = IKEY_STARTCALL;
@@ -89,27 +95,54 @@ public boolean keyDown( int keycode, int time ) {
break;
case Keypad.KEY_ESCAPE:
event = IKEY_BACK;
+ isDialogUp();
break;
case Keypad.KEY_VOLUME_DOWN:
event = IKEY_VOLUME_DOWN;
+ isDialogUp();
break;
case Keypad.KEY_VOLUME_UP:
event = IKEY_VOLUME_UP;
+ isDialogUp();
break;
default:
return false;
}
-
- //If we're listening for this hardware key, queue up an event for it
- if(_listenerForKey[event]) {
- _manager.onSystemEvent(_manager.EVENT_HARDWARE_KEY, String.valueOf(event));
-
+
+ // If we're listening for this hardware key, queue up an event for it,
+ // only queue if the active screen is not a dialog.
+ if( _listenerForKey[ event ] && !_dialogUp ) {
+ _manager.onSystemEvent( _manager.EVENT_HARDWARE_KEY, String.valueOf( event ) );
+
return true;
}
-
return false;
}
+ /*
+ * Checks to see if the current active screen is a Dialog.
+ */
+ private void isDialogUp() {
+ _app = UiApplication.getUiApplication();
+ if( _app.isEventThread() ) {
+ isDialogUpHelper();
+ } else {
+ _app.invokeLater( new Runnable() {
+ public void run() {
+ isDialogUpHelper();
+ }
+ } );
+ }
+ }
+
+ public void isDialogUpHelper() {
+ if( _app.getActiveScreen().getScreenBelow() == null ) {
+ _dialogUp = false;
+ } else {
+ _dialogUp = true;
+ }
+ }
+
/**
* @see net.rim.device.api.system.KeyListener#keyChar(char, int, int)
*/
28 framework/src/blackberry/web/widget/Widget.java
View
@@ -53,18 +53,18 @@ public Widget( WidgetConfig wConfig, String locationURI ) {
initialize();
_locationURI = locationURI;
- // Set our orientation
- WidgetConfigImpl configImpl = (WidgetConfigImpl) _wConfig;
- if (configImpl.isOrientationDefined()) {
- int direction;
- if (configImpl.getOrientation() == 0) {
- direction = net.rim.device.api.system.Display.DIRECTION_PORTRAIT;
- } else {
- direction = net.rim.device.api.system.Display.DIRECTION_LANDSCAPE;
- }
- net.rim.device.api.ui.Ui.getUiEngineInstance().setAcceptableDirections(direction);
- }
-
+ // Set our orientation
+ WidgetConfigImpl configImpl = (WidgetConfigImpl) _wConfig;
+ if( configImpl.isOrientationDefined() ) {
+ int direction;
+ if( configImpl.getOrientation() == 0 ) {
+ direction = net.rim.device.api.system.Display.DIRECTION_NORTH;
+ } else {
+ direction = net.rim.device.api.system.Display.DIRECTION_LANDSCAPE;
+ }
+ net.rim.device.api.ui.Ui.getUiEngineInstance().setAcceptableDirections( direction );
+ }
+
// Create PageManager
PageManager pageManager = new PageManager( this, (WidgetConfigImpl) _wConfig );
@@ -143,9 +143,9 @@ public static void main( String[] args ) {
waitForStartupComplete();
}
Widget widget = makeWidget( args, wConfig );
-
+
widget.enterEventDispatcher();
-
+
MemoryMaid mm = MemoryMaid.getInstance();
if( mm != null ) {
mm.stop();
1,102 framework/src/js/html5_init.js
View
@@ -1 +1,1101 @@
-(function(){function o(){this.hasArgument=function(a){return a&&a.length>0};this.hasTooManyArguments=function(a){return a&&a.length>a.callee.length};this.nullUndefinedArgument=function(a){return this.isNull(a)||this.isUndefined(a)};this.isUndefined=function(a){return a==null&&a!==null};this.isNull=function(a){return a===null};this.isNumber=function(a){return typeof a=="number"};this.isPositiveNumber=function(a){return this.isNumber(a)&&a>=0};this.isNumberInRange=function(a,b,c){return this.isNumber(a)&&a>=b&&a<=c};this.isString=function(a){return typeof a=="string"};this.isNonEmptyString=function(a){return this.isString(a)&&a.length>0};this.isFunction=function(a){return typeof a=="function"};this.isBoolean=function(a){return typeof a=="boolean"};this.isObject=function(a){return typeof a=="object"};this.isArray=function(a){return this.isObject(a)&&a instanceof Array};this.isStringArray=function(a){var b=false;var c=this;if(this.isArray(a)){b=function(a){for(var b=0;b<a.length;b++){if(!c.isString(a[b])){return false}}return true}(a)}return b};this.argumentsLength=function(a){return a.length}}function m(a){var b=new Array;while(a.isValidRow()){fieldCount=a.fieldCount();var c=new Object;for(var d=0;d<fieldCount;d++){var e=a.fieldName(d);c[e]=a.field(d)}b.push(c);a.next()}return new k(b)}function l(a,b){a=a||0;b=b||q["db_error_unknown"];this.__defineGetter__("code",function(){return a});this.__defineGetter__("message",function(){return b});this.toString=function(){return"[object SQLError]"}}function k(a){this.__defineGetter__("length",function(){return a.length});this.item=function(b){if(b<0||b>=this.length){return null}return a[b]};this.toString=function(){return"[object SQLResultSetRowList]"}}function j(a,b,c){this.__defineGetter__("insertId",function(){return a});this.__defineGetter__("rowsAffected",function(){return b});this.__defineGetter__("rows",function(){return c});this.toString=function(){return"[object SQLResultSet]"}}function i(a,b){var c=b;var d;this.executeSql=function(b,e,f,g){if(!p.hasArgument(arguments)){throw q["syntax_err"]}try{if(c){b=b.replace(/^\s+|\s+$/g,"");if(b.search(/^select/i)!=0){throw new l(1,q["not_authorized"])}}var h;try{h=a.execute(b,e)}catch(i){if(i.toString().search(/constraint failed/)!=-1){throw new l(6,q["constraint_failed"])}else{throw new l}}if(p.isFunction(f)){f(this,new j(a.lastInsertRowId,a.rowsAffected,m(h)))}if(h){h.close();h=null}}catch(i){d=i instanceof l?i:new l;if(p.isFunction(g)){g(this,d)}}};this.getLastError=function(){return d};this.toString=function(){return"[object SQLTransaction]"}}function h(a){function d(a,c,d,e){try{b.execute("begin",null);var f=new i(b,e);a(f);var g=f.getLastError();if(g){throw g}}catch(h){if(c){c(h instanceof l?h:new l)}return}finally{b.execute("commit",null)}if(d){d()}}var b=google.gears.factory.create("beta.database");try{b.open(a)}catch(c){throw q["TMP_ERROR"]}this.transaction=function(a,b,c){if(!p.hasArgument(arguments)){throw q["invalid_state_err"]}else if(!p.isFunction(a)||b&&!p.isFunction(b)||c&&!p.isFunction(c)){throw q["type_mismatch_err"]}setTimeout(function(){d(a,b,c)},50)};this.readTransaction=function(a,b,c){if(!p.hasArgument(arguments)){throw q["type_mismatch_err"]}else if(!p.isFunction(a)||b&&!p.isFunction(b)||c&&!p.isFunction(c)){throw q["type_mismatch_err"]}setTimeout(function(){d(a,b,c,true)},50)};this.__defineGetter__("version",function(){return"0.0"});this.changeVersion=function(){};this.toString=function(){return"[object Database]"}}function f(){function e(a){a=a||{};this.__defineGetter__("enableHighAccuracy",function(){return a.enableHighAccuracy||false});this.__defineSetter__("enableHighAccuracy",function(b){if(!p.isUndefined(b)&&!p.isBoolean(b)){throw q["TMP_ERROR"]}a.enableHighAccuracy=b});this.__defineGetter__("timeout",function(){return a.timeout});this.__defineSetter__("timeout",function(b){if(!p.isUndefined(b)&&!p.isNumberInRange(b,0,Infinity)){throw q["TMP_ERROR"]}a.timeout=b});this.__defineGetter__("maximumAge",function(){return a.maximumAge||0});this.__defineSetter__("maximumAge",function(b){if(!p.isUndefined(b)&&!p.isNumberInRange(b,0,Infinity)){throw q["TMP_ERROR"]}a.maximumAge=b})}function d(a,b){this.__defineGetter__("coords",function(){return a});this.__defineGetter__("timestamp",function(){return b})}function c(a){var b=null;if(p.isFunction(a)){b=function(b){a(g(b))}}return b}function b(a){var b;if(p.isFunction(a)){b=function(b){a(new d(f(b.coords),b.timestamp))}}return b}var a=google.gears.factory.create("beta.geolocation");this.getCurrentPosition=function(d,f,g){try{a.getCurrentPosition(b(d),c(f),new e(g))}catch(h){throw q["geo_watch_getCurrent"]}};this.watchPosition=function(d,f,g){try{return a.watchPosition(b(d),c(f),new e(g))}catch(h){throw q["geo_watch_getCurrent"]}};this.clearWatch=function(b){if(p.isUndefined(b)){throw q["geo_clearWatch"]}if(p.isPositiveNumber(b)){a.clearWatch(b)}};var f=function(a){var b=function(a,b,c,d,e){this.__defineGetter__("latitude",function(){return a});this.__defineGetter__("longitude",function(){return b});this.__defineGetter__("altitude",function(){return p.isPositiveNumber(c)?c:null});this.__defineGetter__("accuracy",function(){return p.isPositiveNumber(d)?d:Number.MAX_VALUE});this.__defineGetter__("altitudeAccuracy",function(){return p.isPositiveNumber(e)?e:null});this.__defineGetter__("heading",function(){return null});this.__defineGetter__("speed",function(){return null})};if(p.nullUndefinedArgument(a.latitude)){throw q["geo_coordinates_nullUndefinedLatitude"]}if(p.nullUndefinedArgument(a.longitude)){throw q["geo_coordinates_nullUndefinedLongitude"]}return new b(a.latitude,a.longitude,a.altitude,a.accuracy,a.altitudeAccuracy)};var g=function(a){var b=function(a,b){this.__defineGetter__("code",function(){return a});this.__defineGetter__("message",function(){return b})};b.prototype.__defineGetter__("PERMISSION_DENIED",function(){return 1});b.prototype.__defineGetter__("POSITION_UNAVAILABLE",function(){return 2});b.prototype.__defineGetter__("TIMEOUT",function(){return 3});switch(a.code){case a.PERMISSION_DENIED:return new b(b.prototype.PERMISSION_DENIED,a.message);case a.TIMEOUT:return new b(b.prototype.TIMEOUT,a.message);default:return new b(b.prototype.POSITION_UNAVAILABLE,a.message)}}}function e(a){var b=a[0];if(p.isFunction(b)&&p.argumentsLength(a)>2){var c=new Array;for(var d=0;d<p.argumentsLength(a)-2;d++){c[d]=a[d+2]}b=b.apply(this,c)}return b}function d(a){if(!isFinite(a)||!p.isPositiveNumber(a)){a=0}return a}function c(a){return p.isString(a)||p.isFunction(a)}function b(){navigator.geolocation=new f}if(!window.google||!google.gears){return}b();var a=google.gears.factory.create("beta.timer");window.setTimeout=function(){if(!c(arguments[0])){return a.setTimeout("",0)}var b=e(arguments);var f=d(arguments[1]);return a.setTimeout(b,f)};window.setInterval=function(){const b=10;if(!c(arguments[0])){return a.setInterval("",0)}var f=e(arguments);var g=d(arguments[1]);g=Math.max(g,b);return a.setInterval(f,g)};window.clearTimeout=function(){if(p.isPositiveNumber(arguments[0])){a.clearTimeout(arguments[0])}};window.clearInterval=function(){if(p.isPositiveNumber(arguments[0])){return a.clearInterval(arguments[0])}};var g=XMLHttpRequest;XMLHttpRequest=function(){var a=this;var b=new g;var c=false;this.__defineGetter__("UNSENT",function(){return 0});this.__defineGetter__("OPENED",function(){return 1});this.__defineGetter__("HEADERS_RECEIVED",function(){return 2});this.__defineGetter__("LOADING",function(){return 3});this.__defineGetter__("DONE",function(){return 4});this.__defineGetter__("readyState",function(){return b.readyState});this.__defineGetter__("status",function(){var a=0;try{a=b.status}catch(c){}return a});this.__defineGetter__("statusText",function(){var a="";try{a=b.statusText}catch(c){}return a});this.__defineGetter__("responseText",function(){var a="";try{a=b.responseText}catch(c){}return a});this.__defineGetter__("responseXML",function(){if(!(this.readyState==this.DONE)){return null}var a=new DOMParser;var b=null;try{b=a.parseFromString(this.responseText,"text/xml")}catch(c){}return b});this.open=function(a,c,d,e,f){if(!p.hasArgument(arguments)||arguments.length==1){throw q["not_enough_args"]}try{switch(arguments.length){case 2:b.open(a,c,true);break;case 3:b.open(a,c,d);break;case 4:b.open(a,c,d,e);break;default:b.open(a,c,d,e,f)}}catch(g){}};this.send=function(a){if(p.hasTooManyArguments(arguments)){throw q["invalid_state_err"]}if(a&&!p.isString(a)){throw q["TMP_ERROR"]}try{b.send(a)}catch(c){throw q["invalid_state_err"]}};this.abort=function(){try{b.abort()}catch(a){}};this.getResponseHeader=function(a){if(!p.isString(a)){return null}try{return b.getResponseHeader(a)}catch(c){throw q["invalid_state_err"]}};this.getAllResponseHeaders=function(){try{return b.getAllResponseHeaders()}catch(a){throw q["invalid_state_err"]}};this.setRequestHeader=function(a,c){if(!p.hasArgument(arguments)||arguments.length==1){throw q["not_enough_args"]}else if(!a||!p.isString(a)||!c||!p.isString(c)){return}try{b.setRequestHeader(a,c)}catch(d){throw q["invalid_state_err"]}};this.__defineSetter__("onreadystatechange",function(d){if(p.isFunction(d)){c=true;b.onreadystatechange=function(){d.apply(a)}}else{c=false}});this.__defineGetter__("onreadystatechange",function(){if(c){return b.onreadystatechange}return null});this.toString=function(){return"[object XMLHttpRequest]"}};openDatabase=function(a,b,c,d){if(!p.hasArgument(arguments)){throw q["syntax_err"]}else if(!p.isString(a)){throw q["invalid_state_err"]}try{return new h(a)}catch(e){}};var n=function(){function f(a,b){var d=google.gears.factory.create("beta.httprequest");d.open("GET",a);d.onreadystatechange=function(){if(d.readyState==4&&d.status==200){c.sendMessage(d.responseText,b)}};d.send()}function e(a,c){b[c].queue.push(a)}function d(a){while(b[a].queue.length){var d=b[a].queue.shift();c.sendMessage(d,a)}}var a="html5_worker.js";var b={};var c=google.gears.factory.create("beta.workerpool");c.onmessage=function(a,c,e){if(e.body.type=="ready"){b[e.sender].ready=true;d(e.sender)}else if(e.body.type=="message"){var f=b[e.sender].main;var g=f.onmessage;if(p.isFunction(g)){g.call(f,{data:e.body.content})}}else if(e.body.type=="error"){var f=b[e.sender].main;var h=f.onerror;if(p.isFunction(h)){h.call(f,e.body.content)}}else if(e.body.type=="debug"){}};this.createNewWorker=function(d,e){var g=c.createWorkerFromUrl(a);f(d,g);b[g]={queue:new Array,main:e,ready:false};return g};this.postToWorker=function(a,d){if(b[d].ready&&!b[d].queue.length){c.sendMessage(a,d)}else{e(a,d)}};return this}();Worker=function(a){if(!n){throw"Elemented with id 'html5_init' is not found. Worker with "+a+" cannot be created"}if(!p.hasArgument(arguments)){throw q["not_enough_args"]}if(!p.isString(a)){a=" "}else if(!a.length){throw q["syntax_err"]}var b=null;var c;var d=this;this.__defineSetter__("onmessage",function(a){if(!p.isFunction(a)){b=null;return}else{b=a}});this.__defineGetter__("onmessage",function(){return b});this.postMessage=function(a){if(!p.isPositiveNumber(c)){return}if(p.hasTooManyArguments(arguments)){throw q["worker_error_message_port"]}n.postToWorker(a,c)};this.__defineSetter__("onerror",function(a){window.onerror=a});this.__defineGetter__("onerror",function(){return window.onerror});this.toString=function(){return"[object Worker]"};if(a.indexOf(".js")!=-1){c=n.createNewWorker(a,d)}};var p=new o;var q=function(){var a={geo_watch_getCurrent:new Error("TYPE_MISMATCH_ERR:DOM Exception 17"),geo_clearWatch:new Error("Unexpected error: Not enough arguments [nsIDOMGeoGeolocation.clearWatch]"),geo_coordinates_nullUndefinedLatitude:new Error("Latitude should not be null or undefined"),geo_coordinates_nullUndefinedLongitude:new Error("Longitude should not be null or undefined"),invalid_state_err:new Error("INVALID_STATE_ERR: DOM Exception 11"),syntax_err:new Error("SYNTAX_ERR: DOM Exception 12"),type_mismatch_err:new Error("TYPE_MISMATCH_ERR: DOM Exception 17"),not_enough_args:new SyntaxError("Not enough arguments"),not_authorized:"not authorized",constraint_failed:"constraint failed",db_error_unknown:"Unknown database error occured",worker_error_message_port:new Error("Type error"),TMP_ERROR:new Error("Temporary Error Message")};return a}()})()
+/**
+
+Date: 07/29/2010
+Version: 1.0.0.4
+
+Copyright (c) 2010 Research In Motion Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+This License shall be included in all copies or substantial portions of the Software.
+
+The name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.
+
+ **/
+
+/*
+ Device 5.0 HTML 5 wrapper on Google Gears.
+ */
+
+(function() {
+
+ //Check pre-requisites and attach the various namespaces
+ if (!window.google || !google.gears) {
+ return; //Nothing else we can do
+ }
+
+ attachNamespaces();
+
+ //-----INITIALIZATION AREA-----
+ var timer = google.gears.factory.create("beta.timer");
+
+ function attachNamespaces() {
+
+ navigator.geolocation = new Geolocation();
+ }
+
+ //-----END OF INITIALIZATION AREA-----
+
+ /*
+ * HTML5 API
+ *
+ * handle = window.setTimeout( handler [, timeout [, arguments ] ] ); handle =
+ * window.setTimeout( code [, timeout ] )
+ *
+ */
+ window.setTimeout = function() {
+ /*
+ * Even though a non-string non-function handler is not part of HTML5
+ * API, the browser on 6.0 does not fail in those cases (returns a handler),
+ * so here we are just making a dummy call.
+ */
+ if (!isHandlerValid(arguments[0])) {
+ return timer.setTimeout("", 0);
+ }
+
+ // The first argument is required to be function/code
+ var handler = getTimerTask(arguments);
+ // The second argument is the timeout value
+ var timeout = getTimeout(arguments[1]);
+
+ return timer.setTimeout(handler, timeout);
+ };
+
+ window.setInterval = function() {
+ const MIN_INTERVAL = 10;
+ /*
+ * Even though a non-string non-function handler is not part of HTML5
+ * API, the browser on 6.0 does not fail in those cases (returns a handler),
+ * so here we are just making a dummy call.
+ */
+ if (!isHandlerValid(arguments[0])) {
+ return timer.setInterval("", 0);
+ }
+
+ // The first argument is required to be function/code
+ var handler = getTimerTask(arguments);
+ // The second argument is the timeout value
+ var timeout = getTimeout(arguments[1]);
+
+ //If timeout is less than MIN_INTERVAL, then increase timeout to MIN_INTERVAL.
+ timeout = Math.max(timeout, MIN_INTERVAL);
+
+ return timer.setInterval(handler, timeout);
+ };
+
+ window.clearTimeout = function() {
+ /*
+ * illegal arguments would throw exception in Gears, but only fail
+ * silently in 6.0 browser
+ */
+ if (util.isPositiveNumber(arguments[0])) {
+ timer.clearTimeout(arguments[0]);
+ }
+ };
+
+ window.clearInterval = function() {
+ if (util.isPositiveNumber(arguments[0])) {
+ return timer.clearInterval(arguments[0]);
+ }
+ };
+
+ /*
+ * check whether the handler is valid
+ */
+ function isHandlerValid(handler) {
+ return (util.isString(handler) || util.isFunction(handler));
+ }
+
+ /*
+ * HTML5 Documentation - get timeout
+ *
+ * 1. Let timeout be the second argument to the method, or zero if the
+ * argument was omitted. 2. Apply the ToString() abstract operation to
+ * timeout, and let timeout be the result. [ECMA262] 3. Apply the ToNumber()
+ * abstract operation to timeout, and let timeout be the result. [ECMA262]
+ * 4. If timeout is an Infinity value, a Not-a-Number (NaN) value, or
+ * negative, let timeout be zero. 5. Round timeout down to the nearest
+ * integer, and let timeout be the result. 6. Return timeout.
+ */
+ function getTimeout(timeout) {
+ if (!isFinite(timeout) || !util.isPositiveNumber(timeout)) {
+ timeout = 0;
+ }
+
+ return timeout;
+ }
+
+ /*
+ * getTimerTask take the whole array of arguments.
+ * If the handler is a funciton, it pass any arguments straight through to the handler
+ */
+ function getTimerTask(arguments) {
+ var handler = arguments[0];
+ if (util.isFunction(handler) && util.argumentsLength(arguments) > 2) {
+ // The user put a function signature as the first argument
+ // The third arguments and onwards are parameters for the first
+ // function
+ var args = new Array();
+ for (var i = 0; i < util.argumentsLength(arguments) - 2; i++) {
+ args[i] = arguments[i + 2];
+ }
+
+ handler = handler.apply(this, args);
+ }
+ return handler;
+ }
+
+ function Geolocation() {
+ var geolocation = google.gears.factory.create("beta.geolocation");
+
+ this.getCurrentPosition = function(positionCB, positionErrorCB, positionOptions) {
+ try {
+ geolocation.getCurrentPosition(wrapSuccessCB(positionCB), wrapErrorCB(positionErrorCB), new PositionOptions(positionOptions));
+ }
+ catch (e) {
+ throw (errorsMap["geo_watch_getCurrent"]);
+ }
+ };
+
+ this.watchPosition = function(positionCB, positionErrorCB, positionOptions) {
+ try {
+ return geolocation.watchPosition(wrapSuccessCB(positionCB), wrapErrorCB(positionErrorCB), new PositionOptions(positionOptions));
+ }
+ catch (e) {
+ throw (errorsMap["geo_watch_getCurrent"]);
+ }
+ };
+
+ function wrapSuccessCB(positionCB) {
+ var result;
+
+ if (util.isFunction(positionCB)) {
+ result = function(position) {
+ positionCB(new Position(createCoordinates(position.coords), position.timestamp));
+ };
+ }
+
+ return result;
+ }
+
+ function wrapErrorCB(positionErrorCB) {
+ // Pass null when there is no usage of the callback
+ var result = null;
+
+ if (util.isFunction(positionErrorCB)) {
+ result = function(error) {
+ positionErrorCB(createPositionError(error));
+ };
+ }
+
+ return result;
+ }
+
+ this.clearWatch = function(watchId) {
+ //Throw the only error required by HTML 5
+ if (util.isUndefined(watchId)) {
+ throw (errorsMap["geo_clearWatch"]);
+ }
+
+ /* Only pass the call to Gears if we have a positive integer watchId.
+ * Gears throws exceptions for invalid parameter values that HTML 5
+ * ignores
+ */
+ if (util.isPositiveNumber(watchId)) {
+ geolocation.clearWatch(watchId);
+ }
+ };
+
+ function Position(coords, timestamp) {
+ this.__defineGetter__("coords", function() {
+ return coords;
+ });
+
+ this.__defineGetter__("timestamp", function() {
+ return timestamp;
+ });
+ }
+
+ function PositionOptions(args) {
+ args = args || {};
+
+ this.__defineGetter__("enableHighAccuracy", function() {
+ return args.enableHighAccuracy || false;
+ });
+
+ this.__defineSetter__("enableHighAccuracy", function(value) {
+ if (!util.isUndefined(value) && !util.isBoolean(value)) {
+ throw (errorsMap["TMP_ERROR"]);
+ }
+
+ args.enableHighAccuracy = value;
+ });
+
+ this.__defineGetter__("timeout", function() {
+ return args.timeout;
+ });
+
+ this.__defineSetter__("timeout", function(value) {
+ if (!util.isUndefined(value) && !util.isNumberInRange(value, 0, Infinity)) {
+ throw (errorsMap["TMP_ERROR"]);
+ }
+
+ args.timeout = value;
+ });
+
+ this.__defineGetter__("maximumAge", function() {
+ return args.maximumAge || 0;
+ });
+
+ this.__defineSetter__("maximumAge", function(value) {
+ if (!util.isUndefined(value) && !util.isNumberInRange(value, 0, Infinity)) {
+ throw (errorsMap["TMP_ERROR"]);
+ }
+
+ args.maximumAge = value;
+ });
+ }
+
+ //Factory function that checks Gears object to ensure that it contains
+ //valid coordinate data and creates an HTML 5 Coordinates object from it
+ var createCoordinates = function(fromGearsCoords) {
+
+ //Keep the Coordinates object private so we only navigator members can instantiate it
+ var Coordinates = function(lat, lon, alt, acc, altAcc) {
+ this.__defineGetter__("latitude", function() {
+ return lat;
+ });
+
+ this.__defineGetter__("longitude", function() {
+ return lon;
+ });
+
+ this.__defineGetter__("altitude", function() {
+ return util.isPositiveNumber(alt) ? alt : null;
+ });
+
+ this.__defineGetter__("accuracy", function() {
+ return util.isPositiveNumber(acc) ? acc : Number.MAX_VALUE;
+ });
+
+ this.__defineGetter__("altitudeAccuracy", function() {
+ return util.isPositiveNumber(altAcc) ? altAcc : null;
+ });
+
+ this.__defineGetter__("heading", function() {
+ return null; //Not supported by Gears
+ });
+
+ this.__defineGetter__("speed", function() {
+ return null; //Not supported by Gears
+ });
+ };
+
+ if (util.nullUndefinedArgument(fromGearsCoords.latitude)) {
+ throw errorsMap["geo_coordinates_nullUndefinedLatitude"];
+ }
+
+ if (util.nullUndefinedArgument(fromGearsCoords.longitude)) {
+ throw errorsMap["geo_coordinates_nullUndefinedLongitude"];
+ }
+
+ return new Coordinates(fromGearsCoords.latitude, fromGearsCoords.longitude, fromGearsCoords.altitude, fromGearsCoords.accuracy, fromGearsCoords.altitudeAccuracy);
+ };
+
+ var createPositionError = function(fromGearsError) {
+ var PositionError = function(errorCode, msg) {
+ this.__defineGetter__("code", function() {
+ return errorCode;
+ });
+
+ this.__defineGetter__("message", function() {
+ return msg;
+ });
+ };
+
+ //Getters for the instance error codes used by clients
+ PositionError.prototype.__defineGetter__("PERMISSION_DENIED", function() {
+ return 1;
+ });
+
+ PositionError.prototype.__defineGetter__("POSITION_UNAVAILABLE", function() {
+ return 2;
+ });
+
+ PositionError.prototype.__defineGetter__("TIMEOUT", function() {
+ return 3;
+ });
+
+ //Map the Gears error code to the HTML 5 error codes and return the Gears error message
+ switch (fromGearsError.code) {
+ //Not used by Gears but included for completeness
+ case fromGearsError.PERMISSION_DENIED:
+ return new PositionError(PositionError.prototype.PERMISSION_DENIED, fromGearsError.message);
+ case fromGearsError.TIMEOUT:
+ return new PositionError(PositionError.prototype.TIMEOUT, fromGearsError.message);
+ default:
+ return new PositionError(PositionError.prototype.POSITION_UNAVAILABLE, fromGearsError.message);
+ }
+ };
+
+ }
+ var nativeXMLHttpRequest = XMLHttpRequest;
+
+ XMLHttpRequest = function() {
+ var that = this;
+ var request = new nativeXMLHttpRequest();
+ var hasValidOnReadyStateChange = false;
+
+ // The object has been constructed.
+ this.__defineGetter__("UNSENT", function() {
+ return 0;
+ });
+
+ // The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.
+ this.__defineGetter__("OPENED", function() {
+ return 1;
+ });
+
+ /*
+ * All HTTP headers have been received. Several response members of the object are now available.
+ * HEADERS_RECEIVED is same as SENT of Google Gears.
+ */
+ this.__defineGetter__("HEADERS_RECEIVED", function() {
+ return 2;
+ });
+
+ /*
+ * The response entity body is being received.
+ * LOADING is same as Interactive of Google Gears.
+ */
+ this.__defineGetter__("LOADING", function() {
+ return 3;
+ });
+
+ // The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).
+ this.__defineGetter__("DONE", function() {
+ return 4;
+ });
+
+ // The XMLHttpRequest object can be in several states. The readyState attribute, on getting, must return the current state, which must be one of the above values.
+ this.__defineGetter__("readyState", function() {
+ return request.readyState;
+ });
+
+ this.__defineGetter__("status", function() {
+ var result = 0;
+
+ try {
+ result = request.status;
+ }
+ catch (e) {
+ }
+
+ // Return the HTTP status text.
+ return result;
+ });
+
+ this.__defineGetter__("statusText", function() {
+ var result = "";
+
+ try {
+ result = request.statusText;
+ }
+ catch (e) {
+ }
+
+ // Return the HTTP status text.
+ return result;
+ });
+
+ this.__defineGetter__("responseText", function() {
+ var result = "";
+
+ try {
+ result = request.responseText;
+ }
+ catch (e) {
+ }
+
+ // Return the text response entity body.
+ return result;
+ });
+
+ this.__defineGetter__("responseXML", function() {
+ // If the state is not DONE return null and terminate these steps
+ if (!(this.readyState == this.DONE)) {
+ return null;
+ }
+
+ //parse responseText to XML Document
+ var parser = new DOMParser();
+ var xmlDoc = null;
+
+ try{
+ xmlDoc = parser.parseFromString (this.responseText, "text/xml");
+ }
+ catch (e) {
+ }
+ //Return the XML response entity body.
+ return xmlDoc;
+ });
+
+ this.open = function(method, url, sync, username, password) {
+ if (!util.hasArgument(arguments) || arguments.length == 1) {
+ throw errorsMap["not_enough_args"];
+ }
+
+ try {
+ switch(arguments.length) {
+ case 2:
+ // Native XMLHttp Request must have three arguments
+ // However, gears only takes two. Therefore, we
+ // should make request asynchronous to support
+ // previous functionality.
+ request.open(method, url, true);
+ break;
+ case 3:
+ request.open(method, url, sync);
+ break;
+ case 4:
+ request.open(method, url, sync, username);
+ break;
+ default:
+ request.open(method, url, sync, username, password);
+ }
+ }
+ catch (e) {
+ }
+ };
+
+ this.send = function(data) {
+ if (util.hasTooManyArguments(arguments)) {
+ throw errorsMap["invalid_state_err"];
+ }
+
+ // Gears accept data to be a blob which we are not supporting here.
+ if (data && !util.isString(data)) {
+ throw errorsMap["TMP_ERROR"];
+ }
+
+ try {
+ request.send(data);
+ }
+ catch (e) {
+ throw errorsMap["invalid_state_err"];
+ }
+ };
+
+ this.abort = function() {
+ try {
+ request.abort();
+ }
+ catch (e) {
+ }
+ };
+
+ this.getResponseHeader = function(header) {
+ if (!util.isString(header)) {
+ return null;
+ }
+
+ try {
+ return request.getResponseHeader(header);
+ }
+ catch (e) {
+ throw errorsMap["invalid_state_err"];
+ }
+ };
+
+ this.getAllResponseHeaders = function() {
+ try {
+ return request.getAllResponseHeaders();
+ }
+ catch (e) {
+ throw errorsMap["invalid_state_err"];
+ }
+ };
+
+ this.setRequestHeader = function(header, value) {
+ if (!util.hasArgument(arguments) || arguments.length == 1) {
+ throw errorsMap["not_enough_args"];
+ }
+ else if (!header || !util.isString(header) || !value || !util.isString(value)) {
+ return;
+ }
+
+ try {
+ request.setRequestHeader(header, value);
+ }
+ catch (e) {
+ throw errorsMap["invalid_state_err"];
+ }
+ };
+
+ this.__defineSetter__("onreadystatechange", function(handler) {
+ /*
+ * The behaviour in 6.0 browser:
+ * If the handler is not a function
+ * (this includes undefined, string, number, etc)
+ * Then onreadystatechange is set to null (Gears would throw exception)
+ * Otherwise assign the function to onreadystatechange
+ */
+ if (util.isFunction(handler)) {
+ hasValidOnReadyStateChange = true;
+ request.onreadystatechange = function() {
+ handler.apply(that);
+ };
+ }
+ else {
+ hasValidOnReadyStateChange = false;
+ }
+ });
+
+ this.__defineGetter__("onreadystatechange", function() {
+ if (hasValidOnReadyStateChange) {
+ return request.onreadystatechange;
+ }
+ return null;
+ });
+
+ // The object name is not 'XMLHttpRequest' to prevent collision with a global XMLHttpRequest object.
+ // Overriding toString method to return expected string.
+ this.toString = function() {
+ return "[object XMLHttpRequest]";
+ };
+ };
+
+ openDatabase = function(name, version, displayName, estimatedSize) {
+ if (!util.hasArgument(arguments)) {
+ throw errorsMap["syntax_err"];
+ }
+ else if (!util.isString(name)) {
+ throw errorsMap["invalid_state_err"];
+ }
+
+ try {
+ return new Database(name);
+ }
+ catch (e) {
+ }
+ };
+
+ function Database(name) {
+ var db = google.gears.factory.create("beta.database");
+
+ try {
+ db.open(name);
+ }
+ catch (e) {
+ throw errorsMap["TMP_ERROR"];
+ }
+
+ // Should return immediately, so timer is set.
+ this.transaction = function(callback, errorCallback, successCallback) {
+ if (!util.hasArgument(arguments)) {
+ throw errorsMap["invalid_state_err"];
+ }
+ else if (!util.isFunction(callback) || (errorCallback && !util.isFunction(errorCallback)) || (successCallback && !util.isFunction(successCallback))) {
+ throw errorsMap["type_mismatch_err"];
+ }
+
+ setTimeout(function() {
+ transactionAsync(callback, errorCallback, successCallback);
+ }, 50);
+ };
+
+ // Should return immediately, so timer is set.
+ this.readTransaction = function(callback, errorCallback, successCallback) {
+ if (!util.hasArgument(arguments)) {
+ throw errorsMap["type_mismatch_err"];
+ }
+ else if (!util.isFunction(callback) || (errorCallback && !util.isFunction(errorCallback)) || (successCallback && !util.isFunction(successCallback))) {
+ throw errorsMap["type_mismatch_err"];
+ }
+
+ setTimeout(function() {
+ transactionAsync(callback, errorCallback, successCallback, true);
+ }, 50);
+ };
+
+ function transactionAsync(callback, errorCallback, successCallback, readOnly) {
+ try {
+ // Optimizing by using begin and commit commands.
+ db.execute("begin", null);
+ var sqlTransaction = new SQLTransaction(db, readOnly);
+ callback(sqlTransaction);
+ var lastError = sqlTransaction.getLastError();
+
+ if (lastError) {
+ throw lastError;
+ }
+ }
+ catch (e) {
+ if (errorCallback) {
+ errorCallback(e instanceof SQLError ? e : new SQLError());
+ }
+ return;
+ }
+ finally {
+ db.execute("commit", null);
+ }
+
+ if (successCallback) {
+ successCallback();
+ }
+ }
+
+ // Google gears doesn't support version. version will return 0.0 as default
+ this.__defineGetter__("version", function() {
+ return "0.0";
+ });
+
+ // changeVersion does nothing
+ this.changeVersion = function() {
+ };
+
+
+ this.toString = function() {
+ return "[object Database]";
+ };
+ }
+
+ function SQLTransaction(db, mode) {
+ var readOnly = mode;
+ var lastError;
+
+ this.executeSql = function(sqlStatement, args, callback, errorCallback) {
+ if (!util.hasArgument(arguments)) {
+ throw errorsMap["syntax_err"];
+ }
+
+ try {
+ if (readOnly) {
+ // In readonly mode, checking if select is at the begining of the sqlStatement.
+ sqlStatement = sqlStatement.replace(/^\s+|\s+$/g, "");
+ if (sqlStatement.search(/^select/i) != 0) {
+ throw new SQLError(1, errorsMap["not_authorized"]);
+ }
+ }
+
+ var gearsResultSet;
+
+ try {
+ gearsResultSet = db.execute(sqlStatement, args);
+ }
+ catch (e) {
+ if (e.toString().search(/constraint failed/) != -1) {
+ throw new SQLError(6, errorsMap["constraint_failed"]);
+ }
+ else {
+ throw new SQLError();
+ }
+ }
+
+ if (util.isFunction(callback)) {
+ callback(this, new SQLResultSet(db.lastInsertRowId, db.rowsAffected, buildSQLResultSetRowList(gearsResultSet)));
+ }
+
+ //It's required to call close() when finished with any result set.
+ if (gearsResultSet) {
+ gearsResultSet.close();
+ gearsResultSet = null;
+ }
+
+ }
+ catch (e) {
+ lastError = (e instanceof SQLError ? e : new SQLError());
+
+ if (util.isFunction(errorCallback)) {
+ errorCallback(this, lastError);
+ }
+ }
+ };
+
+ this.getLastError = function() {
+ return lastError;
+ };
+
+ this.toString = function() {
+ return "[object SQLTransaction]";
+ };
+ }
+
+ function SQLResultSet(insertId, rowsAffected, sqlResultSetRowList) {
+ this.__defineGetter__("insertId", function() {
+ return insertId;
+ });
+
+ this.__defineGetter__("rowsAffected", function() {
+ return rowsAffected;
+ });
+
+ this.__defineGetter__("rows", function() {
+ return sqlResultSetRowList;
+ });
+
+ this.toString = function() {
+ return "[object SQLResultSet]";
+ };
+ }
+
+ function SQLResultSetRowList(items) {
+ this.__defineGetter__("length", function() {
+ return items.length;
+ });
+
+ this.item = function(index) {
+ if (index < 0 || index >= this.length) {
+ return null;
+ }
+
+ return items[index];
+ };
+
+ this.toString = function() {
+ return "[object SQLResultSetRowList]";
+ };
+ }
+
+ function SQLError(code, message) {
+ code = code || 0;
+ message = message || errorsMap["db_error_unknown"];
+
+ this.__defineGetter__("code", function() {
+ return code;
+ });
+
+ this.__defineGetter__("message", function() {
+ return message;
+ });
+
+ this.toString = function() {
+ return "[object SQLError]";
+ };
+ }
+
+ function buildSQLResultSetRowList(gearsResultSet) {
+ var items = new Array();
+
+ while (gearsResultSet.isValidRow()) {
+ fieldCount = gearsResultSet.fieldCount();
+
+ var item = new Object();
+ for (var counter = 0; counter < fieldCount; counter++) {
+ var fieldName = gearsResultSet.fieldName(counter);
+ item[fieldName] = gearsResultSet.field(counter);
+ }
+
+ items.push(item);
+
+ gearsResultSet.next();
+ }
+
+ return new SQLResultSetRowList(items);
+ }
+
+ /*
+ * workerRelay is responsible for keeping track of messages
+ * mainly to make sure that no message is lost while the worker
+ * is initializing
+ * workerRelay creates all userWorkers using one workerpool,
+ * although this means that the childWorkers are capable of communicating with each other
+ * we are not allowing it by restricting the workerId the childWorkers may send messages to
+ */
+ var workerRelay = (function() {
+
+ /* Location of worker shim in URL.*/
+ var workerWrapperUrl = "html5_worker.js";
+
+ var relayMap = {};
+ var relayWP = google.gears.factory.create("beta.workerpool");
+
+ relayWP.onmessage = function(messageText, senderId, messageObject) {
+ if (messageObject.body.type == "ready") {
+ //a one-time signal that the initialization is done
+ //start working on the backlog if there is one
+ relayMap[messageObject.sender].ready = true;
+ processQueue(messageObject.sender);
+ }
+ else if (messageObject.body.type == "message") {
+ //Test to see if sender contained in object is valid
+ var mainWorker = relayMap[messageObject.sender].main;
+ var onMessageFunc = mainWorker.onmessage;
+ if (util.isFunction(onMessageFunc)) {
+ onMessageFunc.call(mainWorker, {
+ data: messageObject.body.content
+ });
+ }
+ }
+ else if (messageObject.body.type == "error") {
+ var mainWorker = relayMap[messageObject.sender].main;
+ var onErrorFunc = mainWorker.onerror;
+ if (util.isFunction(onErrorFunc)) {
+ onErrorFunc.call(mainWorker, messageObject.body.content);
+ }
+ }
+ else if (messageObject.body.type == "debug") {
+ }
+ };
+
+ this.createNewWorker = function(fileUrl, mainWorker) {
+ var childId = relayWP.createWorkerFromUrl(workerWrapperUrl);
+ fetchAndSendScript(fileUrl, childId);
+
+ relayMap[childId] = {
+ queue: new Array(),
+ main: mainWorker,
+ ready: false
+ };
+ return childId;
+ };
+
+ this.postToWorker = function(message, childId) {
+ if (relayMap[childId].ready && !relayMap[childId].queue.length) {
+ relayWP.sendMessage(message, childId);
+ }
+ else {
+ addToQueue(message, childId);
+ }
+ };
+
+ function processQueue(childId) {
+ while (relayMap[childId].queue.length) {
+ var msg = relayMap[childId].queue.shift();
+ relayWP.sendMessage(msg, childId);
+ }
+ }
+
+ function addToQueue(message, childId) {
+ relayMap[childId].queue.push(message);
+ }
+
+ function fetchAndSendScript(fileUrl, childId) {
+ var requestFile = google.gears.factory.create("beta.httprequest");
+ requestFile.open('GET', fileUrl);
+ requestFile.onreadystatechange = function() {
+ if (requestFile.readyState == 4 && requestFile.status == 200) {
+ relayWP.sendMessage(requestFile.responseText, childId);
+ }
+ };
+
+ requestFile.send();
+ }
+ return this;
+ })();
+
+ /*The Worker object is a facade to simulate HTML5
+ *Beside error checking,
+ *the actual processing is delegated to workerRelay
+ */
+ Worker = function(fileUrl) {
+ if (!workerRelay) {
+ throw "Elemented with id 'html5_init' is not found. Worker with " + fileUrl + " cannot be created";
+ }
+
+ if (!util.hasArgument(arguments)) {
+ throw errorsMap["not_enough_args"];
+ }
+
+ if (!util.isString(fileUrl)) {
+ fileUrl = " ";
+ }
+ else if (!fileUrl.length) {
+ throw errorsMap["syntax_err"];
+ }
+
+ var onMessageFunction = null;
+ var sendToThisId;
+ var INSTANCE_CONTEXT = this;
+
+ this.__defineSetter__("onmessage", function(func) {
+ //only reassign if onmessage is a valid function
+ //otherwise let it go to null
+
+ if (!util.isFunction(func)) {
+ onMessageFunction = null;
+ return;
+ }
+ else {
+ onMessageFunction = func;
+ }
+ });
+
+ this.__defineGetter__("onmessage", function() {
+ return onMessageFunction;
+ });
+
+ this.postMessage = function(message) {
+ if (!util.isPositiveNumber(sendToThisId)) {
+ return;
+ }
+
+ if (util.hasTooManyArguments(arguments)) {
+ throw errorsMap["worker_error_message_port"];
+ }
+
+ workerRelay.postToWorker(message, sendToThisId);
+ };
+
+ this.__defineSetter__("onerror", function(func) {
+ window.onerror = func;
+ });
+
+ this.__defineGetter__("onerror", function() {
+ return window.onerror;
+ });
+
+ this.toString = function() {
+ return "[object Worker]";
+ };
+
+ if (fileUrl.indexOf(".js") != -1) {
+ sendToThisId = workerRelay.createNewWorker(fileUrl, INSTANCE_CONTEXT);
+ }
+ };
+
+ /* Utility class */
+ function Utility() {
+ // hasArgument() - returns true if at least 1 arg is present (including
+ // null or undefined), false otherwise
+ this.hasArgument = function(args) {
+ return args && (args.length > 0);
+ };
+
+ // hasTooManyArguments() - returns true if number of args passed is
+ // greater than number expected, false otherwise
+ this.hasTooManyArguments = function(args) {
+ return args && (args.length > args.callee.length);
+ };
+
+ // nullUndefinedArgument() - returns true if arg is null or undefined,
+ // false otherwise
+ this.nullUndefinedArgument = function(arg) {
+ return (this.isNull(arg) || this.isUndefined(arg));
+ };
+
+ // isUndefined() - returns true if arg is undefined, false otherwise
+ // Agree it looks bizarre but safe, since undefined can be re-assigned.
+ this.isUndefined = function(arg) {
+ return (arg == null && arg !== null);
+ };
+
+ // isNull() - returns true if arg is null, false otherwise
+ this.isNull = function(arg) {
+ return (arg === null);
+ };
+
+ // isNumber() - returns true if arg is of type number, false otherwise
+ this.isNumber = function(arg) {
+ return typeof arg == "number";
+ };
+
+ // isPositiveNumber() - returns true if arg is of type number and is
+ // positive, false otherwise
+ this.isPositiveNumber = function(arg) {
+ return this.isNumber(arg) && (arg >= 0);
+ };
+
+ // isNumberInRange() - returns true if arg is of type number and in the
+ // specified range, false otherwise
+ this.isNumberInRange = function(arg, low, high) {
+ return this.isNumber(arg) && (arg >= low && arg <= high);
+ };
+
+ // isString() - returns true if arg is of type string, false otherwise
+ this.isString = function(arg) {
+ return typeof arg == "string";
+ };
+
+ // isNonEmptyString() - returns true if arg is of type string and is
+ // non-empty, false otherwise
+ this.isNonEmptyString = function(arg) {
+ return this.isString(arg) && (arg.length > 0);
+ };
+
+ // isFunction() - returns true if arg is of type function, false
+ // otherwise
+ this.isFunction = function(arg) {
+ return typeof arg == "function";
+ };
+
+ // isBoolean() - returns true if arg is of type boolean, false otherwise
+ this.isBoolean = function(arg) {
+ return typeof arg == "boolean";
+ };
+
+ // isObject() - returns true if arg is of type object, false otherwise
+ this.isObject = function(arg) {
+ return typeof arg == "object";
+ };
+
+ // isArray() - returns true if arg is of type array, false otherwise
+ this.isArray = function(arg) {
+ return (this.isObject(arg) && (arg instanceof Array));
+ };
+
+ // isStringArray() - returns true if arg is of type array of strings,
+ // false otherwise
+ this.isStringArray = function(arg) {
+ var result = false;
+ var that = this;
+
+ if (this.isArray(arg)) {
+ result = (function(arg) {
+ for (var i = 0; i < arg.length; i++) {
+ if (!that.isString(arg[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ })(arg);
+ }
+ return result;
+ };
+
+ // argumentsLength - returns an arguments length
+ this.argumentsLength = function(args) {
+ return args.length;
+ };
+ }
+
+ var util = new Utility();
+
+ //Initializing exception messages
+ var errorsMap = (function() {
+ var errors = {
+ "geo_watch_getCurrent": new Error("TYPE_MISMATCH_ERR:DOM Exception 17"),
+
+ "geo_clearWatch": new Error("Unexpected error: Not enough arguments [nsIDOMGeoGeolocation.clearWatch]"),
+
+ "geo_coordinates_nullUndefinedLatitude": new Error("Latitude should not be null or undefined"),
+
+ "geo_coordinates_nullUndefinedLongitude": new Error("Longitude should not be null or undefined"),
+
+ "invalid_state_err": new Error("INVALID_STATE_ERR: DOM Exception 11"),
+
+ "syntax_err": new Error("SYNTAX_ERR: DOM Exception 12"),
+
+ "type_mismatch_err": new Error("TYPE_MISMATCH_ERR: DOM Exception 17"),
+
+ "not_enough_args": new SyntaxError("Not enough arguments"),
+
+ "not_authorized": "not authorized",
+
+ "constraint_failed": "constraint failed",
+
+ "db_error_unknown": "Unknown database error occured",
+
+ "worker_error_message_port": new Error("Type error"),
+
+ "TMP_ERROR": new Error("Temporary Error Message")
+ };
+
+ return errors;
+
+ })();
+
+})();
1,101 framework/src/js/html5_init_uncompressed.js
View
@@ -1,1101 +0,0 @@
-/**
-
-Date: 07/29/2010
-Version: 1.0.0.4
-
-Copyright (c) 2010 Research In Motion Limited.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-This License shall be included in all copies or substantial portions of the Software.
-
-The name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.
-
- **/
-
-/*
- Device 5.0 HTML 5 wrapper on Google Gears.
- */
-
-(function() {
-
- //Check pre-requisites and attach the various namespaces
- if (!window.google || !google.gears) {
- return; //Nothing else we can do
- }
-
- attachNamespaces();
-
- //-----INITIALIZATION AREA-----
- var timer = google.gears.factory.create("beta.timer");
-
- function attachNamespaces() {
-
- navigator.geolocation = new Geolocation();
- }
-
- //-----END OF INITIALIZATION AREA-----
-
- /*
- * HTML5 API
- *
- * handle = window.setTimeout( handler [, timeout [, arguments ] ] ); handle =
- * window.setTimeout( code [, timeout ] )
- *
- */
- window.setTimeout = function() {
- /*
- * Even though a non-string non-function handler is not part of HTML5
- * API, the browser on 6.0 does not fail in those cases (returns a handler),
- * so here we are just making a dummy call.
- */
- if (!isHandlerValid(arguments[0])) {
- return timer.setTimeout("", 0);
- }
-
- // The first argument is required to be function/code
- var handler = getTimerTask(arguments);
- // The second argument is the timeout value
- var timeout = getTimeout(arguments[1]);
-
- return timer.setTimeout(handler, timeout);
- };
-
- window.setInterval = function() {
- const MIN_INTERVAL = 10;
- /*
- * Even though a non-string non-function handler is not part of HTML5
- * API, the browser on 6.0 does not fail in those cases (returns a handler),
- * so here we are just making a dummy call.
- */
- if (!isHandlerValid(arguments[0])) {
- return timer.setInterval("", 0);
- }
-
- // The first argument is required to be function/code
- var handler = getTimerTask(arguments);
- // The second argument is the timeout value
- var timeout = getTimeout(arguments[1]);
-
- //If timeout is less than MIN_INTERVAL, then increase timeout to MIN_INTERVAL.
- timeout = Math.max(timeout, MIN_INTERVAL);
-
- return timer.setInterval(handler, timeout);
- };
-
- window.clearTimeout = function() {
- /*
- * illegal arguments would throw exception in Gears, but only fail
- * silently in 6.0 browser
- */
- if (util.isPositiveNumber(arguments[0])) {
- timer.clearTimeout(arguments[0]);
- }
- };
-
- window.clearInterval = function() {
- if (util.isPositiveNumber(arguments[0])) {
- return timer.clearInterval(arguments[0]);
- }
- };
-
- /*
- * check whether the handler is valid
- */
- function isHandlerValid(handler) {
- return (util.isString(handler) || util.isFunction(handler));
- }
-
- /*
- * HTML5 Documentation - get timeout
- *
- * 1. Let timeout be the second argument to the method, or zero if the
- * argument was omitted. 2. Apply the ToString() abstract operation to
- * timeout, and let timeout be the result. [ECMA262] 3. Apply the ToNumber()
- * abstract operation to timeout, and let timeout be the result. [ECMA262]
- * 4. If timeout is an Infinity value, a Not-a-Number (NaN) value, or
- * negative, let timeout be zero. 5. Round timeout down to the nearest
- * integer, and let timeout be the result. 6. Return timeout.
- */
- function getTimeout(timeout) {
- if (!isFinite(timeout) || !util.isPositiveNumber(timeout)) {
- timeout = 0;
- }
-
- return timeout;
- }
-
- /*
- * getTimerTask take the whole array of arguments.
- * If the handler is a funciton, it pass any arguments straight through to the handler
- */
- function getTimerTask(arguments) {
- var handler = arguments[0];
- if (util.isFunction(handler) && util.argumentsLength(arguments) > 2) {
- // The user put a function signature as the first argument
- // The third arguments and onwards are parameters for the first
- // function
- var args = new Array();
- for (var i = 0; i < util.argumentsLength(arguments) - 2; i++) {
- args[i] = arguments[i + 2];
- }
-
- handler = handler.apply(this, args);
- }
- return handler;
- }
-
- function Geolocation() {
- var geolocation = google.gears.factory.create("beta.geolocation");
-
- this.getCurrentPosition = function(positionCB, positionErrorCB, positionOptions) {
- try {
- geolocation.getCurrentPosition(wrapSuccessCB(positionCB), wrapErrorCB(positionErrorCB), new PositionOptions(positionOptions));
- }
- catch (e) {
- throw (errorsMap["geo_watch_getCurrent"]);
- }
- };
-
- this.watchPosition = function(positionCB, positionErrorCB, positionOptions) {
- try {
- return geolocation.watchPosition(wrapSuccessCB(positionCB), wrapErrorCB(positionErrorCB), new PositionOptions(positionOptions));
- }
- catch (e) {
- throw (errorsMap["geo_watch_getCurrent"]);
- }
- };
-
- function wrapSuccessCB(positionCB) {
- var result;
-
- if (util.isFunction(positionCB)) {
- result = function(position) {
- positionCB(new Position(createCoordinates(position.coords), position.timestamp));
- };
- }
-
- return result;
- }
-
- function wrapErrorCB(positionErrorCB) {
- // Pass null when there is no usage of the callback
- var result = null;
-
- if (util.isFunction(positionErrorCB)) {
- result = function(error) {
- positionErrorCB(createPositionError(error));
- };
- }
-
- return result;
- }
-
- this.clearWatch = function(watchId) {
- //Throw the only error required by HTML 5
- if (util.isUndefined(watchId)) {
- throw (errorsMap["geo_clearWatch"]);
- }
-
- /* Only pass the call to Gears if we have a positive integer watchId.
- * Gears throws exceptions for invalid parameter values that HTML 5
- * ignores
- */
- if (util.isPositiveNumber(watchId)) {
- geolocation.clearWatch(watchId);
- }
- };
-
- function Position(coords, timestamp) {
- this.__defineGetter__("coords", function() {
- return coords;
- });
-
- this.__defineGetter__("timestamp", function() {
- return timestamp;
- });
- }
-
- function PositionOptions(args) {
- args = args || {};
-
- this.__defineGetter__("enableHighAccuracy", function() {
- return args.enableHighAccuracy || false;
- });
-
- this.__defineSetter__("enableHighAccuracy", function(value) {
- if (!util.isUndefined(value) && !util.isBoolean(value)) {
- throw (errorsMap["TMP_ERROR"]);
- }
-
- args.enableHighAccuracy = value;
- });
-
- this.__defineGetter__("timeout", function() {
- return args.timeout;
- });
-
- this.__defineSetter__("timeout", function(value) {
- if (!util.isUndefined(value) && !util.isNumberInRange(value, 0, Infinity)) {
- throw (errorsMap["TMP_ERROR"]);
- }
-
- args.timeout = value;
- });
-
- this.__defineGetter__("maximumAge", function() {
- return args.maximumAge || 0;
- });
-
- this.__defineSetter__("maximumAge", function(value) {
- if (!util.isUndefined(value) && !util.isNumberInRange(value, 0, Infinity)) {
- throw (errorsMap["TMP_ERROR"]);
- }
-
- args.maximumAge = value;
- });
- }
-
- //Factory function that checks Gears object to ensure that it contains
- //valid coordinate data and creates an HTML 5 Coordinates object from it
- var createCoordinates = function(fromGearsCoords) {
-
- //Keep the Coordinates object private so we only navigator members can instantiate it
- var Coordinates = function(lat, lon, alt, acc, altAcc) {
- this.__defineGetter__("latitude", function() {
- return lat;
- });
-
- this.__defineGetter__("longitude", function() {
- return lon;
- });
-
- this.__defineGetter__("altitude", function() {
- return util.isPositiveNumber(alt) ? alt : null;
- });
-
- this.__defineGetter__("accuracy", function() {
- return util.isPositiveNumber(acc) ? acc : Number.MAX_VALUE;
- });
-
- this.__defineGetter__("altitudeAccuracy", function() {
- return util.isPositiveNumber(altAcc) ? altAcc : null;
- });
-
- this.__defineGetter__("heading", function() {
- return null; //Not supported by Gears
- });
-
- this.__defineGetter__("speed", function() {
- return null; //Not supported by Gears
- });
- };
-
- if (util.nullUndefinedArgument(fromGearsCoords.latitude)) {
- throw errorsMap["geo_coordinates_nullUndefinedLatitude"];
- }
-
- if (util.nullUndefinedArgument(fromGearsCoords.longitude)) {
- throw errorsMap["geo_coordinates_nullUndefinedLongitude"];
- }
-
- return new Coordinates(fromGearsCoords.latitude, fromGearsCoords.longitude, fromGearsCoords.altitude, fromGearsCoords.accuracy, fromGearsCoords.altitudeAccuracy);
- };
-
- var createPositionError = function(fromGearsError) {
- var PositionError = function(errorCode, msg) {
- this.__defineGetter__("code", function() {
- return errorCode;
- });
-
- this.__defineGetter__("message", function() {
- return msg;
- });
- };
-
- //Getters for the instance error codes used by clients
- PositionError.prototype.__defineGetter__("PERMISSION_DENIED", function() {
- return 1;
- });
-
- PositionError.prototype.__defineGetter__("POSITION_UNAVAILABLE", function() {
- return 2;
- });
-
- PositionError.prototype.__defineGetter__("TIMEOUT", function() {
- return 3;
- });
-
- //Map the Gears error code to the HTML 5 error codes and return the Gears error message
- switch (fromGearsError.code) {
- //Not used by Gears but included for completeness
- case fromGearsError.PERMISSION_DENIED:
- return new PositionError(PositionError.prototype.PERMISSION_DENIED, fromGearsError.message);
- case fromGearsError.TIMEOUT:
- return new PositionError(PositionError.prototype.TIMEOUT, fromGearsError.message);
- default:
- return new PositionError(PositionError.prototype.POSITION_UNAVAILABLE, fromGearsError.message);
- }
- };
-
- }
- var nativeXMLHttpRequest = XMLHttpRequest;
-
- XMLHttpRequest = function() {
- var that = this;
- var request = new nativeXMLHttpRequest();
- var hasValidOnReadyStateChange = false;
-
- // The object has been constructed.
- this.__defineGetter__("UNSENT", function() {
- return 0;
- });
-
- // The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.
- this.__defineGetter__("OPENED", function() {
- return 1;
- });
-
- /*
- * All HTTP headers have been received. Several response members of the object are now available.
- * HEADERS_RECEIVED is same as SENT of Google Gears.
- */
- this.__defineGetter__("HEADERS_RECEIVED", function() {
- return 2;
- });
-
- /*
- * The response entity body is being received.
- * LOADING is same as Interactive of Google Gears.
- */
- this.__defineGetter__("LOADING", function() {
- return 3;
- });
-
- // The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).
- this.__defineGetter__("DONE", function() {
- return 4;
- });
-
- // The XMLHttpRequest object can be in several states. The readyState attribute, on getting, must return the current state, which must be one of the above values.
- this.__defineGetter__("readyState", function() {
- return request.readyState;
- });
-
- this.__defineGetter__("status", function() {
- var result = 0;
-
- try {
- result = request.status;
- }
- catch (e) {
- }
-
- // Return the HTTP status text.
- return result;
- });
-
- this.__defineGetter__("statusText", function() {
- var result = "";
-
- try {
- result = request.statusText;
- }
- catch (e) {
- }
-
- // Return the HTTP status text.
- return result;
- });
-
- this.__defineGetter__("responseText", function() {
- var result = "";
-
- try {
- result = request.responseText;
- }
- catch (e) {
- }
-
- // Return the text response entity body.
- return result;
- });
-
- this.__defineGetter__("responseXML", function() {
- // If the state is not DONE return null and terminate these steps
- if (!(this.readyState == this.DONE)) {
- return null;
- }
-
- //parse responseText to XML Document
- var parser = new DOMParser();
- var xmlDoc = null;
-
- try{
- xmlDoc = parser.parseFromString (this.responseText, "text/xml");
- }
- catch (e) {
- }
- //Return the XML response entity body.
- return xmlDoc;
- });
-
- this.open = function(method, url, sync, username, password) {
- if (!util.hasArgument(arguments) || arguments.length == 1) {
- throw errorsMap["not_enough_args"];
- }
-
- try {
- switch(arguments.length) {
- case 2:
- // Native XMLHttp Request must have three arguments
- // However, gears only takes two. Therefore, we
- // should make request asynchronous to support
- // previous functionality.
- request.open(method, url, true);
- break;
- case 3:
- request.open(method, url, sync);
- break;
- case 4:
- request.open(method, url, sync, username);
- break;
- default:
- request.open(method, url, sync, username, password);
- }
- }
- catch (e) {
- }
- };
-
- this.send = function(data) {
- if (util.hasTooManyArguments(arguments)) {
- throw errorsMap["invalid_state_err"];
- }
-
- // Gears accept data to be a blob which we are not supporting here.
- if (data && !util.isString(data)) {
- throw errorsMap["TMP_ERROR"];
- }
-
- try {
- request.send(data);
- }
- catch (e) {
- throw errorsMap["invalid_state_err"];
- }
- };
-
- this.abort = function() {
- try {
- request.abort();
- }
- catch (e) {
- }
- };
-
- this.getResponseHeader = function(header) {
- if (!util.isString(header)) {
- return null;
- }
-
- try {
- return request.getResponseHeader(header);
- }
- catch (e) {
- throw errorsMap["invalid_state_err"];
- }
- };
-
- this.getAllResponseHeaders = function() {
- try {
- return request.getAllResponseHeaders();
- }
- catch (e) {
- throw errorsMap["invalid_state_err"];
- }
- };
-
- this.setRequestHeader = function(header, value) {
- if (!util.hasArgument(arguments) || arguments.length == 1) {
- throw errorsMap["not_enough_args"];
- }
- else if (!header || !util.isString(header) || !value || !util.isString(value)) {
- return;
- }
-
- try {
- request.setRequestHeader(header, value);
- }
- catch (e) {
- throw errorsMap["invalid_state_err"];
- }
- };
-
- this.__defineSetter__("onreadystatechange", function(handler) {
- /*
- * The behaviour in 6.0 browser:
- * If the handler is not a function
- * (this includes undefined, string, number, etc)
- * Then onreadystatechange is set to null (Gears would throw exception)
- * Otherwise assign the function to onreadystatechange
- */
- if (util.isFunction(handler)) {
- hasValidOnReadyStateChange = true;
- request.onreadystatechange = function() {
- handler.apply(that);
- };
- }
- else {
- hasValidOnReadyStateChange = false;
- }
- });
-
- this.__defineGetter__("onreadystatechange", function() {
- if (hasValidOnReadyStateChange) {
- return request.onreadystatechange;
- }
- return null;
- });
-
- // The object name is not 'XMLHttpRequest' to prevent collision with a global XMLHttpRequest object.
- // Overriding toString method to return expected string.
- this.toString = function() {
- return "[object XMLHttpRequest]";
- };
- };
-
- openDatabase = function(name, version, displayName, estimatedSize) {
- if (!util.hasArgument(arguments)) {
- throw errorsMap["syntax_err"];
- }
- else if (!util.isString(name)) {
- throw errorsMap["invalid_state_err"];
- }
-
- try {
- return new Database(name);
- }
- catch (e) {
- }
- };
-
- function Database(name) {
- var db = google.gears.factory.create("beta.database");
-
- try {
- db.open(name);
- }
- catch (e) {
- throw errorsMap["TMP_ERROR"];
- }
-
- // Should return immediately, so timer is set.
- this.transaction = function(callback, errorCallback, successCallback) {
- if (!util.hasArgument(arguments)) {
- throw errorsMap["invalid_state_err"];
- }
- else if (!util.isFunction(callback) || (errorCallback && !util.isFunction(errorCallback)) || (successCallback && !util.isFunction(successCallback))) {
- throw errorsMap["type_mismatch_err"];
- }
-
- setTimeout(function() {
- transactionAsync(callback, errorCallback, successCallback);
- }, 50);
- };
-
- // Should return immediately, so timer is set.
- this.readTransaction = function(callback, errorCallback, successCallback) {
- if (!util.hasArgument(arguments)) {
- throw errorsMap["type_mismatch_err"];
- }
- else if (!util.isFunction(callback) || (errorCallback && !util.isFunction(errorCallback)) || (successCallback && !util.isFunction(successCallback))) {
- throw errorsMap["type_mismatch_err"];
- }
-
- setTimeout(function() {
- transactionAsync(callback, errorCallback, successCallback, true);
- }, 50);
- };
-
- function transactionAsync(callback, errorCallback, successCallback, readOnly) {
- try {
- // Optimizing by using begin and commit commands.
- db.execute("begin", null);
- var sqlTransaction = new SQLTransaction(db, readOnly);
- callback(sqlTransaction);
- var lastError = sqlTransaction.getLastError();
-
- if (lastError) {
- throw lastError;
- }
- }
- catch (e) {
- if (errorCallback) {
- errorCallback(e instanceof SQLError ? e : new SQLError());
- }
- return;
- }
- finally {
- db.execute("commit", null);
- }
-
- if (successCallback) {
- successCallback();
- }
- }
-
- // Google gears doesn't support version. version will return 0.0 as default
- this.__defineGetter__("version", function() {
- return "0.0";
- });
-
- // changeVersion does nothing
- this.changeVersion = function() {
- };
-
-
- this.toString = function() {
- return "[object Database]";
- };
- }
-
- function SQLTransaction(db, mode) {
- var readOnly = mode;
- var lastError;
-
- this.executeSql = function(sqlStatement, args, callback, errorCallback) {
- if (!util.hasArgument(arguments)) {
- throw errorsMap["syntax_err"];
- }
-
- try {
- if (readOnly) {
- // In readonly mode, checking if select is at the begining of the sqlStatement.
- sqlStatement = sqlStatement.replace(/^\s+|\s+$/g, "");
- if (sqlStatement.search(/^select/i) != 0) {
- throw new SQLError(1, errorsMap["not_authorized"]);
- }
- }
-
- var gearsResultSet;
-
- try {
- gearsResultSet = db.execute(sqlStatement, args);
- }
- catch (e) {
- if (e.toString().search(/constraint failed/) != -1) {
- throw new SQLError(6, errorsMap["constraint_failed"]);
- }
- else {
- throw new SQLError();
- }
- }
-
- if (util.isFunction(callback)) {
- callback(this, new SQLResultSet(db.lastInsertRowId, db.rowsAffected, buildSQLResultSetRowList(gearsResultSet)));
- }
-
- //It's required to call close() when finished with any result set.
- if (gearsResultSet) {
- gearsResultSet.close();
- gearsResultSet = null;
- }
-
- }
- catch (e) {
- lastError = (e instanceof SQLError ? e : new SQLError());
-
- if (util.isFunction(errorCallback)) {
- errorCallback(this, lastError);
- }
- }
- };
-
- this.getLastError = function() {
- return lastError;
- };
-
- this.toString = function() {
- return "[object SQLTransaction]";
- };
- }
-
- function SQLResultSet(insertId, rowsAffected, sqlResultSetRowList) {
- this.__defineGetter__("insertId", function() {
- return insertId;
- });
-
- this.__defineGetter__("rowsAffected", function() {
- return rowsAffected;
- });
-
- this.__defineGetter__("rows", function() {
- return sqlResultSetRowList;
- });
-
- this.toString = function() {
- return "[object SQLResultSet]";
- };
- }
-
- function SQLResultSetRowList(items) {
- this.__defineGetter__("length", function() {
- return items.length;
- });
-
- this.item = function(index) {
- if (index < 0 || index >= this.length) {
- return null;
- }
-
- return items[index];
- };
-
- this.toString = function() {
- return "[object SQLResultSetRowList]";
- };
- }
-
- function SQLError(code, message) {
- code = code || 0;
- message = message || errorsMap["db_error_unknown"];
-
- this.__defineGetter__("code", function() {
- return code;
- });
-
- this.__defineGetter__("message", function() {
- return message;
- });
-
- this.toString = function() {
- return "[object SQLError]";
- };
- }
-
- function buildSQLResultSetRowList(gearsResultSet) {
- var items = new Array();
-
- while (gearsResultSet.isValidRow()) {
- fieldCount = gearsResultSet.fieldCount();
-
- var item = new Object();
- for (var counter = 0; counter < fieldCount; counter++) {
- var fieldName = gearsResultSet.fieldName(counter);
- item[fieldName] = gearsResultSet.field(counter);
- }
-
- items.push(item);
-
- gearsResultSet.next();
- }
-
- return new SQLResultSetRowList(items);
- }
-
- /*
- * workerRelay is responsible for keeping track of messages
- * mainly to make sure that no message is lost while the worker
- * is initializing
- * workerRelay creates all userWorkers using one workerpool,
- * although this means that the childWorkers are capable of communicating with each other
- * we are not allowing it by restricting the workerId the childWorkers may send messages to
- */
- var workerRelay = (function() {
-
- /* Location of worker shim in URL.*/
- var workerWrapperUrl = "html5_worker.js";
-
- var relayMap = {};
- var relayWP = google.gears.factory.create("beta.workerpool");
-
- relayWP.onmessage = function(messageText, senderId, messageObject) {
- if (messageObject.body.type == "ready") {
- //a one-time signal that the initialization is done
- //start working on the backlog if there is one
- relayMap[messageObject.sender].ready = true;
- processQueue(messageObject.sender);
- }
- else if (messageObject.body.type == "message") {
- //Test to see if sender contained in object is valid
- var mainWorker = relayMap[messageObject.sender].main;
- var onMessageFunc = mainWorker.onmessage;
- if (util.isFunction(onMessageFunc)) {
- onMessageFunc.call(mainWorker, {
- data: messageObject.body.content
- });
- }
- }
- else if (messageObject.body.type == "error") {
- var mainWorker = relayMap[messageObject.sender].main;
- var onErrorFunc = mainWorker.onerror;
- if (util.isFunction(onErrorFunc)) {
- onErrorFunc.call(mainWorker, messageObject.body.content);
- }
- }
- else if (messageObject.body.type == "debug") {
- }
- };
-
- this.createNewWorker = function(fileUrl, mainWorker) {
- var childId = relayWP.createWorkerFromUrl(workerWrapperUrl);
- fetchAndSendScript(fileUrl, childId);
-
- relayMap[childId] = {
- queue: new Array(),
- main: mainWorker,
- ready: false
- };
- return childId;
- };
-
- this.postToWorker = function(message, childId) {
- if (relayMap[childId].ready && !relayMap[childId].queue.length) {
- relayWP.sendMessage(message, childId);
- }
- else {
- addToQueue(message, childId);
- }
- };
-
- function processQueue(childId) {
- while (relayMap[childId].queue.length) {
- var msg = relayMap[childId].queue.shift();
- relayWP.sendMessage(msg, childId);
- }
- }
-
- function addToQueue(message, childId) {
- relayMap[childId].queue.push(message);
- }
-
- function fetchAndSendScript(fileUrl, childId) {
- var requestFile = google.gears.factory.create("beta.httprequest");
- requestFile.open('GET', fileUrl);
- requestFile.onreadystatechange = function() {
- if (requestFile.readyState == 4 && requestFile.status == 200) {
- relayWP.sendMessage(requestFile.responseText, childId);
- }
- };
-
- requestFile.send();
- }
- return this;
- })();
-
- /*The Worker object is a facade to simulate HTML5
- *Beside error checking,
- *the actual processing is delegated to workerRelay
- */
- Worker = function(fileUrl) {
- if (!workerRelay) {
- throw "Elemented with id 'html5_init' is not found. Worker with " + fileUrl + " cannot be created";
- }
-
- if (!util.hasArgument(arguments)) {
- throw errorsMap["not_enough_args"];
- }
-
- if (!util.isString(fileUrl)) {
- fileUrl = " ";
- }
- else if (!fileUrl.length) {
- throw errorsMap["syntax_err"];
- }
-
- var onMessageFunction = null;
- var sendToThisId;
- var INSTANCE_CONTEXT = this;
-
- this.__defineSetter__("onmessage", function(func) {
- //only reassign if onmessage is a valid function
- //otherwise let it go to null
-
- if (!util.isFunction(func)) {
- onMessageFunction = null;
- return;
- }
- else {
- onMessageFunction = func;
- }
- });
-
- this.__defineGetter__("onmessage", function() {
- return onMessageFunction;
- });
-
- this.postMessage = function(message) {
- if (!util.isPositiveNumber(sendToThisId)) {
- return;
- }
-
- if (util.hasTooManyArguments(arguments)) {
- throw errorsMap["worker_error_message_port"];
- }
-
- workerRelay.postToWorker(message, sendToThisId);
- };
-
- this.__defineSetter__("onerror", function(func) {
- window.onerror = func;
- });
-
- this.__defineGetter__("onerror", function() {
- return window.onerror;
- });
-
- this.toString = function() {
- return "[object Worker]";
- };
-
- if (fileUrl.indexOf(".js") != -1) {
- sendToThisId = workerRelay.createNewWorker(fileUrl, INSTANCE_CONTEXT);
- }
- };
-
- /* Utility class */
- function Utility() {
- // hasArgument() - returns true if at least 1 arg is present (including
- // null or undefined), false otherwise
- this.hasArgument = function(args) {
- return args && (args.length > 0);
- };
-
- // hasTooManyArguments() - returns true if number of args passed is
- // greater than number expected, false otherwise
- this.hasTooManyArguments = function(args) {
- return args && (args.length > args.callee.length);
- };
-
- // nullUndefinedArgument() - returns true if arg is null or undefined,
- // false otherwise
- this.nullUndefinedArgument = function(arg) {
- return (this.isNull(arg) || this.isUndefined(arg));
- };
-
- // isUndefined() - returns true if arg is undefined, false otherwise
- // Agree it looks bizarre but safe, since undefined can be re-assigned.
- this.isUndefined = function(arg) {
- return (arg == null && arg !== null);
- };
-
- // isNull() - returns true if arg is null, false otherwise
- this.isNull = function(arg) {
- return (arg === null);
- };
-
- // isNumber() - returns true if arg is of type number, false otherwise
- this.isNumber = function(arg) {
- return typeof arg == "number";
- };