blob: f72da12016cc173364dc5e4554608d1b47e05585 [file] [log] [blame]
if (typeof(DeviceInfo) != 'object')
DeviceInfo = {};
function Cordova() {
ready = true;
available = true;
sceneController = null;
};
Cordova.exec = function(win, fail, clazz, action, args) {
setTimeout(function() {
Cordova.plugins[clazz].execute(action, args, win, fail);
}, 0);
}
Cordova.checkArgs = function(args, func) {
if (typeof args == 'object')
func.apply(null, args);
else
func(args);
}
Cordova.callback = function(success, win, fail) {
if (success)
win();
else
fail();
}
// translates the action into an API call
accelerometerAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'setFastAccelerometer':
Cordova.checkArgs(args, navigator.accelerometer.setFastAccelerometer);
actionFound = true;
break;
case 'getCurrentAcceleration':
Cordova.checkArgs(args, navigator.accelerometer.getCurrentAcceleration);
actionFound = true;
break;
case 'watchAcceleration':
Cordova.checkArgs(args, navigator.accelerometer.watchAcceleration);
actionFound = true;
break;
case 'clearWatch':
Cordova.checkArgs(args, navigator.accelerometer.clearWatch);
actionFound = true;
break;
case 'start':
Cordova.checkArgs(args, navigator.accelerometer.start);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
applicationAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'activate':
Cordova.checkArgs(args, navigator.application.activate);
actionFound = true;
break;
case 'deactivate':
Cordova.checkArgs(args, navigator.application.deactivate);
actionFound = true;
break;
case 'getIdentifier':
Cordova.checkArgs(args, navigator.application.getIdentifier);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
cameraAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'getPicture':
console.log("in here");
Cordova.checkArgs(args, navigator.camera.getPicture);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
// translates the action into an API call
compassAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'getCurrentHeading':
Cordova.checkArgs(args, navigator.compass.getCurrentHeading);
actionFound = true;
break;
case 'watchHeading':
Cordova.checkArgs(args, navigator.compass.watchHeading);
actionFound = true;
break;
case 'clearWatch':
Cordova.checkArgs(args, navigator.compass.clearWatch);
actionFound = true;
break;
case 'start':
Cordova.checkArgs(args, navigator.compass.start);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
debugAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'log':
Cordova.checkArgs(args, window.debug.log);
actionFound = true;
break;
case 'warn':
Cordova.checkArgs(args, window.debug.warn);
actionFound = true;
break;
case 'error':
Cordova.checkArgs(args, window.debug.error);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
deviceAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'getDeviceInfo':
Cordova.checkArgs(args, navigator.device.getDeviceInfo);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
geolocationAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'getCurrentPosition':
Cordova.checkArgs(args, navigator.geolocation.getCurrentPosition);
actionFound = true;
break;
case 'watchPosition':
Cordova.checkArgs(args, navigator.geolocation.watchPosition);
actionFound = true;
break;
case 'clearWatch':
Cordova.checkArgs(args, navigator.geolocation.clearWatch);
actionFound = true;
break;
case 'start':
Cordova.checkArgs(args, navigator.geolocation.start);
actionFound = true;
break;
case 'stop':
Cordova.checkArgs(args, navigator.geolocation.stop);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
mapAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'show':
Cordova.checkArgs(args, navigator.map.show);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
mouseAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'simulateMouseClick':
Cordova.checkArgs(args, navigator.mouse.simulateMouseClick);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
networkAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'isReachable':
Cordova.checkArgs(args, navigator.network.isReachable);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
notificationAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'alert':
Cordova.checkArgs(args, navigator.notification.alert);
actionFound = true;
break;
case 'showBanner':
Cordova.checkArgs(args, navigator.notification.showBanner);
actionFound = true;
break;
case 'newDashboard':
Cordova.checkArgs(args, navigator.notification.newDashboard);
actionFound = true;
break;
case 'removeBannerMessage':
Cordova.checkArgs(args, navigator.notification.removeBannerMessage);
actionFound = true;
break;
case 'clearBannerMessage':
Cordova.checkArgs(args, navigator.notification.clearBannerMessage);
actionFound = true;
break;
case 'vibrate':
Cordova.checkArgs(args, navigator.notification.vibrate);
actionFound = true;
break;
case 'beep':
Cordova.checkArgs(args, navigator.notification.beep);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
orientationAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'setOrientation':
Cordova.checkArgs(args, navigator.orientation.setOrientation);
actionFound = true;
break;
case 'getOrientation':
Cordova.checkArgs(args, navigator.orientation.getOrientation);
actionFound = true;
break;
case 'start':
Cordova.checkArgs(args, navigator.orientation.start);
actionFound = true;
break;
case 'watchOrientation':
Cordova.checkArgs(args, navigator.orientation.watchOrientation);
actionFound = true;
break;
case 'clearWatch':
Cordova.checkArgs(args, navigator.orientation.clearWatch);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
smsAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'send':
Cordova.checkArgs(args, navigator.sms.send);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
telephonyAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'send':
Cordova.checkArgs(args, navigator.telephony.send);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
windowAPI = {
execute: function(action, args, win, fail) {
var actionFound = false;
switch(action) {
case 'newCard':
Cordova.checkArgs(args, navigator.window.newCard);
actionFound = true;
break;
case 'setFullScreen':
Cordova.checkArgs(args, navigator.window.setFullScreen);
actionFound = true;
break;
case 'setWindowProperties':
Cordova.checkArgs(args, navigator.window.setWindowProperties);
actionFound = true;
break;
case 'blockScreenTimeout':
Cordova.checkArgs(args, navigator.window.blockScreenTimeout);
actionFound = true;
break;
case 'setSubtleLightbar':
Cordova.checkArgs(args, navigator.window.setSubtleLightbar);
actionFound = true;
break;
}
Cordova.callback(actionFound, win, fail);
}
}
// this mapping acts as a shim to the webOS APIs
Cordova.plugins = {};
Cordova.plugins['navigator.accelerometer'] = accelerometerAPI;
Cordova.plugins['navigator.application'] = applicationAPI;
Cordova.plugins['navigator.camera'] = cameraAPI;
Cordova.plugins['navigator.compass'] = compassAPI;
Cordova.plugins['window.debug'] = debugAPI;
Cordova.plugins['navigator.device'] = deviceAPI;
Cordova.plugins['navigator.geolocation'] = geolocationAPI;
Cordova.plugins['navigator.map'] = mapAPI;
Cordova.plugins['navigator.mouse'] = mouseAPI;
Cordova.plugins['navigator.network'] = networkAPI;
Cordova.plugins['navigator.notification'] = notificationAPI;
Cordova.plugins['navigator.orientation'] = orientationAPI;
Cordova.plugins['navigator.sms'] = smsAPI;
Cordova.plugins['navigator.telephony'] = telephonyAPI;
Cordova.plugins['navigator.window'] = windowAPI;
document.addEventListener('DOMContentLoaded', function () {
window.cordova = new Cordova();
navigator.device.deviceReady();
});
/*
* This class contains acceleration information
* @constructor
* @param {Number} x The force applied by the device in the x-axis.
* @param {Number} y The force applied by the device in the y-axis.
* @param {Number} z The force applied by the device in the z-axis.
*/
function Acceleration(x, y, z) {
/*
* The force applied by the device in the x-axis.
*/
this.x = x;
/*
* The force applied by the device in the y-axis.
*/
this.y = y;
/*
* The force applied by the device in the z-axis.
*/
this.z = z;
/*
* The time that the acceleration was obtained.
*/
this.timestamp = new Date().getTime();
};
/*
* This class specifies the options for requesting acceleration data.
* @constructor
*/
function AccelerationOptions() {
/*
* The timeout after which if acceleration data cannot be obtained the errorCallback
* is called.
*/
this.timeout = 10000;
};
/*
* This class provides access to device accelerometer data.
* @constructor
*/
function Accelerometer() {
/*
* The last known acceleration.
*/
this.lastAcceleration = null;
};
/*
* Tells WebOS to put higher priority on accelerometer resolution. Also relaxes the internal garbage collection events.
* @param {Boolean} state
* Dependencies: Mojo.windowProperties
* Example:
* navigator.accelerometer.setFastAccelerometer(true)
*/
Accelerometer.prototype.setFastAccelerometer = function(state) {
navigator.windowProperties.fastAccelerometer = state;
navigator.window.setWindowProperties();
};
/*
* Asynchronously aquires the current acceleration.
* @param {Function} successCallback The function to call when the acceleration
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the acceleration data.
* @param {AccelerationOptions} options The options for getting the accelerometer data
* such as timeout.
*/
Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) {
var referenceTime = 0;
if (this.lastAcceleration)
referenceTime = this.lastAcceleration.timestamp;
else
this.start();
var timeout = 20000;
var interval = 500;
if (typeof(options) == 'object' && options.interval)
interval = options.interval;
if (typeof(successCallback) != 'function')
successCallback = function() {};
if (typeof(errorCallback) != 'function')
errorCallback = function() {};
var dis = this;
var delay = 0;
var timer = setInterval(function() {
delay += interval;
//if we have a new acceleration, call success and cancel the timer
if (typeof(dis.lastAcceleration) == 'object' && dis.lastAcceleration != null && dis.lastAcceleration.timestamp > referenceTime) {
successCallback(dis.lastAcceleration);
clearInterval(timer);
} else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
errorCallback();
clearInterval(timer);
}
//else the interval gets called again
}, interval);
};
/*
* Asynchronously aquires the acceleration repeatedly at a given interval.
* @param {Function} successCallback The function to call each time the acceleration
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the acceleration data.
* @param {AccelerationOptions} options The options for getting the accelerometer data
* such as timeout.
*/
Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) {
this.getCurrentAcceleration(successCallback, errorCallback, options);
// TODO: add the interval id to a list so we can clear all watches
var frequency = (options != undefined)? options.frequency : 10000;
var that = this;
return setInterval(function() {
that.getCurrentAcceleration(successCallback, errorCallback, options);
}, frequency);
};
/*
* Clears the specified accelerometer watch.
* @param {String} watchId The ID of the watch returned from #watchAcceleration.
*/
Accelerometer.prototype.clearWatch = function(watchId) {
clearInterval(watchId);
};
/*
* Starts the native acceleration listener.
*/
Accelerometer.prototype.start = function() {
var that = this;
//Mojo.Event.listen(document, "acceleration", function(event) {
document.addEventListener("acceleration", function(event) {
var accel = new Acceleration(event.accelX, event.accelY, event.accelZ);
that.lastAcceleration = accel;
});
};
if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer();
function Application() {
};
/*
* Tell webOS to activate the current page of your app, bringing it into focus.
* Example:
* navigator.application.activate();
*/
Application.prototype.activate = function() {
PalmSystem.activate();
};
/*
* Tell webOS to deactivate your app.
* Example:
* navigator.application.deactivate();
*/
Application.prototype.deactivate = function() {
PalmSystem.deactivate();
};
/*
* Returns the identifier of the current running application (e.g. com.yourdomain.yourapp).
* Example:
* navigator.application.getIdentifier();
*/
Application.prototype.getIdentifier = function() {
return PalmSystem.identifier;
};
if (typeof navigator.application == "undefined") navigator.application = new Application();
/*
* This class provides access to the device audio
* @constructor
*/
Cordova.overrideAudio = function() {
Cordova.MojoAudio = Audio;
Audio = function(src) {
this.src = src;
};
Audio.prototype.play = function() {
// this.src = src;
// The 'end' event listener doesn't seem to work, so we have to call stop before playing
// otherwise, we'll never be able to play again
if (this.paused && !this.stopped) {
this.paused = false;
this.playing = true;
this.audioPlayer.play();
} else {
if (this.audioPlayer)
this.stop();
if (!this.playing) {
this.paused = false;
this.playing = true;
this.stopped = false;
this.audioPlayer = new Cordova.MojoAudio();
var file = Mojo.appPath + this.src;
if (this.audioPlayer.palm) {
this.audioPlayer.mojo.audioClass = "media";
}
this.audioPlayer.src = file;
//event doesn't work, see above
this.audioPlayer.addEventListener('end', this.endHandler, false);
this.audioPlayer.play();
}
}
};
Audio.prototype.pause = function() {
if (this.stopped)
return;
this.paused = true;
if (this.playing) {
this.playing = false;
this.stopped = false;
this.audioPlayer.pause();
} else {
this.playing = false;
this.paused = false;
this.stopped = true;
}
};
Audio.prototype.stop = function() {
this.audioPlayer.pause();
this.audioPlayer.src = null;
this.playing = false;
this.paused = false;
this.stopped = true;
};
// End event handler not working (see comment in Audio.prototype.play)
Audio.prototype.endHandler = function () {
this.audioPlayer.removeEventListener('end', endHandler, false);
this.audioPlayer.pause();
this.audioPlayer.src = null;
this.paused = false;
this.stopped = true;
};
/*
* This class contains information about any Media errors.
* @constructor
*/
MediaError = function() {
this.code = null,
this.message = "";
};
MediaError.MEDIA_ERR_ABORTED = 1;
MediaError.MEDIA_ERR_NETWORK = 2;
MediaError.MEDIA_ERR_DECODE = 3;
MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
}
document.addEventListener("deviceready", Cordova.overrideAudio, false);
/*
* This class provides access to the device camera.
* @constructor
*/
function Camera() {
};
/*
* @param {Function} successCallback
* @param {Function} errorCallback
* @param {Object} options
*/
Camera.prototype.getPicture = function(successCallback, errorCallback, options) {
var filename = "";
if (typeof options != 'undefined' && typeof options.filename != 'undefined') {
filename = options.filename;
}
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'launch',
parameters: {
id: 'com.palm.app.camera',
params: {
appId: 'com.palm.app.camera',
name: 'capture',
sublaunch: true,
filename: filename
}
},
onSuccess: successCallback,
onFailure: errorCallback
});
};
if (typeof navigator.camera == 'undefined') navigator.camera = new Camera();
/*
* This class provides access to the device contacts.
* @constructor
*/
function Contacts() {
};
function Contact() {
this.phones = [];
this.emails = [];
this.name = {
givenName: "",
familyName: "",
formatted: ""
};
this.id = "";
};
Contact.prototype.displayName = function()
{
// TODO: can be tuned according to prefs
return this.givenName + " " + this.familyName;
};
function ContactsFilter(name) {
if (name)
this.name = name;
else
this.name = "";
};
/*
* @param {ContactsFilter} filter Object with filter properties. filter.name only for now.
* @param {function} successCallback Callback function on success
* @param {function} errorCallback Callback function on failure
* @param {object} options Object with properties .page and .limit for paging
*/
Contacts.prototype.find = function(filter, successCallback, errorCallback, options) {
errorCallback({ name: "ContactsError", message: "Cordova Palm contacts not implemented" });
};
Contacts.prototype.success_callback = function(contacts_iterator) {
};
if (typeof navigator.contacts == "undefined") navigator.contacts = new Contacts();
/*
* This class provides access to device compass data.
* @constructor
*/
function Compass() {
/*
* The last known heading.
*/
this.lastHeading = null;//new CompassHeading;
};
/*
* Asynchronously aquires the current compass heading.
* @param {Function} successCallback The function to call when the compass
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the compass data.
* @param {CompassOptions} options The options for getting the compass data
* such as timeout.
*/
Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) {
var referenceTime = 0;
var compassHeading = new CompassHeading();
if (this.lastHeading)
referenceTime = this.lastHeading.timestamp;
else
this.start();
var timeout = 20000;
var interval = 500;
if (typeof(options) == 'object' && options.interval)
interval = options.interval;
if (typeof(successCallback) != 'function')
successCallback = function() {};
if (typeof(errorCallback) != 'function')
errorCallback = function() {};
var dis = this;
var delay = 0;
var timer = setInterval(function() {
delay += interval;
//if we have a new compass heading, call success and cancel the timer
if (typeof(dis.lastHeading) == 'object' && dis.lastHeading != null && dis.lastHeading.timestamp > referenceTime) {
compassHeading.timestamp = new Date(referenceTime);
compassHeading.magneticHeading = dis.lastHeading.magHeading;
compassHeading.trueHeading = dis.lastHeading.trueHeading;
if (dis.lastHeading.headingAccuracy === undefined)
compassHeading.headingAccuracy = 1;
else
compassHeading.headingAccuracy = dis.lastHeading.headingAccuracy;
successCallback(compassHeading);
//successCallback(dis.lastHeading.magHeading);
clearInterval(timer);
} else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
errorCallback();
clearInterval(timer);
}
//else the interval gets called again
}, interval);
};
/*
* Asynchronously aquires the compass heading repeatedly at a given interval.
* @param {Function} successCallback The function to call each time the acceleration
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the compass data.
* @param {CompassOptions} options The options for getting the compass data
* such as timeout.
*/
Compass.prototype.watchHeading = function(successCallback, errorCallback, options) {
this.getCurrentHeading(successCallback, errorCallback, options);
// TODO: add the interval id to a list so we can clear all watches
var frequency = (options != undefined)? options.frequency : 10000;
var that = this;
return setInterval(function() {
that.getCurrentHeading(successCallback, errorCallback, options);
}, frequency);
};
/*
* Clears the specified heading watch.
* @param {String} watchId The ID of the watch returned from #watchHeading.
*/
Compass.prototype.clearWatch = function(watchId) {
clearInterval(watchId);
};
/*
* Starts the native compass listener.
*/
Compass.prototype.start = function() {
var that = this;
//Mojo.Event.listen(document, "acceleration", function(event) {
document.addEventListener("compass", function(event) {
var heading={};
heading.trueHeading=event.trueHeading;
heading.magHeading=event.magHeading;
heading.timestamp = new Date().getTime();
that.lastHeading = heading;
});
};
function CompassHeading(mHeading, tHeading, accuracy, time) {
if (mHeading === undefined)
this.magneticHeading = null;
else
this.magneticHeading = mHeading;
if (tHeading === undefined)
this.trueHeading = null;
else
this.trueHeading = tHeading;
if (accuracy === undefined)
this.headingAccuracy = null;
else
this.headingAccuracy = accuracy;
if (time === undefined)
this.timestamp = new Date();
else
this.timestamp = new Date(time);
};
function CompassError() {
this.code = null;
this.message = "";
};
CompassError.COMPASS_INTERNAL_ERR = 0;
CompassError.COMPASS_NOT_SUPPORTED = 20;
if (typeof navigator.compass == "undefined") navigator.compass = new Compass();
/*
* This class provides access to the debugging console.
* @constructor
*/
function DebugConsole() {
};
/*
* Print a normal log message to the console
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.log = function(message) {
if (typeof message == 'object')
message = Object.toJSON(message);
this.error(message);
};
/*
* Print a warning message to the console
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.warn = function(message) {
if (typeof message == 'object')
message = Object.toJSON(message);
this.error(message);
};
/**
* Print an error message to the console
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.error = function(message) {
if (typeof message == 'object')
message = Object.toJSON(message);
console.log(JSON.stringify(message));
};
if (typeof window.debug == "undefined") window.debug = new DebugConsole();
/*
* this represents the mobile device, and provides properties for inspecting the model, version, UUID of the
* phone, etc.
* @constructor
*/
function Device() {
this.platform = "palm";
this.version = null;
this.name = null;
this.uuid = null;
this.deviceInfo = null;
};
/*
* A direct call to return device information.
* Example:
* var deviceinfo = JSON.stringify(navigator.device.getDeviceInfo()).replace(/,/g, ', ');
*/
Device.prototype.getDeviceInfo = function() {
return this.deviceInfo;//JSON.parse(PalmSystem.deviceInfo);
};
/*
* needs to be invoked in a <script> nested within the <body> it tells WebOS that the app is ready
TODO: see if we can get this added as in a document.write so that the user doesn't have to explicitly call this method
* Dependencies: Mojo.onKeyUp
* Example:
* navigator.device.deviceReady();
*/
Device.prototype.deviceReady = function() {
// tell webOS this app is ready to show
if (window.PalmSystem) {
// setup keystroke events for forward and back gestures
document.body.addEventListener("keyup", Mojo.onKeyUp, true);
setTimeout(function() { PalmSystem.stageReady(); PalmSystem.activate(); }, 1);
alert = this.showBanner;
}
// fire deviceready event; taken straight from phonegap-iphone
// put on a different stack so it always fires after DOMContentLoaded
window.setTimeout(function () {
var e = document.createEvent('Events');
e.initEvent('deviceready');
document.dispatchEvent(e);
}, 10);
this.setUUID();
this.setDeviceInfo();
};
Device.prototype.setDeviceInfo = function() {
var parsedData = JSON.parse(PalmSystem.deviceInfo);
this.deviceInfo = parsedData;
this.version = parsedData.platformVersion;
this.name = parsedData.modelName;
};
Device.prototype.setUUID = function() {
//this is the only system property webos provides (may change?)
var that = this;
this.service = navigator.service.Request('palm://com.palm.preferences/systemProperties', {
method:"Get",
parameters:{"key": "com.palm.properties.nduid" },
onSuccess: function(result) {
that.uuid = result["com.palm.properties.nduid"];
}
});
};
if (typeof window.device == 'undefined') window.device = navigator.device = new Device();
/*
* This class provides generic read and write access to the mobile device file system.
*/
function File() {
/**
* The data of a file.
*/
this.data = "";
/**
* The name of the file.
*/
this.name = "";
};
/*
* Reads a file from the mobile device. This function is asyncronous.
* @param {String} fileName The name (including the path) to the file on the mobile device.
* The file name will likely be device dependant.
* @param {Function} successCallback The function to call when the file is successfully read.
* @param {Function} errorCallback The function to call when there is an error reading the file from the device.
*/
File.prototype.read = function(fileName, successCallback, errorCallback) {
//Mojo has no file i/o yet, so we use an xhr. very limited
var path = fileName; //incomplete
//Mojo.Log.error(path);
navigator.debug.error(path);
if (typeof successCallback != 'function')
successCallback = function () {};
if (typeof errorCallback != 'function')
errorCallback = function () {};
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200 && xhr.responseText != null) {
this.data = xhr.responseText;
this.name = path;
successCallback(this.data);
} else {
errorCallback({ name: xhr.status, message: "could not read file: " + path });
}
}
};
xhr.open("GET", path, true);
xhr.send();
};
/*
* Writes a file to the mobile device.
* @param {File} file The file to write to the device.
*/
File.prototype.write = function(file) {
//Palm does not provide file i/o
};
if (typeof navigator.file == "undefined") navigator.file = new File();
/*
* This class provides access to device GPS data.
* @constructor
*/
function Geolocation() {
/**
* The last known GPS position.
*/
this.lastPosition = null;
this.lastError = null;
this.callbacks = {
onLocationChanged: [],
onError: []
};
};
/*
* Asynchronously aquires the current position.
* @param {Function} successCallback The function to call when the position
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the position data.
* @param {PositionOptions} options The options for getting the position data
* such as timeout.
*/
Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
/*
var referenceTime = 0;
if (this.lastPosition)
referenceTime = this.lastPosition.timestamp;
else
this.start(options);
*/
var timeout = 20000;
if (typeof(options) == 'object' && options.timeout)
timeout = options.timeout;
if (typeof(successCallback) != 'function')
successCallback = function() {};
if (typeof(errorCallback) != 'function')
errorCallback = function() {};
/*
var dis = this;
var delay = 0;
var timer = setInterval(function() {
delay += interval;
//if we have a new position, call success and cancel the timer
if (dis.lastPosition && typeof(dis.lastPosition) == 'object' && dis.lastPosition.timestamp > referenceTime) {
successCallback(dis.lastPosition);
clearInterval(timer);
} else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
errorCallback();
clearInterval(timer);
}
//else the interval gets called again
}, interval);
*/
var responseTime;
if (timeout <= 5000)
responseTime = 1;
else if (5000 < timeout <= 20000)
responseTime = 2;
else
responseTime = 3;
var timer = setTimeout(function() {
errorCallback({
message: "timeout"
});
},
timeout);
var startTime = (new Date()).getTime();
var alias = this;
// It may be that getCurrentPosition is less reliable than startTracking ... but
// not sure if we want to be starting and stopping the tracker if we're not watching.
//new Mojo.Service.Request('palm://com.palm.location', {
navigator.service.Request('palm://com.palm.location', {
method: "getCurrentPosition",
parameters: {
responseTime: responseTime
},
onSuccess: function(event) {
alias.lastPosition = {
coords: {
latitude: event.latitude,
longitude: event.longitude,
altitude: (event.altitude >= 0 ? event.altitude: null),
speed: (event.velocity >= 0 ? event.velocity: null),
heading: (event.heading >= 0 ? event.heading: null),
accuracy: (event.horizAccuracy >= 0 ? event.horizAccuracy: null),
altitudeAccuracy: (event.vertAccuracy >= 0 ? event.vertAccuracy: null)
},
timestamp: new Date().getTime()
};
var responseTime = alias.lastPosition.timestamp - startTime;
if (responseTime <= timeout)
{
clearTimeout(timer);
successCallback(alias.lastPosition);
}
},
onFailure: function() {
errorCallback();
}
});
};
/*
* Asynchronously aquires the position repeatedly at a given interval.
* @param {Function} successCallback The function to call each time the position
* data is available
* @param {Function} errorCallback The function to call when there is an error
* getting the position data.
* @param {PositionOptions} options The options for getting the position data
* such as timeout and the frequency of the watch.
*/
Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
// Invoke the appropriate callback with a new Position object every time the implementation
// determines that the position of the hosting device has changed.
var frequency = 10000;
if (typeof(options) == 'object' && options.frequency)
frequency = options.frequency;
this.start(options, errorCallback);
var referenceTime = 0;
if (this.lastPosition)
referenceTime = this.lastPosition.timestamp;
var alias = this;
return setInterval(function() {
// check if we have a new position, if so call our successcallback
if (!alias.lastPosition)
return;
if (alias.lastPosition.timestamp > referenceTime)
successCallback(alias.lastPosition);
},
frequency);
};
/*
* Clears the specified position watch.
* @param {String} watchId The ID of the watch returned from #watchPosition.
*/
Geolocation.prototype.clearWatch = function(watchId) {
clearInterval(watchId);
this.stop();
};
Geolocation.prototype.start = function(options, errorCallback) {
//options.timeout;
//options.interval;
if (typeof(errorCallback) != 'function')
errorCallback = function() {};
var that = this;
var frequency = 10000;
if (typeof(options) == 'object' && options.frequency)
frequency = options.frequency;
var responseTime;
if (frequency <= 5000)
responseTime = 1;
else if (5000 < frequency <= 20000)
responseTime = 2;
else
responseTime = 3;
//location tracking does not support setting a custom interval :P
this.trackingHandle = navigator.service.Request('palm://com.palm.location', {
method: 'startTracking',
parameters: {
subscribe: true
},
onSuccess: function(event) {
that.lastPosition = {
coords: {
latitude: event.latitude,
longitude: event.longitude,
altitude: (event.altitude >= 0 ? event.altitude: null),
speed: (event.velocity >= 0 ? event.velocity: null),
heading: (event.heading >= 0 ? event.heading: null),
accuracy: (event.horizAccuracy >= 0 ? event.horizAccuracy: null),
altitudeAccuracy: (event.vertAccuracy >= 0 ? event.vertAccuracy: null)
},
timestamp: new Date().getTime()
};
},
onFailure: function() {
errorCallback();
}
});
};
Geolocation.prototype.stop = function() {
this.trackingHandle.cancel();
};
if (typeof navigator.geolocation == "undefined") navigator.geolocation = new Geolocation();
/*
* This class provides access to native mapping applications on the device.
*/
function Map() {
};
/*
* Shows a native map on the device with pins at the given positions.
* @param {Array} positions
*/
Map.prototype.show = function(positions) {
var jsonPos = {};
var pos = null;
if (typeof positions == 'object') {
// If positions is an array, then get the first only, since google's query
// can't take more than one marker (believe it or not).
// Otherwise we assume its a single position object.
if (positions.length) {
pos = positions[0];
} else {
pos = positions;
}
}
else if (navigator.geolocation.lastPosition) {
pos = navigator.geolocation.lastPosition;
} else {
// If we don't have a position, lets use nitobi!
pos = { coords: { latitude: 49.28305, longitude: -123.10689 } };
}
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'open',
parameters: {
id: 'com.palm.app.maps',
params: {
query: "@" + pos.coords.latitude + "," + pos.coords.longitude
}
}
});
};
if (typeof navigator.map == "undefined") navigator.map = new Map();
//===========================
// Mojo Dependencies - we still need to rely on these minimal parts of the Mojo framework - should try to find if we can get access to lower level APIs
// so that we can remove dependence of Mojo
//===========================
Mojo = {
contentIndicator: false,
// called by webOS in certain cases
relaunch: function() {
var launch = JSON.parse(PalmSystem.launchParams);
if (launch['palm-command'] && launch['palm-command'] == 'open-app-menu')
this.fireEvent(window, "appmenuopen");
else
this.fireEvent(window, "palmsystem", launch);
},
// called by webOS when your app gets focus
stageActivated: function() {
this.fireEvent(window, "activate");
},
// called by webOS when your app loses focus
stageDeactivated: function() {
this.fireEvent(window, "deactivate");
},
// this is a stub -- called by webOS when orientation changes
// but the preferred method is to use the orientationchanged
// DOM event
screenOrientationChanged: function(dir) {
},
// used to redirect keyboard events to DOM event "back"
onKeyUp: function(e) {
if (e.keyCode == 27)
this.fireEvent(window, "back");
},
// private method, used to fire off DOM events
fireEvent: function(element, event, data) {
var e = document.createEvent("Event");
e.initEvent(event, false, true);
if (data)
e.data = data;
element.dispatchEvent(e);
},
/*
not sure if these stubs are still needed since the Log object is encapsulated in debugconsole class
and the Service object is encapsulated in the Service class
*/
// stubs to make v8 happier
Service: {},
Log: {}
};function Mouse() {
};
/*
* Possibly useful for automated testing, this call to PalmSystem triggers a mouse click (i.e. touch event).
* x coordinate & y coordinate of where the screen was touched and also a true/false flag to tell WebOS if it should simulate the mouse click
* @param {Number} x
* @param {Number} y
* @param {Boolean} state
* Example:
* navigator.mouse.simulateMouseClick(10, 10, true);
*/
Mouse.prototype.simulateMouseClick = function(x, y, state) {
PalmSystem.simulateMouseClick(x, y, state || true);
};
if (typeof navigator.mouse == "undefined") navigator.mouse = new Mouse();
function Network() {
/*
* The last known Network status.
*/
this.lastReachability = null;
};
Network.prototype.isReachable = function(hostName, successCallback, options) {
this.request = navigator.service.Request('palm://com.palm.connectionmanager', {
method: 'getstatus',
parameters: {},
onSuccess: function(result) {
var status = NetworkStatus.NOT_REACHABLE;
if (result.isInternetConnectionAvailable == true) {
if (result.wan.state == "connected") {
status = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK;
}
if (result.wifi.state == "connected") {
status = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK;
}
}
successCallback(status);
},
onFailure: function() {}
});
};
Network.prototype.connection = function(hostName, successCallback, options) {
this.request = navigator.service.Request('palm://com.palm.connectionmanager', {
method: 'getstatus',
parameters: {},
onSuccess: function(result) {
successCallback(result);
},
onFailure: function() {}
});
};
Network.prototype.connection.type = function(hostName, successCallback, options) {
navigator.network.isReachable(hostName,successCallback, options);
};
function Connection() {
this.code = null;
this.message = "";
};
Connection.UNKNOWN = 'unknown';
Connection.ETHERNET = 'ethernet';
Connection.WIFI = 'wifi';
Connection.CELL_2G = '2g';
Connection.CELL_3G = '3g';
Connection.CELL_4G = '4g';
Connection.NONE = 'none';
/*
* This class contains information about any NetworkStatus.
* @constructor
*/
function NetworkStatus() {
this.code = null;
this.message = "";
};
NetworkStatus.NOT_REACHABLE = 0;
NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK = 1;
NetworkStatus.REACHABLE_VIA_WIFI_NETWORK = 2;
if (typeof navigator.network == "undefined") navigator.network = new Network();
/*
* This class provides access to notifications on the device.
*/
function Notification() {
};
/*
* adds a dashboard to the WebOS app
* @param {String} url
* @param {String} html
* Example:
* navigator.notification.newDashboard("dashboard.html");
*/
Notification.prototype.newDashboard = function(url, html) {
var win = window.open(url, "_blank", "attributes={\"window\":\"dashboard\"}");
html && win.document.write(html);
win.PalmSystem.stageReady();
};
/*
* Displays a banner notification. If specified, will send your 'response' object as data via the 'palmsystem' DOM event.
* If no 'icon' filename is specified, will use a small version of your application icon.
* @param {String} message
* @param {Object} response
* @param {String} icon
* @param {String} soundClass class of the sound; supported classes are: "ringtones", "alerts", "alarm", "calendar", "notification"
* @param {String} soundFile partial or full path to the sound file
* @param {String} soundDurationMs of sound in ms
* Example:
* navigator.notification.showBanner('test message');
*/
Notification.prototype.showBanner = function(message, response, icon, soundClass, soundFile, soundDurationMs) {
var response = response || {
banner: true
};
PalmSystem.addBannerMessage(message, JSON.stringify(response), icon, soundClass, soundFile, soundDurationMs);
};
/**
* Remove a banner from the banner area. The category parameter defaults to 'banner'. Will not remove
* messages that are already displayed.
* @param {String} category
Value defined by the application and usually same one used in {@link showBanner}.
It is used if you have more than one kind of banner message.
*/
Notification.prototype.removeBannerMessage = function(category) {
var bannerKey = category || 'banner';
var bannerId = this.banners.get(bannerKey);
if (bannerId) {
try {
PalmSystem.removeBannerMessage(bannerId);
} catch(removeBannerException) {
window.debug.error(removeBannerException.toString());
}
}
};
/*
* Remove all pending banner messages from the banner area. Will not remove messages that are already displayed.
*/
Notification.prototype.clearBannerMessage = function() {
PalmSystem.clearBannerMessage();
};
/*
* This function vibrates the device
* @param {number} duration The duration in ms to vibrate for.
* @param {number} intensity The intensity of the vibration
*/
Notification.prototype.vibrate = function(duration, intensity) {
//the intensity for palm is inverted; 0=high intensity, 100=low intensity
//this is opposite from our api, so we invert
if (isNaN(intensity) || intensity > 100 || intensity <= 0)
intensity = 0;
else
intensity = 100 - intensity;
// if the app id does not have the namespace "com.palm.", an error will be thrown here
//this.vibhandle = new Mojo.Service.Request("palm://com.palm.vibrate", {
this.vibhandle = navigator.service.Request("palm://com.palm.vibrate", {
method: 'vibrate',
parameters: {
'period': intensity,
'duration': duration
}
},
false);
};
/*
* Plays the specified sound
* @param {String} soundClass class of the sound; supported classes are: "ringtones", "alerts", "alarm", "calendar", "notification"
* @param {String} soundFile partial or full path to the sound file
* @param {String} soundDurationMs of sound in ms
*/
Notification.prototype.beep = function(soundClass, soundFile, soundDurationMs) {
PalmSystem.playSoundNotification(soundClass, soundFile, soundDurationMs);
};
/*
* displays a notification
* @param {String} message
* @param {Object} response
* @param {String} icon
*/
Notification.prototype.alert = function(message, response, icon) {
var response = response || {
banner: true
};
navigator.notification.showBanner(message, response, icon);
};
if (typeof navigator.notification == 'undefined') {
navigator.notification = new Notification();
alert = navigator.notification.alert;
}
/*
* This class provides access to the device orientation.
* @constructor
*/
function Orientation() {
this.started = false;
};
/*
* Manually sets the orientation of the application window.
* 'up', 'down', 'left' or 'right' used to specify fixed window orientation
* 'free' WebOS will change the window orientation to match the device orientation
* @param {String} orientation
* Example:
* navigator.orientation.setOrientation('up');
*/
Orientation.prototype.setOrientation = function(orientation) {
PalmSystem.setWindowOrientation(orientation);
};
/*
* Returns the current window orientation
*/
Orientation.prototype.getCurrentOrientation = function() {
return PalmSystem.windowOrientation;
};
/*
* Starts the native orientationchange event listener.
*/
Orientation.prototype.start = function (successCallback) {
var that = this;
// This subscribes the callback once for the successCallback function
that.callback = function (e) {
document.removeEventListener("orientationChanged", that.callback);
successCallback(e.orientation);
}
document.addEventListener("orientationChanged", that.callback);
// This subscribes setOrientation to be constantly updating the currentOrientation property
document.addEventListener("orientationchange", function(event) {
var orient = null;
switch (event.position) {
case 0: orient = DisplayOrientation.FACE_UP; break;
case 1: orient = DisplayOrientation.FACE_DOWN; break;
case 2: orient = DisplayOrientation.PORTRAIT; break;
case 3: orient = DisplayOrientation.REVERSE_PORTRAIT; break;
case 4: orient = DisplayOrientation.LANDSCAPE_RIGHT_UP; break;
case 5: orient = DisplayOrientation.LANDSCAPE_LEFT_UP; break;
default: return; //orientationchange event seems to get thrown sometimes with a null event position
}
that.setOrientation(orient);
});
this.started = true;
};
/*
* Asynchronously aquires the orientation repeatedly at a given interval.
* @param {Function} successCallback The function to call each time the orientation
* data is available.
* @param {Function} errorCallback The function to call when there is an error
* getting the orientation data.
*/
Orientation.prototype.watchOrientation = function(successCallback, errorCallback, options) {
// Invoke the appropriate callback with a new Position object every time the implementation
// determines that the position of the hosting device has changed.
this.getCurrentOrientation(successCallback, errorCallback);
var interval = 1000;
if (options && !isNaN(options.interval))
interval = options.interval;
var that = this;
return setInterval(function() {
that.getCurrentOrientation(successCallback, errorCallback);
}, interval);
};
/*
* Clears the specified orientation watch.
* @param {String} watchId The ID of the watch returned from #watchOrientation.
*/
Orientation.prototype.clearWatch = function(watchId) {
clearInterval(watchId);
};
/*
* This class encapsulates the possible orientation values.
* @constructor
*/
function DisplayOrientation() {
this.code = null;
this.message = "";
};
DisplayOrientation.PORTRAIT = 0;
DisplayOrientation.REVERSE_PORTRAIT = 1;
DisplayOrientation.LANDSCAPE_LEFT_UP = 2;
DisplayOrientation.LANDSCAPE_RIGHT_UP = 3;
DisplayOrientation.FACE_UP = 4;
DisplayOrientation.FACE_DOWN = 5;
if (typeof navigator.orientation == "undefined") navigator.orientation = new Orientation();
function Position(coords) {
this.coords = coords;
this.timestamp = new Date().getTime();
};
function Coordinates(lat, lng, alt, acc, head, vel, altacc) {
/*
* The latitude of the position.
*/
this.latitude = lat;
/*
* The longitude of the position,
*/
this.longitude = lng;
/*
* The accuracy of the position.
*/
this.accuracy = acc;
/*
* The altitude of the position.
*/
this.altitude = alt;
/*
* The direction the device is moving at the position.
*/
this.heading = head;
/*
* The velocity with which the device is moving at the position.
*/
this.speed = vel;
/*
* The altitude accuracy of the position.
*/
this.altitudeAccuracy = (typeof(altacc) != 'undefined') ? altacc : null;
};
/*
* This class specifies the options for requesting position data.
* @constructor
*/
function PositionOptions() {
/*
* Specifies the desired position accuracy.
*/
this.enableHighAccuracy = true;
/*
* The timeout after which if position data cannot be obtained the errorCallback
* is called.
*/
this.timeout = 10000;
};
/*
* This class contains information about any GSP errors.
* @constructor
*/
function PositionError() {
this.code = null;
this.message = "";
};
PositionError.UNKNOWN_ERROR = 0;
PositionError.PERMISSION_DENIED = 1;
PositionError.POSITION_UNAVAILABLE = 2;
PositionError.TIMEOUT = 3;
function Service() {
};
Service.prototype.Request = function (uri, params) {
var req = new PalmServiceBridge();
var url = uri + "/" + (params.method || "");
req.url = url;
this.req = req;
this.url = url;
this.params = params || {};
this.call(params);
return this;
};
Service.prototype.call = function(params) {
var onsuccess = null;
var onfailure = null;
var oncomplete = null;
if (typeof params.onSuccess === 'function')
onsuccess = params.onSuccess;
if (typeof params.onFailure === 'function')
onerror = params.onFailure;
if (typeof params.onComplete === 'function')
oncomplete = params.onComplete;
this.req.onservicecallback = callback;
function callback(msg) {
var response = JSON.parse(msg);
if ((response.errorCode) && onfailure)
onfailure(response);
else if (onsuccess)
onsuccess(response);
if (oncomplete)
oncomplete(response);
}
this.data = (typeof params.parameters === 'object') ? JSON.stringify(params.parameters) : '{}';
this.req.call(this.url, this.data);
}
if (typeof navigator.service == "undefined") navigator.service = new Service();
/*
* This class provides access to the device SMS functionality.
* @constructor
*/
function Sms() {
};
/*
* Sends an SMS message.
* @param {Integer} number The phone number to send the message to.
* @param {String} message The contents of the SMS message to send.
* @param {Function} successCallback The function to call when the SMS message is sent.
* @param {Function} errorCallback The function to call when there is an error sending the SMS message.
* @param {PositionOptions} options The options for accessing the GPS location such as timeout and accuracy.
*/
Sms.prototype.send = function(number, message, successCallback, errorCallback, options) {
try {
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'launch',
parameters: {
id: "com.palm.app.messaging",
params: {
composeAddress: number,
messageText: message
}
}
});
successCallback();
} catch(ex) {
errorCallback({
name: "SMSerror",
message: ex.name + ": " + ex.message
});
}
};
if (typeof navigator.sms == "undefined") navigator.sms = new Sms();
/*
* This class provides access to the telephony features of the device.
* @constructor
*/
function Telephony() {
this.number = "";
};
/*
* Calls the specifed number.
* @param {Integer} number The number to be called.
*/
Telephony.prototype.send = function(number) {
this.number = number;
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'open',
parameters: {
target: "tel://" + number
}
});
};
if (typeof navigator.telephony == "undefined") navigator.telephony = new Telephony();
function Window() {
};
/*
* This is a thin wrapper for 'window.open()' which optionally sets document contents to 'html', and calls 'PalmSystem.stageReady()'
* on your new card. Note that this new card will not come with your framework (if any) or anything for that matter.
* @param {String} url
* @param {String} html
* Example:
* navigator.window.newCard('about:blank', '<html><body>Hello again!</body></html>');
*/
Window.prototype.newCard = function(url, html) {
var win = window.open(url || "");
if (html)
win.document.write(html);
win.PalmSystem.stageReady();
};
/*
* Enable or disable full screen display (full screen removes the app menu bar and the rounded corners of the screen).
* @param {Boolean} state
* Example:
* navigator.window.setFullScreen(true);
*/
Window.prototype.setFullScreen = function(state) {
// valid state values are: true or false
PalmSystem.enableFullScreenMode(state);
};
/*
* used to set the window properties of the WebOS app
* @param {Object} props
* Example:
* private method used by other member functions - ideally we shouldn't call this method
*/
Window.prototype.setWindowProperties = function(props) {
if (typeof props === 'object')
navigator.windowProperties = props;
PalmSystem.setWindowProperties(props || this.windowProperties);
};
/*
* Enable or disable screen timeout. When enabled, the device screen will not dim. This is useful for navigation, clocks or other "dock" apps.
* @param {Boolean} state
* Example:
* navigator.window.blockScreenTimeout(true);
*/
Window.prototype.blockScreenTimeout = function(state) {
navigator.windowProperties.blockScreenTimeout = state;
this.setWindowProperties();
};
/*
* Sets the lightbar to be a little dimmer for screen locked notifications.
* @param {Boolean} state
* Example:
* navigator.window.setSubtleLightbar(true);
*/
Window.prototype.setSubtleLightbar = function(state) {
navigator.windowProperties.setSubtleLightbar = state;
this.setWindowProperties();
};
if (typeof navigator.window == 'undefined') navigator.window = new Window();
/*
* Object for storing WebOS window properties
*/
function WindowProperties() {
blockScreenTimeout = false;
setSubtleLightbar = false;
fastAccelerometer = false;
};
if (typeof navigator.windowProperties == 'undefined') navigator.windowProperties = new WindowProperties();(function(window) {
/**
* Do not use thumbs.js on touch-enabled devices
*
* Thanks to Jesse MacFadyen (purplecabbage):
* https://gist.github.com/850593#gistcomment-22484
*/
try {
document.createEvent('TouchEvent');
return;
}
catch(e) {
}
/**
* Map touch events to mouse events
*/
var eventMap = {
'mousedown': 'touchstart',
'mouseup': 'touchend',
'mousemove': 'touchmove'
};
/**
* Fire touch events
*
* Monitor mouse events and fire a touch event on the
* object broadcasting the mouse event. This approach
* likely has poorer performance than hijacking addEventListener
* but it is a little more browser friendly.
*/
window.addEventListener('load', function() {
for (var key in eventMap) {
document.body.addEventListener(key, function(e) {
// Supports:
// - addEventListener
// - setAttribute
var event = createTouchEvent(eventMap[e.type], e);
e.target.dispatchEvent(event);
// Supports:
// - element.ontouchstart
var fn = e.target['on' + eventMap[e.type]];
if (typeof fn === 'function') fn(e);
}, false);
}
}, false);
/**
* Utility function to create a touch event.
*
* @param name {String} of the event
* @return event {Object}
*/
var createTouchEvent = function(name, e) {
var event = document.createEvent('MouseEvents');
event.initMouseEvent(
name,
e.bubbles,
e.cancelable,
e.view,
e.detail,
e.screenX,
e.screenY,
e.clientX,
e.clientY,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
e.button,
e.relatedTarget
);
return event;
};
})(window);