You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by lo...@apache.org on 2013/05/07 17:16:20 UTC
[04/32] js commit: [BlackBerry10] Incorporate webworks.js logic into
cordova.blackberry10.js
[BlackBerry10] Incorporate webworks.js logic into cordova.blackberry10.js
Project: http://git-wip-us.apache.org/repos/asf/cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-js/commit/28084c53
Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/28084c53
Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/28084c53
Branch: refs/heads/future
Commit: 28084c5348374f3c94787fae4807b69672758bd6
Parents: 615aea4
Author: Rosa Tse <rt...@rim.com>
Authored: Wed Feb 20 09:21:18 2013 -0500
Committer: Bryan Higgins <bh...@blackberry.com>
Committed: Fri May 3 09:49:10 2013 -0400
----------------------------------------------------------------------
lib/blackberry10/platform.js | 2 +-
lib/blackberry10/plugin/blackberry10/builder.js | 74 ++
lib/blackberry10/plugin/blackberry10/event.js | 102 +++
lib/blackberry10/plugin/blackberry10/exception.js | 74 ++
lib/blackberry10/plugin/blackberry10/utils.js | 556 ++++++++++++++++
lib/scripts/bootstrap-blackberry10.js | 199 ++++++-
lib/scripts/require.js | 289 +++++++--
test/blackberry10/test.builder.js | 121 ++++
test/blackberry10/test.event.js | 188 ++++++
9 files changed, 1533 insertions(+), 72 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/blackberry10/platform.js
----------------------------------------------------------------------
diff --git a/lib/blackberry10/platform.js b/lib/blackberry10/platform.js
index af6d65e..7b6bb2a 100644
--- a/lib/blackberry10/platform.js
+++ b/lib/blackberry10/platform.js
@@ -31,7 +31,7 @@ module.exports = {
builder.buildIntoAndMerge(platform.merges, window);
modulemapper.loadMatchingModules(/cordova.*\/symbols$/);
- modulemapper.loadMatchingModules(new RegExp('cordova/.*' + this.runtime() + '/.*bbsymbols$'));
+ modulemapper.loadMatchingModules(new RegExp('cordova/blackberry10/.*bbsymbols$'));
modulemapper.mapModules(window);
platform.initialize();
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/blackberry10/plugin/blackberry10/builder.js
----------------------------------------------------------------------
diff --git a/lib/blackberry10/plugin/blackberry10/builder.js b/lib/blackberry10/plugin/blackberry10/builder.js
new file mode 100644
index 0000000..9271c58
--- /dev/null
+++ b/lib/blackberry10/plugin/blackberry10/builder.js
@@ -0,0 +1,74 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var utils = require("cordova/plugin/blackberry10/utils");
+
+function buildNamespace(currentNamespace, namespaceParts, featureProperties) {
+ var featureId,
+ nextPart;
+
+ if (namespaceParts.length === 1) {
+ //base case, feature properties go here
+ featureId = namespaceParts[0];
+ if (currentNamespace[featureId] === undefined) {
+ currentNamespace[featureId] = {};
+ }
+
+ currentNamespace = utils.mixin(featureProperties, currentNamespace[featureId]);
+ return currentNamespace;
+ }
+ else {
+ nextPart = namespaceParts.shift();
+ if (currentNamespace[nextPart] === undefined) {
+ currentNamespace[nextPart] = {};
+ }
+
+ return buildNamespace(currentNamespace[nextPart], namespaceParts, featureProperties);
+ }
+}
+
+function include(parent, featureIdList) {
+ var featureId,
+ featureProperties,
+ localUrl,
+ i;
+
+ for (i = 0; i < featureIdList.length; i++) {
+ featureId = featureIdList[i];
+
+ localUrl = "local://ext/" + featureId + "/client.js";
+ featureProperties = utils.loadModule(localUrl);
+
+ buildNamespace(parent, featureId.split("."), featureProperties);
+ }
+}
+
+var _self = {
+ build: function (featureIdList) {
+ return {
+ into: function (target) {
+ include(target, featureIdList);
+ }
+ };
+ }
+};
+
+module.exports = _self;
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/blackberry10/plugin/blackberry10/event.js
----------------------------------------------------------------------
diff --git a/lib/blackberry10/plugin/blackberry10/event.js b/lib/blackberry10/plugin/blackberry10/event.js
new file mode 100644
index 0000000..9e91fe4
--- /dev/null
+++ b/lib/blackberry10/plugin/blackberry10/event.js
@@ -0,0 +1,102 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var _handlers = {};
+
+function _add(featureId, name, cb, success, fail, once) {
+ var handler;
+ if (featureId && name && typeof cb === "function") {
+ handler = {
+ func: cb,
+ once: !!once
+ };
+ //If this is the first time we are adding a cb
+ if (!_handlers.hasOwnProperty(name)) {
+ _handlers[name] = [handler];
+ //Once listeners should not be registered with the context because there is no underlying event to call them
+ //HOWEVER the webview needs to register itself with lib/event.
+ if (once) {
+ window.webworks.exec(success, fail, "event", "once", {"eventName": name});
+ } else {
+ window.webworks.exec(success, fail, featureId, "add", {"eventName": name});
+ }
+ } else if (!_handlers[name].some(function (element, index, array) {
+ return element.func === cb;
+ })) {
+ //Only add unique callbacks
+ _handlers[name].push(handler);
+ }
+ }
+}
+
+module.exports = {
+ add: function (featureId, name, cb, success, fail) {
+ _add(featureId, name, cb, success, fail, false);
+ },
+
+ once: function (featureId, name, cb, success, fail) {
+ _add(featureId, name, cb, success, fail, true);
+ },
+
+ isOn: function (name) {
+ return !!_handlers[name];
+ },
+
+ remove: function (featureId, name, cb, success, fail) {
+ if (featureId && name && typeof cb === "function") {
+ if (_handlers.hasOwnProperty(name)) {
+ _handlers[name] = _handlers[name].filter(function (element, index, array) {
+ return element.func !== cb || element.once;
+ });
+
+ if (_handlers[name].length === 0) {
+ delete _handlers[name];
+ window.webworks.exec(success, fail, featureId, "remove", {"eventName": name});
+ }
+ }
+ }
+ },
+
+ trigger: function (name, args) {
+ var parsedArgs;
+ if (_handlers.hasOwnProperty(name)) {
+ if (args && args !== "undefined") {
+ parsedArgs = JSON.parse(decodeURIComponent(unescape(args)));
+ }
+ //Call the handlers
+ _handlers[name].forEach(function (handler) {
+ if (handler) {
+ //args should be an array of arguments
+ handler.func.apply(undefined, parsedArgs);
+ }
+ });
+ //Remove the once listeners
+ _handlers[name] = _handlers[name].filter(function (handler) {
+ return !handler.once;
+ });
+ //Clean up the array if it is empty
+ if (_handlers[name].length === 0) {
+ delete _handlers[name];
+ //No need to call remove since this would only be for callbacks
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/blackberry10/plugin/blackberry10/exception.js
----------------------------------------------------------------------
diff --git a/lib/blackberry10/plugin/blackberry10/exception.js b/lib/blackberry10/plugin/blackberry10/exception.js
new file mode 100644
index 0000000..515d46d
--- /dev/null
+++ b/lib/blackberry10/plugin/blackberry10/exception.js
@@ -0,0 +1,74 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+module.exports = {
+
+ types: {
+ Application: "Application",
+ ArgumentLength: "ArgumentLength",
+ ArgumentType: "ArgumentType",
+ Argument: "Argument",
+ NotificationType: "NotificationType",
+ NotificationStateType: "NotificationStateType",
+ DomObjectNotFound: "DomObjectNotFound",
+ MethodNotImplemented: "MethodNotImplemented",
+ InvalidState: "InvalidState",
+ ApplicationState: "ApplicationState"
+ },
+
+ handle: function handle(exception, reThrow) {
+ reThrow = reThrow || false;
+
+ var eMsg = exception.message || "exception caught!",
+ msg = eMsg + "\n\n" + (exception.stack || "*no stack provided*") + "\n\n";
+
+ console.error(msg);
+
+ if (reThrow) {
+ throw exception;
+ }
+ },
+
+ raise: function raise(exceptionType, message, customExceptionObject) {
+ var obj = customExceptionObject || {
+ type: "",
+ message: "",
+
+ toString: function () {
+ var result = this.name + ': "' + this.message + '"';
+
+ if (this.stack) {
+ result += "\n" + this.stack;
+ }
+ return result;
+ }
+ };
+
+ message = message || "";
+
+ obj.name = exceptionType;
+ obj.type = exceptionType;
+ // TODO: include the exception objects original message if exists
+ obj.message = message;
+
+ throw obj;
+ }
+};
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/blackberry10/plugin/blackberry10/utils.js
----------------------------------------------------------------------
diff --git a/lib/blackberry10/plugin/blackberry10/utils.js b/lib/blackberry10/plugin/blackberry10/utils.js
new file mode 100644
index 0000000..3a630da
--- /dev/null
+++ b/lib/blackberry10/plugin/blackberry10/utils.js
@@ -0,0 +1,556 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var self,
+ exception = require('cordova/plugin/blackberry10/exception');
+
+function S4() {
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+}
+
+self = module.exports = {
+ validateNumberOfArguments: function (lowerBound, upperBound, numberOfArguments, customExceptionType, customExceptionMessage, customExceptionObject) {
+
+ customExceptionMessage = customExceptionMessage || "";
+
+ if (arguments.length < 3 || arguments.length > 6) {
+ exception.raise(exception.types.Argument, "Wrong number of arguments when calling: validateNumberOfArguments()");
+ }
+
+ if (isNaN(lowerBound) && isNaN(upperBound) && isNaN(numberOfArguments)) {
+ exception.raise(exception.types.ArgumentType, "(validateNumberOfArguments) Arguments are not numbers");
+ }
+
+ lowerBound = parseInt(lowerBound, 10);
+ upperBound = parseInt(upperBound, 10);
+ numberOfArguments = parseInt(numberOfArguments, 10);
+
+ if (numberOfArguments < lowerBound || numberOfArguments > upperBound) {
+ exception.raise((customExceptionType || exception.types.ArgumentLength), (customExceptionMessage + "\n\nWrong number of arguments"), customExceptionObject);
+ }
+
+ },
+
+ validateArgumentType: function (arg, argType, customExceptionType, customExceptionMessage, customExceptionObject) {
+ var invalidArg = false,
+ msg;
+
+ switch (argType) {
+ case "array":
+ if (!arg instanceof Array) {
+ invalidArg = true;
+ }
+ break;
+ case "date":
+ if (!arg instanceof Date) {
+ invalidArg = true;
+ }
+ break;
+ case "integer":
+ if (typeof arg === "number") {
+ if (arg !== Math.floor(arg)) {
+ invalidArg = true;
+ }
+ }
+ else {
+ invalidArg = true;
+ }
+ break;
+ default:
+ if (typeof arg !== argType) {
+ invalidArg = true;
+ }
+ break;
+ }
+
+ if (invalidArg) {
+ msg = customExceptionMessage + ("\n\nInvalid Argument type. argument: " + arg + " ==> was expected to be of type: " + argType);
+ exception.raise((customExceptionType || exception.types.ArgumentType), msg, customExceptionObject);
+ }
+ },
+
+ validateMultipleArgumentTypes: function (argArray, argTypeArray, customExceptionType, customExceptionMessage, customExceptionObject) {
+ for (var i = 0; i < argArray.length; i++) {
+ this.validateArgumentType(argArray[i], argTypeArray[i], customExceptionType, customExceptionMessage, customExceptionObject);
+ }
+ },
+
+ arrayContains: function (array, obj) {
+ var i = array.length;
+ while (i--) {
+ if (array[i] === obj) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ some: function (obj, predicate, scope) {
+ if (obj instanceof Array) {
+ return obj.some(predicate, scope);
+ }
+ else {
+ var values = self.map(obj, predicate, scope);
+
+ return self.reduce(values, function (some, value) {
+ return value ? value : some;
+ }, false);
+ }
+ },
+
+ count: function (obj) {
+ return self.sum(obj, function (total) {
+ return 1;
+ });
+ },
+
+ sum: function (obj, selector, scope) {
+ var values = self.map(obj, selector, scope);
+ return self.reduce(values, function (total, value) {
+ return total + value;
+ });
+ },
+
+ max: function (obj, selector, scope) {
+ var values = self.map(obj, selector, scope);
+ return self.reduce(values, function (max, value) {
+ return max < value ? value : max;
+ }, Number.MIN_VALUE);
+ },
+
+ min: function (obj, selector, scope) {
+ var values = self.map(obj, selector, scope);
+ return self.reduce(values, function (min, value) {
+ return min > value ? value : min;
+ }, Number.MAX_VALUE);
+ },
+
+ forEach: function (obj, action, scope) {
+ if (obj instanceof Array) {
+ return obj.forEach(action, scope);
+ }
+ else {
+ self.map(obj, action, scope);
+ }
+ },
+
+ filter: function (obj, predicate, scope) {
+ if (obj instanceof Array) {
+ return obj.filter(predicate, scope);
+ }
+ else {
+ var result = [];
+ self.forEach(obj, function (value, index) {
+ if (predicate.apply(scope, [value, index])) {
+ result.push(value);
+ }
+
+ }, scope);
+
+ return result;
+ }
+ },
+
+ reduce: function (obj, func, init, scope) {
+ var i,
+ initial = init === undefined ? 0 : init,
+ result = initial;
+
+
+ if (obj instanceof Array) {
+ return obj.reduce(func, initial);
+ }
+ else if (obj instanceof NamedNodeMap) {
+ for (i = 0; i < obj.length; i++) {
+ result = func.apply(scope, [result, obj[i], i]);
+ }
+ }
+ else {
+ for (i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ result = func.apply(scope, [result, obj[i], i]);
+ }
+ }
+ }
+
+ return result;
+
+ },
+
+ map: function (obj, func, scope) {
+ var i,
+ returnVal = null,
+ result = [];
+
+ if (obj instanceof Array) {
+ return obj.map(func, scope);
+ }
+ else if (obj instanceof NamedNodeMap) {
+ for (i = 0; i < obj.length; i++) {
+ returnVal = func.apply(scope, [obj[i], i]);
+ result.push(returnVal);
+ }
+ }
+ else {
+ for (i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ returnVal = func.apply(scope, [obj[i], i]);
+ result.push(returnVal);
+ }
+ }
+ }
+
+ return result;
+ },
+
+ series: function (tasks, callback) {
+
+ var execute = function () {
+ var args = [],
+ task;
+
+ if (tasks.length) {
+ task = tasks.shift();
+ args = args.concat(task.args).concat(execute);
+ task.func.apply(this, args);
+ }
+ else {
+ callback.func.apply(this, callback.args);
+ }
+ };
+
+ execute();
+ },
+
+ regexSanitize: function (regexString) {
+ return regexString.replace("^", "\\^")
+ .replace("$", "\\$")
+ .replace("(", "\\(")
+ .replace(")", "\\)")
+ .replace("<", "\\<")
+ .replace("[", "\\[")
+ .replace("{", "\\{")
+ .replace(/\\/, "\\\\")
+ .replace("|", "\\|")
+ .replace(">", "\\>")
+ .replace(".", "\\.")
+ .replace("*", "\\*")
+ .replace("+", "\\+")
+ .replace("?", "\\?");
+ },
+
+ find: function (comparison, collection, startInx, endInx, callback) {
+ var results = [],
+ compare = function (s, pattern) {
+
+ if (typeof(s) !== "string" || pattern === null) {
+ return s === pattern;
+ }
+
+ var regex = pattern.replace(/\./g, "\\.")
+ .replace(/\^/g, "\\^")
+ .replace(/\*/g, ".*")
+ .replace(/\\\.\*/g, "\\*");
+
+ regex = "^".concat(regex, "$");
+
+ return !!s.match(new RegExp(regex, "i"));
+ };
+
+ self.forEach(collection, function (c) {
+ var match,
+ fail = false;
+
+ self.forEach(comparison, function (value, key) {
+ if (!fail && value !== undefined) {
+
+ if (compare(c[key], value)) {
+ match = c;
+ }
+ else {
+ fail = true;
+ match = null;
+ }
+ }
+ });
+
+ if (match) {
+ results.push(match);
+ }
+ });
+
+ if (callback) {
+ if (startInx === undefined) {
+ startInx = 0;
+ }
+ if (endInx === undefined) {
+ endInx = results.length;
+ }
+ if (startInx === endInx) {
+ endInx = startInx + 1;
+ }
+
+ callback.apply(null, [results.slice(startInx, endInx)]);
+ }
+ },
+
+ mixin: function (mixin, to) {
+ Object.getOwnPropertyNames(mixin).forEach(function (prop) {
+ if (Object.hasOwnProperty.call(mixin, prop)) {
+ Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(mixin, prop));
+ }
+ });
+ return to;
+ },
+
+ copy: function (obj) {
+ var i,
+ newObj = (obj === null ? false : global.toString.call(obj) === "[object Array]") ? [] : {};
+
+ if (typeof obj === 'number' ||
+ typeof obj === 'string' ||
+ typeof obj === 'boolean' ||
+ obj === null ||
+ obj === undefined) {
+ return obj;
+ }
+
+ if (obj instanceof Date) {
+ return new Date(obj);
+ }
+
+ if (obj instanceof RegExp) {
+ return new RegExp(obj);
+ }
+
+ for (i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ if (obj[i] && typeof obj[i] === "object") {
+ if (obj[i] instanceof Date) {
+ newObj[i] = obj[i];
+ }
+ else {
+ newObj[i] = self.copy(obj[i]);
+ }
+ }
+ else {
+ newObj[i] = obj[i];
+ }
+ }
+ }
+
+ return newObj;
+ },
+
+ startsWith : function (str, substr) {
+ return str.indexOf(substr) === 0;
+ },
+
+ endsWith : function (str, substr) {
+ return str.indexOf(substr, str.length - substr.length) !== -1;
+ },
+
+ parseUri : function (str) {
+ var i, uri = {},
+ key = [ "source", "scheme", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor" ],
+ matcher = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(str);
+
+ for (i = key.length - 1; i >= 0; i--) {
+ uri[key[i]] = matcher[i] || "";
+ }
+
+ return uri;
+ },
+
+ // uri - output from parseUri
+ isAbsoluteURI : function (uri) {
+ if (uri && uri.source) {
+ return uri.relative !== uri.source;
+ }
+
+ return false;
+ },
+
+ fileNameToImageMIME : function (fileName) {
+
+ var extensionsToMIME = {},
+ ext;
+
+ extensionsToMIME.png = 'image/png';
+ extensionsToMIME.jpg = 'image/jpeg';
+ extensionsToMIME.jpe = 'image/jpeg';
+ extensionsToMIME.jpeg = 'image/jpeg';
+ extensionsToMIME.gif = 'image/gif';
+ extensionsToMIME.bmp = 'image/bmp';
+ extensionsToMIME.bm = 'image/bmp';
+ extensionsToMIME.svg = 'image/svg+xml';
+ extensionsToMIME.tif = 'image/tiff';
+ extensionsToMIME.tiff = 'image/tiff';
+
+ ext = fileName.split('.').pop();
+ return extensionsToMIME[ext];
+ },
+
+ isLocalURI : function (uri) {
+ return uri && uri.scheme && "local:///".indexOf(uri.scheme.toLowerCase()) !== -1;
+ },
+
+ isFileURI : function (uri) {
+ return uri && uri.scheme && "file://".indexOf(uri.scheme.toLowerCase()) !== -1;
+ },
+
+ isHttpURI : function (uri) {
+ return uri && uri.scheme && "http://".indexOf(uri.scheme.toLowerCase()) !== -1;
+ },
+
+ isHttpsURI : function (uri) {
+ return uri && uri.scheme && "https://".indexOf(uri.scheme.toLowerCase()) !== -1;
+ },
+
+ // Checks if the specified uri starts with 'data:'
+ isDataURI : function (uri) {
+ return uri && uri.scheme && "data:".indexOf(uri.scheme.toLowerCase()) !== -1;
+ },
+
+ performExec : function (featureId, property, args) {
+ var result;
+
+ window.webworks.exec(function (data, response) {
+ result = data;
+ }, function (data, response) {
+ throw data;
+ }, featureId, property, args, true);
+
+ return result;
+ },
+
+ inNode : function () {
+ return !!require.resolve;
+ },
+
+ requireWebview : function () {
+ return require("./webview");
+ },
+ convertDataToBinary : function (data, dataEncoding) {
+ var rawData,
+ uint8Array,
+ i;
+
+ if (data) {
+ if (dataEncoding.toLowerCase() === "base64") {
+ rawData = window.atob(data);
+ }
+ else {
+ rawData = data;
+ }
+
+ uint8Array = new Uint8Array(new ArrayBuffer(rawData.length));
+
+ for (i = 0; i < uint8Array.length; i++) {
+ uint8Array[i] = rawData.charCodeAt(i);
+ }
+
+ return uint8Array.buffer;
+ }
+ },
+ getBlobWithArrayBufferAsData : function (data, dataEncoding) {
+ var rawData,
+ blobBuilderObj = new window.WebKitBlobBuilder();
+ rawData = this.convertDataToBinary(data, dataEncoding);
+ blobBuilderObj.append(rawData);
+
+ return blobBuilderObj.getBlob("arraybuffer");
+ },
+ loadModule: function (module) {
+ return require(module);
+ },
+ loadExtensionModule: function (extBasename, path) {
+ var ext = require("./manifest")[extBasename];
+
+ if (ext) {
+ return require("../ext/" + ext.namespace + "/" + path);
+ } else {
+ return null;
+ }
+ },
+ hasPermission: function (config, permission) {
+ if (config && config.permissions && config.permissions.length) {
+ return config.permissions.indexOf(permission) >= 0;
+ }
+
+ return false;
+ },
+ guid: function () {
+ return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+ },
+ getURIPrefix: function () {
+ return "http://localhost:8472/";
+ },
+ translatePath: function (path) {
+ if (path.indexOf("local:///") === 0) {
+ var sourceDir = window.qnx.webplatform.getApplication().getEnv("HOME"); //leading slashes need to be removed
+ path = "file:///" + sourceDir.replace(/^\/*/, '') + "/../app/native/" + path.replace(/local:\/\/\//, '');
+ }
+ return path;
+ },
+ invokeInBrowser: function (url) {
+ var request = {
+ uri: url,
+ target: "sys.browser"
+ };
+ window.qnx.webplatform.getApplication().invocation.invoke(request);
+ },
+ isPersonal: function () {
+ return window.qnx.webplatform.getApplication().getEnv("PERIMETER") === "personal";
+ },
+ deepclone: function (obj) {
+ var newObj = obj instanceof Array ? [] : {},
+ key;
+
+ if (typeof obj === 'number' ||
+ typeof obj === 'string' ||
+ typeof obj === 'boolean' ||
+ obj === null ||
+ obj === undefined) {
+ return obj;
+ }
+
+ if (obj instanceof Date) {
+ return new Date(obj);
+ }
+
+ if (obj instanceof RegExp) {
+ return new RegExp(obj);
+ }
+
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ if (obj[key] && typeof obj[key] === "object") {
+ newObj[key] = self.deepclone(obj[key]);
+ } else {
+ newObj[key] = obj[key];
+ }
+ }
+ }
+
+ return newObj;
+ }
+};
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/scripts/bootstrap-blackberry10.js
----------------------------------------------------------------------
diff --git a/lib/scripts/bootstrap-blackberry10.js b/lib/scripts/bootstrap-blackberry10.js
index 65115fd..1a33845 100644
--- a/lib/scripts/bootstrap-blackberry10.js
+++ b/lib/scripts/bootstrap-blackberry10.js
@@ -19,16 +19,193 @@
*
*/
-document.addEventListener("DOMContentLoaded", function () {
- var wwjs = document.createElement("script");
- wwjs.src = "local:///chrome/webworks.js";
- wwjs.onload = function () {
- document.addEventListener("webworksready", function () {
- require('cordova/channel').onNativeReady.fire();
- });
- };
- wwjs.onerror = function () {
- alert('there was a problem loading webworks.js');
+(function () {
+ var _d = document.addEventListener,
+ _webworksReady = false,
+ _alreadyFired = false,
+ _listenerRegistered = false;
+
+ //Only fire the webworks event when both webworks is ready and a listener is registered
+ function fireWebworksReadyEvent() {
+ if (_listenerRegistered && _webworksReady && !_alreadyFired) {
+ _alreadyFired = true;
+ var evt = document.createEvent("Events");
+ evt.initEvent("webworksready", true, true);
+ document.dispatchEvent(evt);
+ }
+ }
+
+ //Trapping when users add listeners to the webworks ready event
+ //This way we can make sure not to fire the event before there is a listener
+ document.addEventListener = function (event, callback, capture) {
+ _d.call(document, event, callback, capture);
+ if (event.toLowerCase() === "webworksready") {
+ _listenerRegistered = true;
+ fireWebworksReadyEvent();
+ }
};
- document.head.appendChild(wwjs);
+
+ function createWebworksReady() {
+ function RemoteFunctionCall(functionUri) {
+ var params = {};
+
+ function composeUri() {
+ return require("cordova/plugin/blackberry10/utils").getURIPrefix() + functionUri;
+ }
+
+ function createXhrRequest(uri, isAsync) {
+ var request = new XMLHttpRequest();
+
+ request.open("POST", uri, isAsync);
+ request.setRequestHeader("Content-Type", "application/json");
+
+ return request;
+ }
+
+ this.addParam = function (name, value) {
+ params[name] = encodeURIComponent(JSON.stringify(value));
+ };
+
+ this.makeSyncCall = function (success, error) {
+ var requestUri = composeUri(),
+ request = createXhrRequest(requestUri, false),
+ response,
+ errored,
+ cb,
+ data;
+
+ request.send(JSON.stringify(params));
+
+ response = JSON.parse(decodeURIComponent(request.responseText) || "null");
+ errored = response.code < 0;
+ cb = errored ? error : success;
+ data = errored ? response.msg : response.data;
+
+ if (cb) {
+ cb(data, response);
+ }
+ else if (errored) {
+ throw data;
+ }
+
+ return data;
+ };
+
+ this.makeAsyncCall = function (success, error) {
+ var requestUri = composeUri(),
+ request = createXhrRequest(requestUri, true);
+
+ request.onreadystatechange = function () {
+ if (request.readyState === 4 && request.status === 200) {
+ var response = JSON.parse(decodeURIComponent(request.responseText) || "null"),
+ cb = response.code < 0 ? error : success,
+ data = response.code < 0 ? response.msg : response.data;
+
+ return cb && cb(data, response);
+ }
+ };
+
+ request.send(JSON.stringify(params));
+ };
+ }
+
+ var builder,
+ request,
+ resp,
+ execFunc;
+
+ //For users who wish to have a single source project across BB7 -> PB -> BB10 they will need to use webworks.js
+ //To aid in this, we will fire the webworksready event on these platforms as well
+ //If blackberry object already exists then we are in an older version of webworks
+ if (window.blackberry) {
+ _webworksReady = true;
+ fireWebworksReadyEvent();
+ return;
+ }
+
+ // Build out the blackberry namespace based on the APIs desired in the config.xml
+ builder = require('cordova/plugin/blackberry10/builder');
+
+ request = new XMLHttpRequest();
+ request.open("GET", "http://localhost:8472/extensions/get", true);
+
+ request.onreadystatechange = function () {
+ if (request.readyState === 4) {
+ resp = JSON.parse(decodeURIComponent(request.responseText));
+
+ if (request.status === 200) {
+ builder.build(resp.data).into(window);
+ //At this point all of the APIs should be built into the window object
+ //Fire the webworks ready event
+ _webworksReady = true;
+ fireWebworksReadyEvent();
+ }
+ }
+ };
+ request.send(null);
+
+ execFunc = function (success, fail, service, action, args, sync) {
+ var uri = service + "/" + action,
+ request = new RemoteFunctionCall(uri),
+ name;
+
+ for (name in args) {
+ if (Object.hasOwnProperty.call(args, name)) {
+ request.addParam(name, args[name]);
+ }
+ }
+
+ request[sync ? "makeSyncCall" : "makeAsyncCall"](success, fail);
+ };
+
+ window.webworks = {
+ exec: execFunc,
+ execSync: function (service, action, args) {
+ var result;
+
+ execFunc(function (data, response) {
+ result = data;
+ }, function (data, response) {
+ throw data;
+ }, service, action, args, true);
+
+ return result;
+ },
+ execAsync: function (service, action, args) {
+ var result;
+
+ execFunc(function (data, response) {
+ result = data;
+ }, function (data, response) {
+ throw data;
+ }, service, action, args, false);
+
+ return result;
+ },
+ successCallback: function (id, args) {
+ //HACK: this will live later
+ throw "not implemented";
+ },
+ errorCallback: function (id, args) {
+ //HACK: this will live later
+ throw "not implemented";
+ },
+ defineReadOnlyField: function (obj, field, value) {
+ Object.defineProperty(obj, field, {
+ "value": value,
+ "writable": false
+ });
+ },
+ event: require("cordova/plugin/blackberry10/event")
+ };
+ }
+
+ // Let's create the webworks namespace
+ createWebworksReady();
+}());
+
+document.addEventListener("DOMContentLoaded", function () {
+ document.addEventListener("webworksready", function () {
+ require('cordova/channel').onNativeReady.fire();
+ });
});
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/lib/scripts/require.js
----------------------------------------------------------------------
diff --git a/lib/scripts/require.js b/lib/scripts/require.js
index 5dbc905..35f160e 100644
--- a/lib/scripts/require.js
+++ b/lib/scripts/require.js
@@ -1,82 +1,251 @@
/*
+ * Copyright 2012 Research In Motion Limited.
*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
+ * 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
+ * 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.
- *
-*/
+ * 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.
+ */
-var require,
- define;
+var define,
+ require;
(function () {
- var modules = {};
- // Stack of moduleIds currently being built.
- var requireStack = [];
- // Map of module ID -> index into requireStack of modules currently being built.
- var inProgressModules = {};
-
- function build(module) {
- var factory = module.factory;
- module.exports = {};
- delete module.factory;
- factory(require, module.exports, module);
+ var unpreparedModules = {},
+ readyModules = {},
+ ACCEPTABLE_EXTENSIONS = [".js", ".json"],
+ DEFAULT_EXTENSION = ".js";
+
+ function hasValidExtension(moduleName) {
+ return ACCEPTABLE_EXTENSIONS.some(function (element, index, array) {
+ return moduleName.match("\\" + element + "$");
+ });
+ }
+
+
+ function normalizeName(originalName, baseName) {
+ var nameParts,
+ name = originalName.slice(0);
+ //remove ^local:// (if it exists) and .js$
+ //This will not work for local:// without a trailing js
+ name = name.replace(/(?:^local:\/\/)/, "");
+ if (name.charAt(0) === '.' && baseName) {
+ //Split the baseName and remove the final part (the module name)
+ nameParts = baseName.split('/');
+ nameParts.pop();
+ nameParts = nameParts.concat(name.split('/'));
+
+ name = nameParts.reduce(function (previous, current, index, array) {
+ var returnValue,
+ slashIndex;
+
+ //If previous is a dot, ignore it
+ //If previous is ever just .. we're screwed anyway
+ if (previous !== '.') {
+ returnValue = previous;
+ }
+
+ //If we have a .. then remove a chunk of previous
+ if (current === "..") {
+ slashIndex = previous.lastIndexOf('/');
+ //If there's no slash we're either screwed or we remove the final token
+ if (slashIndex !== -1) {
+ returnValue = previous.slice(0, previous.lastIndexOf('/'));
+ } else {
+ returnValue = "";
+ }
+ } else if (current !== '.') {
+ //Otherwise simply append anything not a .
+ //Only append a slash if we're not empty
+ if (returnValue.length) {
+ returnValue += "/";
+ }
+ returnValue += current;
+ }
+
+ return returnValue;
+ });
+
+ }
+
+ //If there is no acceptable extension tack on a .js
+ if (!hasValidExtension(name)) {
+ name = name + DEFAULT_EXTENSION;
+ }
+
+ return name;
+ }
+
+ function buildModule(name, dependencies, factory) {
+ var module = {exports: {}},
+ localRequire = function (moduleName) {
+ return require(moduleName, name);
+ },
+ args = [];
+ localRequire.toUrl = function (moduleName, baseName) {
+ return require.toUrl(moduleName, baseName || name);
+ };
+ dependencies.forEach(function (dependency) {
+ if (dependency === 'require') {
+ args.push(localRequire);
+ } else if (dependency === 'exports') {
+ args.push(module.exports);
+ } else if (dependency === 'module') {
+ args.push(module);
+ } else {
+ //This is because jshint cannot handle out of order functions
+ /*global loadModule:false */
+ args.push(loadModule(dependency));
+ /*global loadModule:true */
+ }
+ });
+
+ //No need to process dependencies, webworks only has require, exports, module
+ factory.apply(this, args);
+
+ //For full AMD we would need logic to also check the return value
return module.exports;
+
}
- require = function (id) {
- if (!modules[id]) {
- throw "module " + id + " not found";
- } else if (id in inProgressModules) {
- var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
- throw "Cycle in require graph: " + cycle;
+ function getDefineString(moduleName, body) {
+ var evalString = 'define("' + moduleName + '", function (require, exports, module) {',
+ isJson = /\.json$/.test(moduleName);
+
+ evalString += isJson ? ' module.exports = ' : '';
+ evalString += body.replace(/^\s+|\s+$/g, '');
+ evalString += isJson ? ' ;' : '';
+ evalString += '});';
+
+ return evalString;
+ }
+
+ function loadModule(name, baseName) {
+ var normalizedName = normalizeName(name, baseName),
+ url,
+ xhr,
+ loadResult;
+ //Always check undefined first, this allows the user to redefine modules
+ //(Not used in WebWorks, although it is used in our unit tests)
+ if (unpreparedModules[normalizedName]) {
+ readyModules[normalizedName] = buildModule(normalizedName, unpreparedModules[normalizedName].dependencies, unpreparedModules[normalizedName].factory);
+ delete unpreparedModules[normalizedName];
}
- if (modules[id].factory) {
- try {
- inProgressModules[id] = requireStack.length;
- requireStack.push(id);
- return build(modules[id]);
- } finally {
- delete inProgressModules[id];
- requireStack.pop();
+
+ //If the module does not exist, load the module from external source
+ //Webworks currently only loads APIs from across bridge
+ if (!readyModules[normalizedName]) {
+ //If the module to be loaded ends in .js then we will define it
+ //Also if baseName exists than we have a local require situation
+ if (hasValidExtension(name) || baseName) {
+ xhr = new XMLHttpRequest();
+ url = name;
+ //If the module to be loaded starts with local:// go over the bridge
+ //Else If the module to be loaded is a relative load it may not have .js extension which is needed
+ if (/^local:\/\//.test(name)) {
+ url = "http://localhost:8472/extensions/load/" + normalizedName.replace(/(?:^ext\/)(.+)(?:\/client.js$)/, "$1");
+
+ xhr.open("GET", url, false);
+ xhr.send(null);
+ try {
+ loadResult = JSON.parse(xhr.responseText);
+
+ loadResult.dependencies.forEach(function (dep) {
+ /*jshint evil:true */
+ eval(getDefineString(dep.moduleName, dep.body));
+ /*jshint evil:false */
+ });
+
+ //Trimming responseText to remove EOF chars
+ /*jshint evil:true */
+ eval(getDefineString(normalizedName, loadResult.client));
+ /*jshint evil:false */
+ } catch (err1) {
+ err1.message += ' in ' + url;
+ throw err1;
+ }
+ } else {
+ if (baseName) {
+ url = normalizedName;
+ }
+
+ xhr.open("GET", url, false);
+ xhr.send(null);
+ try {
+ //Trimming responseText to remove EOF chars
+ /*jshint evil:true */
+ eval(getDefineString(normalizedName, xhr.responseText));
+ /*jshint evil:false */
+ } catch (err) {
+ err.message += ' in ' + url;
+ throw err;
+ }
+ }
+
+ if (unpreparedModules[normalizedName]) {
+ readyModules[normalizedName] = buildModule(normalizedName, unpreparedModules[normalizedName].dependencies, unpreparedModules[normalizedName].factory);
+ delete unpreparedModules[normalizedName];
+ }
+ } else {
+ throw "module " + name + " cannot be found";
}
+
}
- return modules[id].exports;
- };
- define = function (id, factory) {
- if (modules[id]) {
- throw "module " + id + " already defined";
+ return readyModules[normalizedName];
+
+ }
+
+ //Use the AMD signature incase we ever want to change.
+ //For now we will only be using (name, baseName)
+ require = function (dependencies, callback) {
+ if (typeof dependencies === "string") {
+ //dependencies is the module name and callback is the relName
+ //relName is not part of the AMDJS spec, but we use it from localRequire
+ return loadModule(dependencies, callback);
+ } else if (Array.isArray(dependencies) && typeof callback === 'function') {
+ //Call it Asynchronously
+ setTimeout(function () {
+ buildModule(undefined, dependencies, callback);
+ }, 0);
}
+ };
- modules[id] = {
- id: id,
- factory: factory
- };
+ require.toUrl = function (originalName, baseName) {
+ return normalizeName(originalName, baseName);
};
- define.remove = function (id) {
- delete modules[id];
- };
+ //Use the AMD signature incase we ever want to change.
+ //For now webworks will only be using (name, factory) signature.
+ define = function (name, dependencies, factory) {
+ if (typeof name === "string" && typeof dependencies === 'function') {
+ factory = dependencies;
+ dependencies = ['require', 'exports', 'module'];
+ }
- define.moduleMap = modules;
-})();
+ //According to the AMDJS spec we should parse out the require statments
+ //from factory.toString and add those to the list of dependencies
-//Export for use in node
+ //Normalize the name. Remove local:// and .js
+ name = normalizeName(name);
+ unpreparedModules[name] = {
+ dependencies: dependencies,
+ factory: factory
+ };
+ };
+}());
+
+//Export for use in node for unit tests
if (typeof module === "object" && typeof require === "function") {
- module.exports.require = require;
- module.exports.define = define;
+ module.exports = {
+ require: require,
+ define: define
+ };
}
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/test/blackberry10/test.builder.js
----------------------------------------------------------------------
diff --git a/test/blackberry10/test.builder.js b/test/blackberry10/test.builder.js
new file mode 100644
index 0000000..86e5487
--- /dev/null
+++ b/test/blackberry10/test.builder.js
@@ -0,0 +1,121 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+var app,
+ io,
+ filetransfer,
+ system,
+ builder,
+ utils;
+
+describe("blackberry10 builder", function () {
+
+ beforeEach(function () {
+ //Set up mocking, no need to "spyOn" since spies are included in mock
+ window.webworks = {
+ webworks: {
+ execSync: jasmine.createSpy(),
+ defineReadOnlyField: jasmine.createSpy()
+ }
+ };
+
+ app = {
+ "name": "abc",
+ "version": "1.2.3"
+ };
+ io = {
+ "sandbox": false
+ };
+ filetransfer = {
+ "upload": function () {},
+ "download": function () {}
+ };
+ system = {
+ "getCurrentTimezone": function () {}
+ };
+
+ utils = require("cordova/plugin/blackberry10/utils");
+ spyOn(utils, "loadModule").andCallFake(function (module) {
+ if (module.indexOf("app") !== -1) {
+ return app;
+ } else if (module.indexOf("filetransfer") !== -1) {
+ return filetransfer;
+ } else if (module.indexOf("io") !== -1) {
+ return io;
+ } else if (module.indexOf("system") !== -1) {
+ return system;
+ }
+ });
+
+ builder = require("cordova/plugin/blackberry10/builder");
+ });
+
+ afterEach(function () {
+ delete window.webworks;
+ builder = null;
+ });
+
+ it("can build an object with a single member", function () {
+ var featureIds = ['blackberry.app'],
+ target = {};
+
+ builder.build(featureIds).into(target);
+
+ expect(target.blackberry.app).toEqual(app);
+ expect(Object.hasOwnProperty.call(target.blackberry.app, "name")).toBeTruthy();
+ expect(Object.hasOwnProperty.call(target.blackberry.app, "version")).toBeTruthy();
+ });
+
+ it("can build an object with a nested member", function () {
+ var featureIds = ['blackberry.io', 'blackberry.io.filetransfer'],
+ target = {};
+
+ builder.build(featureIds).into(target);
+ expect(target.blackberry.io.filetransfer).toEqual(filetransfer);
+ expect(target.blackberry.io.sandbox).toEqual(io.sandbox);
+ });
+
+ it("can build with feature IDs provided in any order", function () {
+ var featureIds = ['blackberry.io.filetransfer', 'blackberry.io'],
+ target = {};
+
+ builder.build(featureIds).into(target);
+ expect(target.blackberry.io.filetransfer).toEqual(filetransfer);
+ expect(target.blackberry.io.sandbox).toEqual(io.sandbox);
+ });
+
+ it("can build an object with only the nested member", function () {
+ var featureIds = ['blackberry.io.filetransfer'],
+ target = {};
+
+ builder.build(featureIds).into(target);
+ expect(target.blackberry.io.filetransfer).toEqual(filetransfer);
+ });
+
+ it("can build an object with multiple members", function () {
+ var featureIds = ['blackberry.app', 'blackberry.system'],
+ target = {};
+
+ builder.build(featureIds).into(target);
+ expect(target.blackberry.app).toEqual(app);
+ expect(target.blackberry.system).toEqual(system);
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/28084c53/test/blackberry10/test.event.js
----------------------------------------------------------------------
diff --git a/test/blackberry10/test.event.js b/test/blackberry10/test.event.js
new file mode 100644
index 0000000..7d293b8
--- /dev/null
+++ b/test/blackberry10/test.event.js
@@ -0,0 +1,188 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+describe("blackberry10 event", function () {
+ var event = require("cordova/plugin/blackberry10/event"),
+ _window;
+
+ beforeEach(function () {
+ _window = {
+ webworks: {
+ exec: jasmine.createSpy("window.webworks.exec")
+ }
+ };
+ window.webworks = _window.webworks;
+ });
+
+ afterEach(function () {
+ delete window.webworks;
+ });
+
+ describe("add", function () {
+
+ it("it can call webworks.exec action 'add' given valid featureId, eventName and callback", function () {
+ var callback = function () {};
+ event.add("blackberry.system.event", "foo", callback);
+ expect(_window.webworks.exec).toHaveBeenCalledWith(undefined, undefined, "blackberry.system.event", "add", {"eventName": "foo"});
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("it will not call webworks.exec for multiple callbacks", function () {
+ var callback = jasmine.createSpy(),
+ callback2 = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.add("blackberry.system.event", "foo", callback2);
+ expect(_window.webworks.exec).toHaveBeenCalledWith(undefined, undefined, "blackberry.system.event", "add", {"eventName": "foo"});
+ expect(_window.webworks.exec.callCount).toEqual(1);
+ event.remove("blackberry.system.event", "foo", callback);
+ event.remove("blackberry.system.event", "foo", callback2);
+ });
+
+ it("will not register duplicate callbacks if it is the only registered callback for the event", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.add("blackberry.system.event", "foo", callback);
+ event.trigger("foo", '[{"id": 1}]');
+ expect(callback).toHaveBeenCalledWith({"id": 1});
+ expect(callback.callCount).toEqual(1);
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("will not register duplicate callbacks if it is not the only registered callback for the event", function () {
+ var firstCallback = jasmine.createSpy(),
+ secondCallback = jasmine.createSpy(),
+ thirdCallback = jasmine.createSpy();
+
+ event.add("blackberry.system.event", "foo", firstCallback);
+ event.add("blackberry.system.event", "foo", secondCallback);
+ event.add("blackberry.system.event", "foo", thirdCallback);
+ event.add("blackberry.system.event", "foo", firstCallback);
+ event.trigger("foo", null);
+ expect(firstCallback.callCount).toEqual(1);
+ event.remove("blackberry.system.event", "foo", firstCallback);
+ event.remove("blackberry.system.event", "foo", secondCallback);
+ event.remove("blackberry.system.event", "foo", thirdCallback);
+ });
+
+ it("will register two distinct callbacks", function () {
+ var callback = jasmine.createSpy(),
+ callback2 = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.add("blackberry.system.event", "foo", callback2);
+ event.trigger("foo", '[{"id": 1}]');
+ expect(callback).toHaveBeenCalledWith({"id": 1});
+ expect(callback2).toHaveBeenCalledWith({"id": 1});
+ event.remove("blackberry.system.event", "foo", callback);
+ event.remove("blackberry.system.event", "foo", callback2);
+ });
+ });
+
+ describe("once", function () {
+ it("will call webworks.exec action 'once' given valid featureId, eventName and callback", function () {
+ var callback = function () {};
+ event.once("blackberry.system.event", "foo", callback);
+ expect(_window.webworks.exec).toHaveBeenCalledWith(undefined, undefined, "event", "once", {"eventName": "foo"});
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+ });
+
+ describe("remove", function () {
+ it("can call webworks.exec action 'remove' given valid featureId, eventName and callback", function () {
+ var cb = jasmine.createSpy();
+ event.add("blackberry.system.event", "a", cb);
+ event.remove("blackberry.system.event", "a", cb);
+ expect(_window.webworks.exec).toHaveBeenCalledWith(undefined, undefined, "blackberry.system.event", "remove", {"eventName": "a"});
+ });
+ });
+
+ describe("trigger", function () {
+ it("will invoke callback if event has been added", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.trigger("foo", '[{"id": 1}]');
+ expect(callback).toHaveBeenCalledWith({"id": 1});
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("will invoke callback if no args are provided", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.event", "pause", callback);
+ event.trigger("pause");
+ expect(callback).toHaveBeenCalled();
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("will invoke callback with multiple args", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.event", "pause", callback);
+ event.trigger("pause", "[1,2,3,4,5]");
+ expect(callback).toHaveBeenCalledWith(1, 2, 3, 4, 5);
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("will not invoke callback if event has been removed", function () {
+ var cb = jasmine.createSpy();
+ event.add("blackberry.system.event", "c", cb);
+ event.remove("blackberry.system.event", "c", cb);
+ event.trigger("c", {"id": 1});
+ expect(cb).not.toHaveBeenCalled();
+ });
+
+ it("will remove once listeners after they are triggered", function () {
+ var callback = jasmine.createSpy();
+ event.once("blackberry.system.event", "foo", callback);
+ event.trigger("foo", '[{"id": 1}]');
+ event.trigger("foo", '[{"id": 1}]');
+ expect(callback).toHaveBeenCalledWith({"id": 1});
+ expect(callback.callCount).toEqual(1);
+ });
+
+ it("will not remove on listeners after they are triggered", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.trigger("foo", '[{"id": 1}]');
+ event.trigger("foo", '[{"id": 1}]');
+ expect(callback).toHaveBeenCalledWith({"id": 1});
+ expect(callback.callCount).toEqual(2);
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+ });
+
+ describe("isOn", function () {
+ it("returns false with no listeners", function () {
+ expect(event.isOn("foo")).toEqual(false);
+ });
+
+ it("returns true with listeners", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ expect(event.isOn("foo")).toEqual(true);
+ event.remove("blackberry.system.event", "foo", callback);
+ });
+
+ it("Updates properly once listeners are removed", function () {
+ var callback = jasmine.createSpy();
+ event.add("blackberry.system.event", "foo", callback);
+ event.remove("blackberry.system.event", "foo", callback);
+ expect(event.isOn("foo")).toEqual(false);
+ });
+ });
+});