From 230e7262069a6cc98ca4bcd25262133d51c47f30 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 24 Aug 2011 16:21:01 -0400 Subject: [PATCH 001/182] removed wac, vodafone and opera platforms, tweaked some widgetConfig tests --- lib/ripple.js | 2 - lib/ripple/constants.js | 31 +- lib/ripple/devices.js | 6 +- lib/ripple/devices/FWVGA.js | 2 +- lib/ripple/devices/G1.js | 2 +- lib/ripple/devices/HVGA.js | 2 +- lib/ripple/devices/Legend.js | 23 +- lib/ripple/devices/Nexus.js | 2 +- lib/ripple/devices/NokiaN97.js | 23 +- lib/ripple/devices/QVGA.js | 2 +- lib/ripple/devices/SamsungH1.js | 57 -- lib/ripple/devices/SamsungM1.js | 57 -- lib/ripple/devices/Tattoo.js | 17 +- lib/ripple/devices/WQVGA.js | 2 +- lib/ripple/devices/WVGA.js | 2 +- lib/ripple/devices/XperiaX10.js | 70 -- lib/ripple/devices/XperiaX10Mini.js | 70 -- lib/ripple/fileSystem.js | 99 -- .../platform/opera/4.0/defaultStatus.js | 16 - lib/ripple/platform/opera/4.0/moveBy.js | 20 - lib/ripple/platform/opera/4.0/moveTo.js | 20 - lib/ripple/platform/opera/4.0/resizeBy.js | 20 - lib/ripple/platform/opera/4.0/resizeTo.js | 20 - lib/ripple/platform/opera/4.0/spec.js | 56 -- lib/ripple/platform/opera/4.0/spec/config.js | 274 ------ lib/ripple/platform/opera/4.0/spec/events.js | 26 - lib/ripple/platform/opera/4.0/spec/ui.js | 22 - lib/ripple/platform/opera/4.0/status.js | 16 - lib/ripple/platform/opera/4.0/widget.js | 130 --- lib/ripple/platform/spec.js | 5 +- .../platform/vodafone/2.7/DeviceStateInfo.js | 82 -- lib/ripple/platform/vodafone/2.7/spec.js | 140 --- .../platform/vodafone/2.7/spec/config.js | 385 -------- .../platform/vodafone/2.7/spec/device.js | 105 --- .../platform/vodafone/2.7/spec/events.js | 44 - lib/ripple/platform/vodafone/2.7/spec/ui.js | 28 - .../platform/wac/1.0/AccelerometerInfo.js | 31 - lib/ripple/platform/wac/1.0/Account.js | 32 - lib/ripple/platform/wac/1.0/AccountInfo.js | 45 - .../platform/wac/1.0/AddressBookItem.js | 90 -- .../platform/wac/1.0/ApplicationTypes.js | 26 - lib/ripple/platform/wac/1.0/Attachment.js | 20 - lib/ripple/platform/wac/1.0/AudioPlayer.js | 152 --- lib/ripple/platform/wac/1.0/CalendarItem.js | 48 - lib/ripple/platform/wac/1.0/CallRecord.js | 23 - .../platform/wac/1.0/CallRecordTypes.js | 20 - lib/ripple/platform/wac/1.0/Camera.js | 146 --- lib/ripple/platform/wac/1.0/Config.js | 50 - .../wac/1.0/DataNetworkConnectionTypes.js | 34 - .../platform/wac/1.0/DataNetworkInfo.js | 60 -- lib/ripple/platform/wac/1.0/Device.js | 131 --- lib/ripple/platform/wac/1.0/DeviceInfo.js | 79 -- .../platform/wac/1.0/DeviceStateInfo.js | 108 --- .../platform/wac/1.0/EventRecurrenceTypes.js | 24 - lib/ripple/platform/wac/1.0/Exception.js | 28 - lib/ripple/platform/wac/1.0/ExceptionTypes.js | 34 - lib/ripple/platform/wac/1.0/File.js | 23 - lib/ripple/platform/wac/1.0/Message.js | 97 -- .../platform/wac/1.0/MessageFolderTypes.js | 21 - .../platform/wac/1.0/MessageQuantities.js | 20 - lib/ripple/platform/wac/1.0/MessageTypes.js | 20 - lib/ripple/platform/wac/1.0/Messaging.js | 103 --- lib/ripple/platform/wac/1.0/Multimedia.js | 60 -- lib/ripple/platform/wac/1.0/PIM.js | 281 ------ lib/ripple/platform/wac/1.0/PositionInfo.js | 36 - lib/ripple/platform/wac/1.0/PowerInfo.js | 113 --- lib/ripple/platform/wac/1.0/RadioInfo.js | 61 -- .../wac/1.0/RadioSignalSourceTypes.js | 33 - lib/ripple/platform/wac/1.0/Telephony.js | 111 --- lib/ripple/platform/wac/1.0/VideoPlayer.js | 172 ---- lib/ripple/platform/wac/1.0/Widget.js | 129 --- lib/ripple/platform/wac/1.0/WidgetManager.js | 26 - lib/ripple/platform/wac/1.0/spec.js | 147 --- lib/ripple/platform/wac/1.0/spec/config.js | 385 -------- lib/ripple/platform/wac/1.0/spec/device.js | 331 ------- lib/ripple/platform/wac/1.0/spec/events.js | 29 - lib/ripple/platform/wac/1.0/spec/ui.js | 29 - lib/ripple/ui/plugins/audioPlayer.js | 44 - lib/ripple/ui/plugins/fileSystem.js | 37 - lib/ripple/ui/plugins/fileSystem/panel.html | 52 -- lib/ripple/ui/plugins/multimedia.js | 46 - lib/ripple/ui/plugins/multimedia/panel.html | 78 -- lib/ripple/ui/plugins/security.js | 44 - lib/ripple/ui/plugins/security/panel.html | 35 - lib/ripple/ui/plugins/storage.js | 74 -- lib/ripple/ui/plugins/storage/panel.html | 38 - lib/ripple/ui/plugins/telephony.js | 124 --- lib/ripple/ui/plugins/telephony/panel.html | 44 - lib/ripple/xhr/cors.js | 5 +- test/assets/config/config.xml | 48 +- .../config/config_with_missing_attributes.xml | 43 +- test/assets/media/short_video.ogv | Bin 700699 -> 0 bytes test/unit/devices.js | 2 +- test/unit/fileSystem.js | 81 -- test/unit/opera/widget.js | 84 -- test/unit/platform.js | 6 +- test/unit/vodafone/DeviceStateInfo.js | 121 --- test/unit/wac/AccelerometerInfo.js | 29 - test/unit/wac/Account.js | 51 -- test/unit/wac/AccountInfo.js | 80 -- test/unit/wac/AddressBookItem.js | 202 ---- test/unit/wac/AudioPlayer.js | 293 ------ test/unit/wac/CalendarItem.js | 87 -- test/unit/wac/Camera.js | 186 ---- test/unit/wac/Config.js | 81 -- test/unit/wac/DataNetworkInfo.js | 79 -- test/unit/wac/Device.js | 41 - test/unit/wac/DeviceInfo.js | 88 -- test/unit/wac/DeviceStateInfo.js | 152 --- test/unit/wac/Message.js | 34 - test/unit/wac/Messaging.js | 116 --- test/unit/wac/Multimedia.js | 63 -- test/unit/wac/PIM.js | 867 ------------------ test/unit/wac/PositionInfo.js | 50 - test/unit/wac/PowerInfo.js | 104 --- test/unit/wac/RadioInfo.js | 80 -- test/unit/wac/Telephony.js | 444 --------- test/unit/wac/VideoPlayer.js | 404 -------- test/unit/wac/Widget.js | 103 --- test/unit/widgetConfig.js | 216 ++--- test/unit/xhr.js | 1 - 121 files changed, 171 insertions(+), 9972 deletions(-) delete mode 100644 lib/ripple/devices/SamsungH1.js delete mode 100644 lib/ripple/devices/SamsungM1.js delete mode 100644 lib/ripple/devices/XperiaX10.js delete mode 100644 lib/ripple/devices/XperiaX10Mini.js delete mode 100644 lib/ripple/fileSystem.js delete mode 100644 lib/ripple/platform/opera/4.0/defaultStatus.js delete mode 100644 lib/ripple/platform/opera/4.0/moveBy.js delete mode 100644 lib/ripple/platform/opera/4.0/moveTo.js delete mode 100644 lib/ripple/platform/opera/4.0/resizeBy.js delete mode 100644 lib/ripple/platform/opera/4.0/resizeTo.js delete mode 100644 lib/ripple/platform/opera/4.0/spec.js delete mode 100644 lib/ripple/platform/opera/4.0/spec/config.js delete mode 100644 lib/ripple/platform/opera/4.0/spec/events.js delete mode 100644 lib/ripple/platform/opera/4.0/spec/ui.js delete mode 100644 lib/ripple/platform/opera/4.0/status.js delete mode 100644 lib/ripple/platform/opera/4.0/widget.js delete mode 100644 lib/ripple/platform/vodafone/2.7/DeviceStateInfo.js delete mode 100644 lib/ripple/platform/vodafone/2.7/spec.js delete mode 100644 lib/ripple/platform/vodafone/2.7/spec/config.js delete mode 100644 lib/ripple/platform/vodafone/2.7/spec/device.js delete mode 100644 lib/ripple/platform/vodafone/2.7/spec/events.js delete mode 100644 lib/ripple/platform/vodafone/2.7/spec/ui.js delete mode 100644 lib/ripple/platform/wac/1.0/AccelerometerInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/Account.js delete mode 100644 lib/ripple/platform/wac/1.0/AccountInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/AddressBookItem.js delete mode 100644 lib/ripple/platform/wac/1.0/ApplicationTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/Attachment.js delete mode 100644 lib/ripple/platform/wac/1.0/AudioPlayer.js delete mode 100644 lib/ripple/platform/wac/1.0/CalendarItem.js delete mode 100644 lib/ripple/platform/wac/1.0/CallRecord.js delete mode 100644 lib/ripple/platform/wac/1.0/CallRecordTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/Camera.js delete mode 100644 lib/ripple/platform/wac/1.0/Config.js delete mode 100644 lib/ripple/platform/wac/1.0/DataNetworkConnectionTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/DataNetworkInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/Device.js delete mode 100644 lib/ripple/platform/wac/1.0/DeviceInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/DeviceStateInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/EventRecurrenceTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/Exception.js delete mode 100644 lib/ripple/platform/wac/1.0/ExceptionTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/File.js delete mode 100644 lib/ripple/platform/wac/1.0/Message.js delete mode 100644 lib/ripple/platform/wac/1.0/MessageFolderTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/MessageQuantities.js delete mode 100644 lib/ripple/platform/wac/1.0/MessageTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/Messaging.js delete mode 100644 lib/ripple/platform/wac/1.0/Multimedia.js delete mode 100644 lib/ripple/platform/wac/1.0/PIM.js delete mode 100644 lib/ripple/platform/wac/1.0/PositionInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/PowerInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/RadioInfo.js delete mode 100644 lib/ripple/platform/wac/1.0/RadioSignalSourceTypes.js delete mode 100644 lib/ripple/platform/wac/1.0/Telephony.js delete mode 100644 lib/ripple/platform/wac/1.0/VideoPlayer.js delete mode 100644 lib/ripple/platform/wac/1.0/Widget.js delete mode 100644 lib/ripple/platform/wac/1.0/WidgetManager.js delete mode 100644 lib/ripple/platform/wac/1.0/spec.js delete mode 100644 lib/ripple/platform/wac/1.0/spec/config.js delete mode 100644 lib/ripple/platform/wac/1.0/spec/device.js delete mode 100644 lib/ripple/platform/wac/1.0/spec/events.js delete mode 100644 lib/ripple/platform/wac/1.0/spec/ui.js delete mode 100644 lib/ripple/ui/plugins/audioPlayer.js delete mode 100644 lib/ripple/ui/plugins/fileSystem.js delete mode 100644 lib/ripple/ui/plugins/fileSystem/panel.html delete mode 100644 lib/ripple/ui/plugins/multimedia.js delete mode 100644 lib/ripple/ui/plugins/multimedia/panel.html delete mode 100644 lib/ripple/ui/plugins/security.js delete mode 100644 lib/ripple/ui/plugins/security/panel.html delete mode 100644 lib/ripple/ui/plugins/storage.js delete mode 100644 lib/ripple/ui/plugins/storage/panel.html delete mode 100644 lib/ripple/ui/plugins/telephony.js delete mode 100644 lib/ripple/ui/plugins/telephony/panel.html delete mode 100644 test/assets/media/short_video.ogv delete mode 100644 test/unit/fileSystem.js delete mode 100644 test/unit/opera/widget.js delete mode 100644 test/unit/vodafone/DeviceStateInfo.js delete mode 100644 test/unit/wac/AccelerometerInfo.js delete mode 100644 test/unit/wac/Account.js delete mode 100644 test/unit/wac/AccountInfo.js delete mode 100644 test/unit/wac/AddressBookItem.js delete mode 100644 test/unit/wac/AudioPlayer.js delete mode 100644 test/unit/wac/CalendarItem.js delete mode 100644 test/unit/wac/Camera.js delete mode 100644 test/unit/wac/Config.js delete mode 100644 test/unit/wac/DataNetworkInfo.js delete mode 100644 test/unit/wac/Device.js delete mode 100644 test/unit/wac/DeviceInfo.js delete mode 100644 test/unit/wac/DeviceStateInfo.js delete mode 100644 test/unit/wac/Message.js delete mode 100644 test/unit/wac/Messaging.js delete mode 100644 test/unit/wac/Multimedia.js delete mode 100644 test/unit/wac/PIM.js delete mode 100644 test/unit/wac/PositionInfo.js delete mode 100644 test/unit/wac/PowerInfo.js delete mode 100644 test/unit/wac/RadioInfo.js delete mode 100644 test/unit/wac/Telephony.js delete mode 100644 test/unit/wac/VideoPlayer.js delete mode 100644 test/unit/wac/Widget.js diff --git a/lib/ripple.js b/lib/ripple.js index 2417d28b..147f8a2b 100644 --- a/lib/ripple.js +++ b/lib/ripple.js @@ -18,7 +18,6 @@ var omgwtf = require('ripple/omgwtf'), xhr = require('ripple/xhr'), accelerometer = require('ripple/accelerometer'), geo = require('ripple/geo'), - fileSystem = require('ripple/fileSystem'), platform = require('ripple/platform'), builder = require('ripple/platform/builder'), devices = require('ripple/devices'), @@ -32,7 +31,6 @@ var omgwtf = require('ripple/omgwtf'), .andThen(xhr.initialize, xhr) .andThen(accelerometer.initialize, accelerometer) .andThen(geo.initialize, geo) - .andThen(fileSystem.initialize, fileSystem) .andThen(devices.initialize, devices) .andThen(platform.initialize, platform) .andThen(widgetConfig.initialize, widgetConfig) diff --git a/lib/ripple/constants.js b/lib/ripple/constants.js index 0f95f772..6792799e 100644 --- a/lib/ripple/constants.js +++ b/lib/ripple/constants.js @@ -65,7 +65,7 @@ module.exports = { "PLATFORM": { "SAVED_KEY": "api-key", "DEFAULT": { - "name": "wac", + "name": "phonegap", "version": "1.0" } }, @@ -210,34 +210,5 @@ module.exports = { "XHR": { "PROXY_DISABLED_BUTTON": "settings-xhrproxy-disabled" - }, - - "PLATFORMS": { - "WAC": { - "APPLICATIONS": [ - "ALARM", - "BROWSER", - "CALCULATOR", - "CALENDAR", - "CAMERA", - "CONTACTS", - "FILES", - "GAMES", - "MAIL", - "MEDIAPLAYER", - "MESSAGING", - "PHONECALL", - "PICTURES", - "PROG_MANAGER", - "SETTINGS", - "TASKS", - "WIDGET_MANAGER" - ], - "DEVICE": { - "WIDGET_ENGINE_NAME": "Generic", - "WIDGET_ENGINE_PROVIDER": "tinyHippos", - "WIDGET_ENGINE_VERSION": "x.x" - } - } } }; diff --git a/lib/ripple/devices.js b/lib/ripple/devices.js index b8bc16a1..2861476b 100644 --- a/lib/ripple/devices.js +++ b/lib/ripple/devices.js @@ -72,15 +72,11 @@ _self = module.exports = { "PalmPre2", "Playbook", "QVGA", - "SamsungH1", - "SamsungM1", "Tattoo", "Torch", "Wave", "WQVGA", - "WVGA", - "XperiaX10", - "XperiaX10Mini" + "WVGA" ].reduce(function (hash, deviceID) { hash[deviceID] = require('ripple/devices/' + deviceID); return hash; diff --git a/lib/ripple/devices/FWVGA.js b/lib/ripple/devices/FWVGA.js index 3ce387e5..892e0059 100644 --- a/lib/ripple/devices/FWVGA.js +++ b/lib/ripple/devices/FWVGA.js @@ -46,6 +46,6 @@ module.exports = { "browser": ["Generic"], "ppi": 96, - "platforms": ["web", "wac", "opera", "vodafone", "phonegap"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2" }; diff --git a/lib/ripple/devices/G1.js b/lib/ripple/devices/G1.js index 438868dd..5e7280b1 100644 --- a/lib/ripple/devices/G1.js +++ b/lib/ripple/devices/G1.js @@ -45,7 +45,7 @@ module.exports = { "browser": ["Webkit", "Presto"], "ppi": 180.28, - "platforms": ["web", "wac", "phonegap", "vodafone"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", "notes": { diff --git a/lib/ripple/devices/HVGA.js b/lib/ripple/devices/HVGA.js index 4ea16863..687924fb 100644 --- a/lib/ripple/devices/HVGA.js +++ b/lib/ripple/devices/HVGA.js @@ -46,6 +46,6 @@ module.exports = { "browser": ["Generic"], "ppi": 96, - "platforms": ["web", "wac", "opera", "vodafone", "phonegap"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2" }; diff --git a/lib/ripple/devices/Legend.js b/lib/ripple/devices/Legend.js index 4913fd6c..e3f716ed 100644 --- a/lib/ripple/devices/Legend.js +++ b/lib/ripple/devices/Legend.js @@ -42,29 +42,8 @@ module.exports = { } }, - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 320, - "height": 430, - "paddingTop": 50, - "paddingLeft": 0 - }, - "landscape": { - "width": 480, - "height": 270, - "paddingTop": 50, - "paddingLeft": 0 - } - } - } - } - }, - "ppi": 180.3, "userAgent": "Mozilla/5.0 (Linux; U; Android 2.1; fr-fr; HTC Legend 1.32.163.1 Build/ERD79) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", "browser": ["Webkit", "Presto"], - "platforms": ["web", "wac", "phonegap", "vodafone"] + "platforms": ["web", "phonegap"] }; diff --git a/lib/ripple/devices/Nexus.js b/lib/ripple/devices/Nexus.js index 48be4db5..ae72d92f 100644 --- a/lib/ripple/devices/Nexus.js +++ b/lib/ripple/devices/Nexus.js @@ -45,7 +45,7 @@ module.exports = { "ppi": 252.15, "userAgent": "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", "browser": ["Webkit", "Presto"], - "platforms": ["web", "wac", "phonegap", "vodafone"], + "platforms": ["web", "phonegap"], "notes": { "1": "Specs" diff --git a/lib/ripple/devices/NokiaN97.js b/lib/ripple/devices/NokiaN97.js index bf6a7d41..7d3e4745 100644 --- a/lib/ripple/devices/NokiaN97.js +++ b/lib/ripple/devices/NokiaN97.js @@ -42,29 +42,8 @@ module.exports = { } }, - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 360, - "height": 542, - "paddingTop": 98, - "paddingLeft": 0 - }, - "landscape": { - "width": 640, - "height": 262, - "paddingTop": 98, - "paddingLeft": 0 - } - } - } - } - }, - "ppi": 232, "browser": ["Webkit", "Presto"], "userAgent": "?", - "platforms": ["web", "wac", "vodafone", "phonegap"] + "platforms": ["web", "phonegap"] }; diff --git a/lib/ripple/devices/QVGA.js b/lib/ripple/devices/QVGA.js index 21c7cbb7..659a6b80 100644 --- a/lib/ripple/devices/QVGA.js +++ b/lib/ripple/devices/QVGA.js @@ -44,6 +44,6 @@ module.exports = { "browser": ["Generic"], "ppi": 96, - "platforms": ["web", "wac", "opera", "vodafone", "phonegap"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2" }; diff --git a/lib/ripple/devices/SamsungH1.js b/lib/ripple/devices/SamsungH1.js deleted file mode 100644 index 0ed536f5..00000000 --- a/lib/ripple/devices/SamsungH1.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "id": "SamsungH1", - "name": "Samsung H1 (touch)", - "manufacturer": "Samsung", - "model": "H1", - "firmware": "i8320BUIJ6", - "osName": "LiMo", - "osVersion": "n/a", - - "screen": { - "width": 480, - "height": 800 - }, - "viewPort": { - "portrait": { - "width": 480, - "height": 800, - "paddingTop": 0, - "paddingLeft": 0 - } - }, - - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 480, - "height": 684, - "paddingTop": 116, - "paddingLeft": 0 - } - } - } - } - }, - - "ppi": 265, - "browser": ["Webkit"], - "userAgent": "?", - "platforms": ["web", "wac", "vodafone"] -}; diff --git a/lib/ripple/devices/SamsungM1.js b/lib/ripple/devices/SamsungM1.js deleted file mode 100644 index f129c190..00000000 --- a/lib/ripple/devices/SamsungM1.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "id": "SamsungM1", - "name": "Samsung M1 (touch)", - "manufacturer": "Samsung", - "model": "M1", - "firmware": "n/a", - "osName": "LiMo", - "osVersion": "n/a", - - "screen": { - "width": 240, - "height": 400 - }, - "viewPort": { - "portrait": { - "width": 240, - "height": 400, - "paddingTop": 0, - "paddingLeft": 0 - } - }, - - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 240, - "height": 330, - "paddingTop": 70, - "paddingLeft": 0 - } - } - } - } - }, - - "ppi": 146, - "browser": ["Webkit"], - "userAgent": "?", - "platforms": ["web", "wac", "vodafone"] -}; diff --git a/lib/ripple/devices/Tattoo.js b/lib/ripple/devices/Tattoo.js index f37385e4..d85744bd 100644 --- a/lib/ripple/devices/Tattoo.js +++ b/lib/ripple/devices/Tattoo.js @@ -36,23 +36,8 @@ module.exports = { } }, - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 240, - "height": 283, - "paddingTop": 37, - "paddingLeft": 0 - } - } - } - } - }, - "ppi": 142.9, "userAgent": "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", "browser": ["Webkit"], - "platforms": ["web", "wac", "phonegap", "vodafone"] + "platforms": ["web", "phonegap"] }; diff --git a/lib/ripple/devices/WQVGA.js b/lib/ripple/devices/WQVGA.js index ec8b46e0..3ce9334c 100644 --- a/lib/ripple/devices/WQVGA.js +++ b/lib/ripple/devices/WQVGA.js @@ -44,6 +44,6 @@ module.exports = { "ppi": 96, "browser": ["Generic"], - "platforms": ["web", "wac", "opera", "vodafone", "phonegap"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2" }; diff --git a/lib/ripple/devices/WVGA.js b/lib/ripple/devices/WVGA.js index f54d2979..43b7b6e4 100644 --- a/lib/ripple/devices/WVGA.js +++ b/lib/ripple/devices/WVGA.js @@ -44,6 +44,6 @@ module.exports = { "ppi": 96, "browser": ["Generic"], - "platforms": ["web", "wac", "opera", "vodafone", "phonegap"], + "platforms": ["web", "phonegap"], "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2" }; diff --git a/lib/ripple/devices/XperiaX10.js b/lib/ripple/devices/XperiaX10.js deleted file mode 100644 index b2d1f904..00000000 --- a/lib/ripple/devices/XperiaX10.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "id": "XperiaX10", - "name": "Sony Ericsson - Xperia X10", - "manufacturer": "Sony", - "model": "Xperia", - "firmware": "n/a", - "osName": "Android", - "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3", - "osVersion": "1.6", - - "screen": { - "width": 480, - "height": 854 - }, - "viewPort": { - "portrait": { - "width": 480, - "height": 854, - "paddingTop": 0, - "paddingLeft": 0 - }, - "landscape": { - "width": 854, - "height": 480, - "paddingTop": 0, - "paddingLeft": 0 - } - }, - - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 480, - "height": 787, - "paddingTop": 67, - "paddingLeft": 0 - }, - "landscape": { - "width": 854, - "height": 413, - "paddingTop": 67, - "paddingLeft": 0 - } - } - } - } - }, - - "ppi": 245, - "userAgent": "?", - "browser": ["Webkit"], - "platforms": ["web", "wac", "vodafone"] -}; diff --git a/lib/ripple/devices/XperiaX10Mini.js b/lib/ripple/devices/XperiaX10Mini.js deleted file mode 100644 index bb881267..00000000 --- a/lib/ripple/devices/XperiaX10Mini.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "id": "XperiaX10Mini", - "name": "Sony Ericsson - Xperia X10 mini", - "manufacturer": "Sony", - "model": "Xperia", - "firmware": "n/a", - "osName": "Android", - "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3", - "osVersion": "1.6", - - "screen": { - "width": 240, - "height": 320 - }, - "viewPort": { - "portrait": { - "width": 240, - "height": 320, - "paddingTop": 0, - "paddingLeft": 0 - }, - "landscape": { - "width": 320, - "height": 240, - "paddingTop": 0, - "paddingLeft": 0 - } - }, - - "overrides": { - "api": { - "vodafone": { - "viewPort": { - "portrait": { - "width": 240, - "height": 282, - "paddingTop": 38, - "paddingLeft": 0 - }, - "landscape": { - "width": 320, - "height": 202, - "paddingTop": 38, - "paddingLeft": 0 - } - } - } - } - }, - - "ppi": 156.9, - "userAgent": "?", - "browser": ["Webkit"], - "platforms": ["web", "wac", "vodafone"] -}; diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js deleted file mode 100644 index d6cc3a13..00000000 --- a/lib/ripple/fileSystem.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - db = require('ripple/db'), - exception = require('ripple/exception'), - event = require('ripple/event'), - _console = require('ripple/console'), - utils = require('ripple/utils'), - _fileSystemPaths = { - "photos": { "uri": "" }, - "videos": { "uri": "" }, - "music": { "uri": "" }, - "downloads": { "uri": "" }, - "widgethome": { "uri": "" } - }, - _fileSystemRegex = { - "photos": { "virtualPathRegex": /^\/virtual\/photos\//i }, - "videos": { "virtualPathRegex": /^\/virtual\/videos\//i }, - "music": { "virtualPathRegex": /^\/virtual\/music\//i }, - "downloads": { "virtualPathRegex": /^\/virtual\/downloads\//i }, - "widgethome": { "virtualPathRegex": /^\/virtual\/widgethome\//i } - }, - _overrides = {}; - -module.exports = { - initialize: function () { - _fileSystemPaths = db.retrieveObject(constants.FILESYSTEM.PERSISTENCE_KEY) || _fileSystemPaths; - _fileSystemPaths.widgethome.uri = window.location.protocol + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/') + 1); - }, - - getURI: function getURI(origURI) { - var newURI = origURI, - found = false; - - if (_overrides[origURI]) { - return _overrides[origURI]; - } - - utils.forEach(_fileSystemPaths, function (value, key) { - if (found) { - return; - } - - var uri = value.uri.replace(/\/$/, ""); - if (origURI.match(_fileSystemRegex[key].virtualPathRegex)) { - newURI = origURI.replace(_fileSystemRegex[key].virtualPathRegex, uri + "/"); - found = true; - } - }); - - return newURI; - }, - - exists: function (path) { - try { - var scrubbedUri = this.getURI(path), - xhr = new XMLHttpRequest(); - - xhr.open("GET", scrubbedUri, false); - xhr.send(); - - //HACK: this should return maybe for 403 - return xhr.status !== 404; - } - catch (e) { - exception.handle(e); - _console.log("failed to check if [" + path + "] exists"); - return false; - } - }, - - - getFileSystemPaths: function getFileSystemPaths() { - return utils.copy(_fileSystemPaths); - }, - - updateFileSystemPaths: function updateFileSystemPaths(filePathsObject) { - _fileSystemPaths = utils.copy(filePathsObject); - _fileSystemPaths.widgethome.uri = window.location.protocol + "//" + window.location.host + window.location.pathname; - db.saveObject(constants.FILESYSTEM.PERSISTENCE_KEY, filePathsObject); - }, - - override : function (from, to) { - _overrides[from] = to; - } -}; diff --git a/lib/ripple/platform/opera/4.0/defaultStatus.js b/lib/ripple/platform/opera/4.0/defaultStatus.js deleted file mode 100644 index d2272b60..00000000 --- a/lib/ripple/platform/opera/4.0/defaultStatus.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = {}; diff --git a/lib/ripple/platform/opera/4.0/moveBy.js b/lib/ripple/platform/opera/4.0/moveBy.js deleted file mode 100644 index 8cc04bb5..00000000 --- a/lib/ripple/platform/opera/4.0/moveBy.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'); - -module.exports = function moveBy(deltaX, deltaY) { - exception.raise(exception.types.MethodNotImplemented, "window.moveBy is not yet implemented"); -}; diff --git a/lib/ripple/platform/opera/4.0/moveTo.js b/lib/ripple/platform/opera/4.0/moveTo.js deleted file mode 100644 index 54d1e6de..00000000 --- a/lib/ripple/platform/opera/4.0/moveTo.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'); - -module.exports = function moveTo(posX, posY) { - exception.raise(exception.types.MethodNotImplemented, "window.moveTo is not yet implemented"); -}; diff --git a/lib/ripple/platform/opera/4.0/resizeBy.js b/lib/ripple/platform/opera/4.0/resizeBy.js deleted file mode 100644 index fd9128d6..00000000 --- a/lib/ripple/platform/opera/4.0/resizeBy.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'); - -module.exports = function resizeBy(deltaX, deltaY) { - exception.raise(exception.types.MethodNotImplemented, "window.resizeBy is not yet implemented"); -}; diff --git a/lib/ripple/platform/opera/4.0/resizeTo.js b/lib/ripple/platform/opera/4.0/resizeTo.js deleted file mode 100644 index 95a2d4b6..00000000 --- a/lib/ripple/platform/opera/4.0/resizeTo.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'); - -module.exports = function resizeTo(posX, posY) { - exception.raise(exception.types.MethodNotImplemented, "window.resizeTo is not yet implemented"); -}; diff --git a/lib/ripple/platform/opera/4.0/spec.js b/lib/ripple/platform/opera/4.0/spec.js deleted file mode 100644 index f0d5b8ea..00000000 --- a/lib/ripple/platform/opera/4.0/spec.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - id: "opera", - version: "4.0", - name: "Opera", - type: "platform", - - persistencePrefix: "opera-", - - config: require('ripple/platform/opera/4.0/spec/config'), - device: {}, - ui: require('ripple/platform/opera/4.0/spec/ui'), - events: require('ripple/platform/opera/4.0/spec/events'), - - objects: { - navigator: { - path: "w3c/1.0/navigator" - }, - widget: { - path: "opera/4.0/widget" - }, - defaultStatus: { - path: "opera/4.0/defaultStatus" - }, - moveBy: { - path: "opera/4.0/moveBy" - }, - moveTo: { - path: "opera/4.0/moveTo" - }, - resizeBy: { - path: "opera/4.0/resizeBy" - }, - resizeTo: { - path: "opera/4.0/resizeTo" - }, - status: { - path: "opera/4.0/status" - } - } -}; - diff --git a/lib/ripple/platform/opera/4.0/spec/config.js b/lib/ripple/platform/opera/4.0/spec/config.js deleted file mode 100644 index e8a5f21b..00000000 --- a/lib/ripple/platform/opera/4.0/spec/config.js +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'); - -module.exports = { - config: "config.xml", - configSchema: { - rootElement: "widget", - widget: { - nodeName: "widget", - required: true, - occurrence: 1, - attributes: { - defaultmode: { - attributeName: "defaultmode", - required: false, - type: "listDefault", - listValues: ["widget", "application", "fullscreen"], - defaultValue: "widget" - }, - dockable: { - attributeName: "dockable", - required: false, - type: "listBoolean", - listValues: ["yes", "true", "dockable"], - defaultValue: false - }, - transparent: { - attributeName: "transparent", - required: false, - type: "listBoolean", - listValues: ["yes", "true", "transparent"], - defaultValue: false - }, - network: { - attributeName: "network", - required: false, - type: "list", - listValues: ["public", "private", "public private", "private public"] - } - }, - children: { - widgetname: { - nodeName: "widgetname", - required: true, - occurrence: 1, - type: "string" - }, - width: { - nodeName: "width", - required: false, - occurrence: 1, - type: "integer", - defaultValue: 300 - }, - height: { - nodeName: "height", - required: false, - occurrence: 1, - type: "integer", - defaultValue: 300 - }, - widgetfile: { - nodeName: "widgetfile", - required: false, - occurrence: 1, - type: "regex", - regex: constants.REGEX.URL, - helpText: "An author must not %-encode all path names.

It is recommended that authors use this element." - }, - author: { - nodeName: "author", - required: false, - occurrence: 1, - children: { - name: { - nodeName: "name", - type: "string", - occurrence: 1, - required: false - }, - organization: { - nodeName: "organization", - type: "string", - occurrence: 1, - required: false - }, - email: { - nodeName: "email", - type: "regex", - regex: constants.REGEX.EMAIL, - occurrence: 1, - required: false - }, - link: { - nodeName: "link", - type: "regex", - regex: constants.REGEX.URL, - occurrence: 1, - required: false - } - } - }, - description: { - nodeName: "description", - required: false, - occurrence: 1, - type: "string" - }, - icon: { - nodeName: "icon", - required: false, - occurrence: 0, - type: "string", - attributes: { - width: { - attributeName: "width", - type: "integer", - required: false - }, - height: { - attributeName: "height", - type: "integer", - required: false - } - } - }, - feature: { - nodeName: "feature", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - type: "string", - required: true - }, - required: { - attributeName: "required", - type: "boolean", - required: false - } - }, - children: { - param: { - nodeName: "param", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - required: true, - type: "string" - }, - value: { - attributeName: "value", - required: true, - type: "string" - } - } - } - } - }, - id: { - nodeName: "id", - required: false, - occurrence: 1, - children: { - host: { - nodeName: "host", - required: true, - occurrence: 1, - type: "regex", - regex: constants.REGEX.URL - }, - name: { - nodeName: "name", - required: true, - occurrence: 1, - type: "string" - }, - revised: { - nodeName: "revised", - required: true, - occurrence: 1, - type: "regex", - regex: constants.REGEX.WC3_DTF - } - } - }, - security: { - nodeName: "security", - required: false, - occurrence: 1, - children: { - access: { - nodeName: "access", - required: false, - occurrence: 1, - helpText: "A user agent must treat undeclared child elements of the access element to mean that an author is requesting access to the full capabilities afforded by the semantics of the missing element. An example is that if the host element is missing, the widget is requesting access to all hosts.", - children: { - protocol: { - nodeName: "protocol", - occurrence: 0, - type: "list", - listValues: ["http", "https"], - required: false - }, - host: { - nodeName: "host", - occurrence: 0, - type: "string", - required: false - }, - port: { - nodeName: "port", - occurrence: 0, - type: "listNumbers", - required: false - }, - path: { - nodeName: "path", - occurrence: 0, - type: "string", - required: false - } - } - }, - content: { - nodeName: "content", - required: false, - occurrence: 1, - attributes: { - plugin: { - attributeName: "plugin", - type: "string", - required: true, - listValues: ["yes", "no", "true", "false", "plugin"] - } - } - } - } - } - } - } - }, - extractInfo: function (configValidationObject) { - if (!configValidationObject) { - return null; - } - - var widgetInfo = {}; - - widgetInfo.id = configValidationObject.widget.children.id.children.name.validationResult[0].value || ""; - widgetInfo.name = configValidationObject.widget.children.widgetname.validationResult[0].value || ""; - widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].value || ""; - widgetInfo.preferences = {}; - - return widgetInfo; - } -}; diff --git a/lib/ripple/platform/opera/4.0/spec/events.js b/lib/ripple/platform/opera/4.0/spec/events.js deleted file mode 100644 index d20c97d7..00000000 --- a/lib/ripple/platform/opera/4.0/spec/events.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "contexts": { - "widget": { - "events": { - "WidgetShow": "onShow", - "WidgetHide": "onHide" - }, - "context": "widget" - } - } -}; diff --git a/lib/ripple/platform/opera/4.0/spec/ui.js b/lib/ripple/platform/opera/4.0/spec/ui.js deleted file mode 100644 index 9ee7d852..00000000 --- a/lib/ripple/platform/opera/4.0/spec/ui.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - plugins: [ - "storage", - "widgetConfig", - "platformEvents" - ] -}; diff --git a/lib/ripple/platform/opera/4.0/status.js b/lib/ripple/platform/opera/4.0/status.js deleted file mode 100644 index d2272b60..00000000 --- a/lib/ripple/platform/opera/4.0/status.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = {}; diff --git a/lib/ripple/platform/opera/4.0/widget.js b/lib/ripple/platform/opera/4.0/widget.js deleted file mode 100644 index e4817bb1..00000000 --- a/lib/ripple/platform/opera/4.0/widget.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var event = require('ripple/event'), - _console = require('ripple/console'), - app = require('ripple/app'), - exception = require('ripple/exception'), - notifications = require('ripple/notifications'), - utils = require('ripple/utils'), - db = require('ripple/db'), - platform = require('ripple/platform'), - _self; - -event.on("ScreenChangeDimensions", function (width, height) { - var eventToFire = document.createEvent("Event"); - _console.log("Firing resolution changed event for width: " + width + " and height: " + height); - eventToFire.height = height; - eventToFire.width = width; - eventToFire.initEvent("resolution", false, false); - window.dispatchEvent(eventToFire); -}); - -event.on("WidgetShow", function () { - if (_self.onShow) { - _self.onShow(); - } -}); - -event.on("WidgetHide", function () { - if (_self.onHide) { - _self.onHide(); - } -}); - -_self = { - // read only - originalURL: "", - identifier: "", - widgetMode: "application", - - onShow: null, - onHide: null, - - openUrl: function (url) { - window.open(url); - }, - - setPreferenceForKey: function (preference, key) { - utils.validateNumberOfArguments(1, 2, arguments.length); - utils.validateArgumentType(key, "string"); - - var msg = "", - prefix = platform.getPersistencePrefix(); - - if (app.isPreferenceReadOnly(key)) { - msg += "Cannot modify a read only preference. Preference key: " + key; - } - else { - if (preference === null) { - msg += "deleting preference " + key; - db.remove(key, prefix); - } - else { - msg += "setting preference " + key + " == " + preference; - utils.validateArgumentType(preference, "string"); - db.save(key, preference, prefix); - } - } - - _console.log(msg); - event.trigger("StorageUpdatedEvent"); - }, - - preferenceForKey: function (key) { - utils.validateNumberOfArguments(1, 1, arguments.length); - utils.validateArgumentType(key, "string"); - - var prefix = platform.getPersistencePrefix(), - value = db.retrieve(key, prefix) || undefined; - - _console.log("retrieving preference " + key + " == " + value); - - return value; - }, - - hide: function () { - exception.raise(exception.types.MethodNotImplemented, "The hide method is not yet implemented"); - }, - - show: function () { - exception.raise(exception.types.MethodNotImplemented, "The show method is not yet implemented"); - }, - - getAttention: function () { - notifications.openNotification("Hi i''m getting your attention!!!!"); - }, - - showNotification: function (message, callback) { - notifications.openNotification(message); - - if (callback) { - callback.apply(); - } - }, - - addEventListener: function (type, expression, bubbling) { - _console.log("Adding Widget Event Listener for type == " + type); - bubbling = bubbling || false; - window.addEventListener(type, expression, bubbling); - }, - - removeEventListener: function (type, listener, useCapture) { - _console.log("Removing a Widget Event Listener for type == " + type); - window.removeEventListener(type, listener, useCapture); - } -}; - -module.exports = _self; diff --git a/lib/ripple/platform/spec.js b/lib/ripple/platform/spec.js index f606beaa..e01092ec 100644 --- a/lib/ripple/platform/spec.js +++ b/lib/ripple/platform/spec.js @@ -14,11 +14,8 @@ * limitations under the License. */ module.exports = { - "wac": {"1.0": require('ripple/platform/wac/1.0/spec')}, "phonegap": {"1.0": require('ripple/platform/phonegap/1.0/spec')}, "webworks.handset": {"2.0.0": require('ripple/platform/webworks.handset/2.0.0/spec')}, "webworks.tablet": {"2.0.0": require('ripple/platform/webworks.tablet/2.0.0/spec')}, - "web": {"default": require('ripple/platform/web/default/spec')}, - "opera": {"4.0": require('ripple/platform/opera/4.0/spec')}, - "vodafone": {"2.7": require('ripple/platform/vodafone/2.7/spec')} + "web": {"default": require('ripple/platform/web/default/spec')} }; diff --git a/lib/ripple/platform/vodafone/2.7/DeviceStateInfo.js b/lib/ripple/platform/vodafone/2.7/DeviceStateInfo.js deleted file mode 100644 index 3e9ea8f3..00000000 --- a/lib/ripple/platform/vodafone/2.7/DeviceStateInfo.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - exception = require('ripple/exception'), - geo = require('ripple/geo'), - deviceSettings = require('ripple/deviceSettings'), - PositionInfo = require('ripple/platform/wac/1.0/PositionInfo'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - _self; - -_self = { - // Properties - availableMemory: undefined, - language: undefined, - keypadLightOn: undefined, - backLightOn: undefined, - processorUtilizationPercent: undefined, - audioPath: undefined, - - // Methods/Callbacks - // TODO: define setter/getter and move into closure? - onPositionRetrieved: undefined, // this.onPositionRetrieved(Widget.Device.PositionInfo, method); - - requestPositionInfo: function (method) { - utils.validateNumberOfArguments(1, 1, arguments.length, - ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid number of parameters", new Exception()); - utils.validateArgumentType(method, "string", - ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid parameter", new Exception()); - - if (!(method.match(/gps|agps|cellid/))) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, - "Invalid method argument, expected (gps, agps or cellid)", new Exception()); - } - - if (typeof _self.onPositionRetrieved === "function") { - var delay = geo.delay * 1000, - timeout = geo.timeout; - window.setTimeout(function () { - var pos = PositionInfo, - errorObj = {}; - - if (timeout) { - //create - utils.forEach(pos, function (val, key) { - errorObj[key] = undefined; - }); - pos = errorObj; - } - _self.onPositionRetrieved(pos, method); - }, delay); - } - }, - - onScreenChangeDimensions: undefined, - - onFlipEvent: undefined - -}; - -_self.__defineGetter__("availableMemory", function () { - return deviceSettings.retrieveAsInt("DeviceStateInfo.availableMemory"); -}); - -_self.__defineGetter__("language", function () { - return deviceSettings.retrieve("DeviceStateInfo.language"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/vodafone/2.7/spec.js b/lib/ripple/platform/vodafone/2.7/spec.js deleted file mode 100644 index 28a84756..00000000 --- a/lib/ripple/platform/vodafone/2.7/spec.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - - id: "vodafone", - version: "2.7", - name: "Vodafone", - type: "carrier", - - persistencePrefix: "vodafone-", - - config: require('ripple/platform/vodafone/2.7/spec/config'), - device: require('ripple/platform/vodafone/2.7/spec/device'), - ui: require('ripple/platform/vodafone/2.7/spec/ui'), - events: require('ripple/platform/vodafone/2.7/spec/events'), - - objects: { - navigator: { - path: "w3c/1.0/navigator" - }, - WidgetManager: { - path: "wac/1.0/WidgetManager" - }, - Widget: { - path: "wac/1.0/Widget", - children: { - Device: { - path: "wac/1.0/Device", - children: { - AccountInfo: { - path: "wac/1.0/AccountInfo" - }, - ApplicationTypes: { - path: "wac/1.0/ApplicationTypes" - }, - DataNetworkInfo: { - path: "wac/1.0/DataNetworkInfo", - children: { - DataNetworkConnectionTypes: { - path: "wac/1.0/DataNetworkConnectionTypes" - } - } - }, - DeviceInfo: { - path: "wac/1.0/DeviceInfo" - }, - DeviceStateInfo: { - path: "vodafone/2.7/DeviceStateInfo", - children: { - AccelerometerInfo: { - path: "wac/1.0/AccelerometerInfo" - } - } - }, - File: { - path: "wac/1.0/File" - }, - PositionInfo: { - path: "wac/1.0/PositionInfo" - }, - RadioInfo: { - path: "wac/1.0/RadioInfo", - children: { - RadioSignalSourceTypes: { - path: "wac/1.0/RadioSignalSourceTypes" - } - } - } - } - }, - ExceptionTypes: { - path: "wac/1.0/ExceptionTypes" - }, - Exception: { - path: "wac/1.0/Exception" - }, - PIM: { - path: "wac/1.0/PIM", - children: { - AddressBookItem: { - path: "wac/1.0/AddressBookItem" - }, - CalendarItem: { - path: "wac/1.0/CalendarItem" - }, - EventRecurrenceTypes: { - path: "wac/1.0/EventRecurrenceTypes" - } - } - }, - Multimedia: { - path: "wac/1.0/Multimedia", - children: { - Camera: { - path: "wac/1.0/Camera" - }, - AudioPlayer: { - path: "wac/1.0/AudioPlayer" - } - } - } - } - }, - widget: { - path: "opera/4.0/widget" - }, - defaultStatus: { - path: "opera/4.0/defaultStatus" - }, - moveBy: { - path: "opera/4.0/moveBy" - }, - moveTo: { - path: "opera/4.0/moveTo" - }, - resizeBy: { - path: "opera/4.0/resizeBy" - }, - resizeTo: { - path: "opera/4.0/resizeTo" - }, - status: { - path: "opera/4.0/status" - } - } - -}; diff --git a/lib/ripple/platform/vodafone/2.7/spec/config.js b/lib/ripple/platform/vodafone/2.7/spec/config.js deleted file mode 100644 index e2d0fdb0..00000000 --- a/lib/ripple/platform/vodafone/2.7/spec/config.js +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - utils = require('ripple/utils'), - platform = require('ripple/platform'), - db = require('ripple/db'); - -module.exports = { - fileName: "config.xml", - validateVersion: function (configValidationObject) { - var valid = true; - valid = !((!configValidationObject.widget.validationResult[0].attributes.xmlns.valid) || - (!configValidationObject.widget.validationResult[0].attributes["xmlns:JIL"].valid)); - - return valid; - }, - extractInfo: function (configValidationObject) { - if (!configValidationObject) { - return null; - } - - var widgetInfo = {}, - configPreferences, - preferenceName; - - widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || ""; - widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value; - widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value; - widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value; - widgetInfo.preferences = {}; - - configPreferences = configValidationObject.widget.children.preference.validationResult; - - utils.forEach(configPreferences, function (preference) { - preferenceName = preference.attributes.name.value; - if (preferenceName) { - widgetInfo.preferences[preferenceName] = { - "key": preferenceName, - "value": preference.attributes.value.value || "", - "readonly": preference.attributes.readonly.value === "true" - }; - - db.save(preferenceName, - widgetInfo.preferences[preferenceName].value, - platform.getPersistencePrefix(widgetInfo.id)); - } - }); - - return widgetInfo; - }, - schema: { - rootElement: "widget", - widget: { - nodeName: "widget", - required: true, - occurrence: 1, - helpText: "\"widget\" element describes widget information in configuration documents and serves as a container for other elements. It must be used in configuration document and may have following child elments: name,description,icon,author,license,content,maximum_display_mode,update,feature,access,billing. \"widget\" element MAY have following attributes: id,version,height,width,xml:lang", - attributes: { - xmlns: { - attributeName: "xmlns", - required: true, - type: "list", - listValues: ["http://www.w3.org/ns/widgets"] - }, - "xmlns:JIL": { - attributeName: "xmlns:JIL", - required: true, - type: "list", - listValues: ["http://www.jil.org/ns/widgets1.2"] - }, - "xmlns:its": { - attributeName: "xmlns:its", - helpText: "Indicates Text Directionality can be used. According to W3C spec, this feature is at risk, therefore we don't currently validate this.", - required: false, - type: "string" - }, - id: { - attributeName: "id", - required: true, - type: "string" - }, - version: { - attributeName: "version", - helpText: "Version must be in the following format: jil-rec-version-tag = major-version \".\" minor-version [\".\" version-desc]", - required: true, - type: "regex", - regex: /^\d{1,2}\.\d{1,2}(\.[A-Za-z0-9]{1,10})?$/ - }, - height: { - attributeName: "height", - required: true, - type: "integer" - }, - width: { - attributeName: "width", - required: true, - type: "integer" - }, - viewmodes: { - attributeName: "viewmodes", - required: false, - type: "list", - listValues: ["floating", "fullscreen"] - }, - "xml:lang": { - attributeName: "xml:lang", - required: false, - type: "iso-language" - } - }, - children: { - preference: { - nodeName: "preference", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - type: "string", - required: true - }, - value: { - type: "string", - attributeName: "value", - required: false - }, - readonly: { - attributeName: "readonly", - type: "boolean", - required: false - } - } - }, - name: { - nodeName: "name", - required: false, - occurrence: 0, - type: "string", - attributes: { - "short": { - attributeName: "short", - type: "string", - required: false - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - description: { - nodeName: "description", - required: false, - occurrence: 0, - type: "string", - attributes: { - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - icon: { - nodeName: "icon", - required: false, - occurrence: 0, - attributes: { - src: { - attributeName: "src", - type: "string", - required: true - }, - height: { - attributeName: "height", - required: false, - type: "integer" - }, - width: { - attributeName: "width", - required: false, - type: "integer" - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - author: { - nodeName: "author", - required: false, - occurrence: 1, - type: "string", - attributes: { - email: { - attributeName: "email", - type: "regex", - required: false, - regex: constants.REGEX.EMAIL - }, - href: { - attributeName: "href", - type: "regex", - required: false, - regex: constants.REGEX.URL - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - license: { - nodeName: "license", - required: false, - occurrence: 1, - type: "string", - attributes: { - href: { - attributeName: "href", - type: "regex", - required: false, - regex: constants.REGEX.URL - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - content: { - nodeName: "content", - required: false, - occurrence: 1, - attributes: { - src: { - attributeName: "src", - type: "string", - required: true - }, - encoding: { - attributeName: "encoding", - type: "string", - required: false - }, - type: { - attributeName: "type", - type: "string", - required: false - } - } - }, - feature: { - nodeName: "feature", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - type: "list", - required: true, - listValues: ["http://jil.org/jil/api/1.1/widget", "http://jil.org/jil/api/1.1.5/exception", - "http://jil.org/jil/api/1.1.5/exceptiontypes", "http://jil.org/jil/api/1.1/device", - "http://jil.org/jil/api/1.1/accountinfo", "http://jil.org/jil/api/1.1/deviceinfo", - "http://jil.org/jil/api/1.1.1/datanetworkinfo", "http://jil.org/jil/api/1.1/devicestateinfo", - "http://jil.org/jil/api/1.1/accelerometerinfo", "http://jil.org/jil/api/1.1/config", - "http://jil.org/jil/api/1.1.1/file", "http://jil.org/jil/api/1.1/positioninfo", - "http://jil.org/jil/api/1.1/powerinfo", "http://jil.org/jil/api/1.1.1/radioinfo", - "http://jil.org/jil/api/1.1.5/radiosignalsourcetypes", "http://jil.org/jil/api/1.1.5/applicationtypes", - "http://jil.org/jil/api/1.1/messaging", "http://jil.org/jil/api/1.1/account", - "http://jil.org/jil/api/1.1/attachment", "http://jil.org/jil/api/1.1/message", - "http://jil.org/jil/api/1.1.4/messagefoldertypes", "http://jil.org/jil/api/1.1/messagequantities", - "http://jil.org/jil/api/1.1/messagetypes", "http://jil.org/jil/api/1.1/multimedia", - "http://jil.org/jil/api/1.1/audioplayer", "http://jil.org/jil/api/1.1.2/camera", - "http://jil.org/jil/api/1.1.2/videoplayer", "http://jil.org/jil/api/1.1.1/pim", - "http://jil.org/jil/api/1.1/addressbookitem", "http://jil.org/jil/api/1.1/calendaritem", - "http://jil.org/jil/api/1.1/eventrecurrencetypes", "http://jil.org/jil/api/1.1.1/telephony", - "http://jil.org/jil/api/1.1/callrecord", "http://jil.org/jil/api/1.1.1/callrecordtypes", - "http://jil.org/jil/api/1.1.1/widgetmanager"] - }, - required: { - attributeName: "required", - type: "boolean", - required: false - } - } - }, - "JIL:maximum_display_mode": { - nodeName: "JIL:maximum_display_mode", - required: false, - occurrence: 1, - attributes: { - height: { - attributeName: "height", - type: "integer", - required: false - }, - width: { - attributeName: "width", - type: "integer", - required: false - } - } - }, - "JIL:update": { - nodeName: "JIL:update", - required: false, - occurrence: 1, - attributes: { - href: { - attributeName: "href", - type: "regex", - required: true, - regex: constants.REGEX.URL - }, - period: { - attributeName: "period", - helpText: "Possible values for the period attribute are: 0, 1, 2, 3 meaning: every time the widget is opened in maximum display mode, every day, every week, every month; respectivly", - type: "list", - required: true, - listValues: ["0", "1", "2", "3"] - } - } - }, - "JIL:access": { - nodeName: "JIL:access", - required: false, - occurrence: 1, - attributes: { - network: { - attributeName: "network", - type: "boolean", - required: false - }, - localfs: { - attributeName: "localfs", - type: "boolean", - required: false - }, - remote_scripts: { - attributeName: "remote_scripts", - type: "boolean", - required: false - } - } - }, - "JIL:billing": { - nodeName: "JIL:billing", - required: false, - occurrence: 1, - attributes: { - required: { - attributeName: "required", - type: "boolean", - required: true - } - } - } - } - } - } -}; diff --git a/lib/ripple/platform/vodafone/2.7/spec/device.js b/lib/ripple/platform/vodafone/2.7/spec/device.js deleted file mode 100644 index fa60956a..00000000 --- a/lib/ripple/platform/vodafone/2.7/spec/device.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - event = require('ripple/event'); - -module.exports = { - "AccountInfo": { - "phoneUserUniqueId": { - "name": "User Unique Id", - "control": { - "type": "text", - "value": new Date().getTime().toString() - } - }, - "phoneOperatorName": { - "name": "Operator Name", - "control": { - "type": "text", - "value": "" - } - } - }, - "RadioInfo": { - "isRoaming": { - "name": "Is Roaming", - "control": { - "type": "checkbox", - "value": false - }, - "callback": function () { - event.trigger("RadioSignalSourceChanged"); - } - }, - "isRadioEnabled": { - "name": "Is Radio Enabled", - "control": { - "type": "checkbox", - "value": true - } - } - }, - "DeviceInfo": { - "phoneColorDepthDefault": { - "name": "Color Depth", - "control": { - "type": "number", - "value": 24 - } - } - }, - "DeviceStateInfo": { - "availableMemory": { - "name": "Available Memory", - "control": { - "type": "range", - "value": 262144, - "min": 0, - "max": 4096000 - } - }, - "language": { - "name": "Language", - "control": { - "type": "select", - "value": "eng" - }, - "options": (function () { - var i, - optionList = {}, - iterator = constants.LANG.ISO6392_LIST; - - for (i = 0; i <= iterator.length - 1; i++) { - optionList[i] = iterator[i]; - } - - return optionList; - }()) - } - }, - "DataNetworkInfo": { - "isDataNetworkConnected": { - "name": "Data Network Is Connected", - "control": { - "type": "checkbox", - "value": true - }, - "callback": function (setting) { - event.trigger("isDataNetworkConnectedChanged", [setting]); - } - } - } -}; diff --git a/lib/ripple/platform/vodafone/2.7/spec/events.js b/lib/ripple/platform/vodafone/2.7/spec/events.js deleted file mode 100644 index 67feceb6..00000000 --- a/lib/ripple/platform/vodafone/2.7/spec/events.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "contexts": { - "Widget": { - "events": { - "WidgetWakeup": { - name: "WidgetWakeup", - description: "onWakeup", - args: false - }, - "WidgetMaximize": { - name: "WidgetMaximize", - description: "onMaximize", - args: false - }, - "WidgetFocus": { - name: "WidgetMaximize", - description: "onFocus", - args: false - }, - "WidgetRestore": { - name: "WidgetRestore", - desription: "onRestore", - args: false - } - }, - "context": "Widget" - } - } -}; diff --git a/lib/ripple/platform/vodafone/2.7/spec/ui.js b/lib/ripple/platform/vodafone/2.7/spec/ui.js deleted file mode 100644 index de36273b..00000000 --- a/lib/ripple/platform/vodafone/2.7/spec/ui.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - plugins: [ - "accelerometer", - "deviceSettings", - "fileSystem", - "geoView", - "multimedia", - "audioPlayer", - "storage", - "platformEvents", - "widgetConfig" - ] -}; diff --git a/lib/ripple/platform/wac/1.0/AccelerometerInfo.js b/lib/ripple/platform/wac/1.0/AccelerometerInfo.js deleted file mode 100644 index f5942d00..00000000 --- a/lib/ripple/platform/wac/1.0/AccelerometerInfo.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var accelerometer = require('ripple/accelerometer'), - _self = {}; - -_self.__defineGetter__("xAxis", function () { - return accelerometer.getInfo().accelerationIncludingGravity.x; -}); - -_self.__defineGetter__("yAxis", function () { - return accelerometer.getInfo(true).accelerationIncludingGravity.y; -}); - -_self.__defineGetter__("zAxis", function () { - return accelerometer.getInfo(true).accelerationIncludingGravity.z; -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/Account.js b/lib/ripple/platform/wac/1.0/Account.js deleted file mode 100644 index b5130dd3..00000000 --- a/lib/ripple/platform/wac/1.0/Account.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var deviceSettings = require('ripple/deviceSettings'), - _self; - -_self = { - accountName: undefined, - accountId: undefined -}; - -_self.__defineGetter__("accountName", function () { - return deviceSettings.retrieve("Account.accountName"); -}); - -_self.__defineGetter__("accountId", function () { - return deviceSettings.retrieve("Account.accountId"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/AccountInfo.js b/lib/ripple/platform/wac/1.0/AccountInfo.js deleted file mode 100644 index 7ab8762c..00000000 --- a/lib/ripple/platform/wac/1.0/AccountInfo.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var deviceSettings = require('ripple/deviceSettings'), - _self = { - phoneUserUniqueId: undefined, - phoneMSISDN: undefined, - phoneOperatorName: undefined, - userAccountBalance: undefined, - userSubscriptionType: undefined - }; - -_self.__defineGetter__("phoneUserUniqueId", function () { - return deviceSettings.retrieve("AccountInfo.phoneUserUniqueId"); -}); - -_self.__defineGetter__("phoneMSISDN", function () { - return deviceSettings.retrieve("AccountInfo.phoneMSISDN"); -}); - -_self.__defineGetter__("phoneOperatorName", function () { - return deviceSettings.retrieve("AccountInfo.phoneOperatorName"); -}); - -_self.__defineGetter__("userAccountBalance", function () { - return deviceSettings.retrieve("AccountInfo.userAccountBalance"); -}); - -_self.__defineGetter__("userSubscriptionType", function () { - return deviceSettings.retrieve("AccountInfo.userSubscriptionType"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/AddressBookItem.js b/lib/ripple/platform/wac/1.0/AddressBookItem.js deleted file mode 100644 index 641edc9e..00000000 --- a/lib/ripple/platform/wac/1.0/AddressBookItem.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - exception = require('ripple/exception'), - db = require('ripple/db'), - constants = require('ripple/constants'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'); - -function _validateArgs(min, max, len) { - utils.validateNumberOfArguments(min, max, len, - ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception()); -} - -function _validateType(arg, argType) { - utils.validateArgumentType(arg, argType, - ExceptionTypes.INVALID_PARAMETER, "argument of wrong type provided", - new Exception()); -} - -module.exports = function () { - function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); - } - - this.addressBookItemId = undefined; - this.fullName = undefined; - this.mobilePhone = undefined; - this.homePhone = undefined; - this.workPhone = undefined; - this.eMail = undefined; - this.company = undefined; - this.title = undefined; - this.address = undefined; - - this.setAttributeValue = function (attribute, value) { - _validateArgs(2, 2, arguments.length); - _validateType(attribute, "string"); - this[attribute] = value; - }; - this.setAddressGroupNames = function (groups) { - _throwUnsupportedException("PIM.AddressBookItem.setAddressGroupNames"); - }; - this.getAttributeValue = function (attribute) { - _validateArgs(1, 1, arguments.length); - _validateType(attribute, "string"); - return this[attribute]; - }; - this.getAddressGroupNames = function () { - _throwUnsupportedException("PIM.AddressBookItem.getAddressGroupNames"); - }; - this.getAvailableAttributes = function () { - return utils.reduce(this, function (attributes, value, key) { - if (typeof(value) !== 'function') { - attributes.push(key); - } - return attributes; - }, []).sort(); - }; - this.update = function () { - var items = db.retrieveObject(constants.PIM.ADDRESS_LIST_KEY), - that = this, - itemIndex = items.reduce(function (current, value, i) { - return value.addressBookItemId === that.addressBookItemId ? - i : current; - }, -1); - - if (itemIndex >= 0) { - items[itemIndex] = this; - db.saveObject(constants.PIM.ADDRESS_LIST_KEY, items); - } - else { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "Address Book Item not found: " + (this.addressBookItemId || ""), new Exception()); - } - - }; -}; diff --git a/lib/ripple/platform/wac/1.0/ApplicationTypes.js b/lib/ripple/platform/wac/1.0/ApplicationTypes.js deleted file mode 100644 index 8ba17713..00000000 --- a/lib/ripple/platform/wac/1.0/ApplicationTypes.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - constants = require('ripple/constants'), - _self = {}; - -utils.forEach(constants.PLATFORMS.WAC.APPLICATIONS, function (application) { - _self.__defineGetter__(application, function () { - return application; - }); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/Attachment.js b/lib/ripple/platform/wac/1.0/Attachment.js deleted file mode 100644 index 4f947219..00000000 --- a/lib/ripple/platform/wac/1.0/Attachment.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = function () { - this.fileName = ""; - this.MIMEType = ""; - this.size = 0; -}; diff --git a/lib/ripple/platform/wac/1.0/AudioPlayer.js b/lib/ripple/platform/wac/1.0/AudioPlayer.js deleted file mode 100644 index d4a80785..00000000 --- a/lib/ripple/platform/wac/1.0/AudioPlayer.js +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - event = require('ripple/event'), - exception = require('ripple/exception'), - utils = require('ripple/utils'), - fileSystem = require('ripple/fileSystem'), - _console = require('ripple/console'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - _self, - _state = null, - _STATES = constants.MULTIMEDIA.AUDIO_STATES, - _currentAudioFile, - _audio, _loopCount; - -event.on("MultimediaAudioStateChanged", function updateAudioState(state) { - _state = state; - if (typeof _self.onStateChange === 'function') { - _self.onStateChange.apply(_self, arguments); - } -}); - -_audio = utils.createElement("audio", { - "id": "multimedia-audio" -}); - -_audio.addEventListener('error', function () { - _console.warn("AudioPlayer encountered an error: " + _audio.error.code); - if (_audio.error.code === 4) { - _console.warn("AudioPlayer error 4 could be caused by missing codecs"); - } - _state = null; - event.trigger("MultimediaAudioStateChanged", [null], true); -}); - -_audio.addEventListener('ended', function handleAudioEnded() { - event.trigger("MultimediaAudioStateChanged", [_STATES.COMPLETED], true); - if (_loopCount > 1) { - _self.open(_currentAudioFile); - _self.play(_loopCount--); - } -}); - -document.getElementById("ui").appendChild(_audio); - -function _validateAndSet(state, validStates, callbackBeforeSuccess) { - var i, valid = false; - - for (i = 0; i < validStates.length; i++) { - if (validStates[i] === _state) { - valid = true; - } - } - - if (!valid) { - _console.warn("Attempted to initiate AudioPlayer." + state + - " in invalid state. current state: " + _state); - } else { - if (typeof(callbackBeforeSuccess) === "function") { - callbackBeforeSuccess.apply(); - } - event.trigger("MultimediaAudioStateChanged", [state], true); - } - - return valid; -} - -function _validateAudioType(fileUrl) { - var matched = fileUrl.match(/\.(\w*)$/), - type = matched ? matched[1] : ""; - - if (_audio && _audio.canPlayType("audio/" + type) === "") { - _console.warn("Attempting to load an audio that might not work in the current browser [" + fileUrl + "]"); - } -} - -_self = { - onStateChange: undefined, - - open: function (fileUrl) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.open wrong number of arguments", new Exception()); - utils.validateArgumentType(fileUrl, "string", ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.open invalid parameter! expected string, fileUrl: " + - fileUrl, new Exception()); - - if (fileUrl.match(/^rtsp:\/\//)) { - exception.raise(exception.types.MethodNotImplemented, "rtsp:// scheme not yet supported. sorry :("); - } - - _validateAndSet(_STATES.OPENED, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED, null], function () { - _validateAudioType(fileUrl); - _currentAudioFile = fileSystem.getURI(fileUrl); - _audio.setAttribute("src", _currentAudioFile); - _audio.load(); - }); - }, - - play: function (repeatTimes) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.play wrong number of arguments", new Exception()); - utils.validateArgumentType(repeatTimes, "integer", ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.play invalid parameter! expected integer, repeatTimes: " + repeatTimes, new Exception()); - - if (repeatTimes < 0) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "value of repeatTimes must be greater than 0", new Exception()); - } - - if (repeatTimes !== 0) { - _validateAndSet(_STATES.PLAYING, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED], function () { - _loopCount = repeatTimes; - _audio.play(); - }); - } - }, - - pause: function () { - _validateAndSet(_STATES.PAUSED, [_STATES.PLAYING], function () { - _audio.pause(); - }); - }, - - resume: function () { - _validateAndSet(_STATES.PLAYING, [_STATES.PAUSED], function () { - _audio.play(); - }); - }, - - stop: function () { - _validateAndSet(_STATES.STOPPED, [_STATES.PAUSED, _STATES.PLAYING], function () { - try { - _audio.pause(); - _audio.currentTime = 0; - } catch (e) { - //HACK: do nothing, this could throw a dom exception 11 sometimes when playing an mp3 or before the file has loaded. - //see http://developer.palm.com/distribution/viewtopic.php?f=11&t=7568 - } - }); - } -}; - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/CalendarItem.js b/lib/ripple/platform/wac/1.0/CalendarItem.js deleted file mode 100644 index 1bbb7f2c..00000000 --- a/lib/ripple/platform/wac/1.0/CalendarItem.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - db = require('ripple/db'), - exception = require('ripple/exception'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'); - -module.exports = function () { - this.calendarItemId = undefined; - this.alarmDate = undefined; - this.eventStartTime = undefined; - this.eventEndTime = undefined; - this.eventName = undefined; - this.eventNotes = undefined; - this.alarmed = undefined; - - this.update = function () { - var events = db.retrieveObject(constants.PIM.CALENDAR_LIST_KEY) || [], - that = this, - eventIndex = events.reduce(function (match, value, i) { - return value.calendarItemId === that.calendarItemId ? - i : match; - }, -1); - - - if (eventIndex >= 0) { - events[eventIndex] = this; - db.saveObject(constants.PIM.CALENDAR_LIST_KEY, events); - } - else { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "Calendar Item not found: " + (this.calendarItemId || ""), new Exception()); - } - }; -}; diff --git a/lib/ripple/platform/wac/1.0/CallRecord.js b/lib/ripple/platform/wac/1.0/CallRecord.js deleted file mode 100644 index c6372193..00000000 --- a/lib/ripple/platform/wac/1.0/CallRecord.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = function () { - this.callRecordType = undefined; - this.callRecordId = undefined; - this.callRecordAddress = undefined; - this.callRecordName = undefined; - this.durationSeconds = undefined; - this.startTime = undefined; -}; diff --git a/lib/ripple/platform/wac/1.0/CallRecordTypes.js b/lib/ripple/platform/wac/1.0/CallRecordTypes.js deleted file mode 100644 index e5d5bb26..00000000 --- a/lib/ripple/platform/wac/1.0/CallRecordTypes.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - RECEIVED: "received", - OUTGOING: "outgoing", - MISSED: "missed" -}; diff --git a/lib/ripple/platform/wac/1.0/Camera.js b/lib/ripple/platform/wac/1.0/Camera.js deleted file mode 100644 index 0fc6fa73..00000000 --- a/lib/ripple/platform/wac/1.0/Camera.js +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - constants = require('ripple/constants'), - _console = require('ripple/console'), - utils = require('ripple/utils'), - notifications = require('ripple/notifications'), - _currentlySet, - _img, - _buttons, - _self, - _videoCapture; - - -function _populateWindow(domObject) { - var record = document.createElement("button"), - pause = document.createElement("button"), - stop = document.createElement("button"); - - _img = document.createElement("img"); - _img.setAttribute("id", "jil-camera-window"); - _img.setAttribute("src", document.querySelector("#extension-url").innerHTML + constants.CAMERA.WINDOW_ANIMATION); - _img.setAttribute("width", "100%"); - _currentlySet = domObject; - domObject.appendChild(_img); - - _buttons = document.createElement("div"); - _buttons.setAttribute("id", "jil-camera-window-buttons"); - _buttons.setAttribute("style", "display: none"); - - record.setAttribute("id", "jil-camera-window-buttons-record"); - record.innerHTML = "Record"; - pause.setAttribute("id", "jil-camera-window-buttons-pause"); - pause.innerHTML = "Pause"; - stop.setAttribute("id", "jil-camera-window-buttons-stop"); - stop.innerHTML = "Stop"; - stop.addEventListener("click", _self.stopVideoCapture); - - _buttons.appendChild(record); - _buttons.appendChild(pause); - _buttons.appendChild(stop); - - domObject.appendChild(_buttons); - -} - -function _verifySetWindow(method) { - if (!_img) { - exception.raise(ExceptionTypes.UNKNOWN, "Camera." + - method + " was (most likely) called before using the setWindow method.", new Exception()); - } -} - -_self = { - onCameraCaptured: undefined, //function (fileName) { } - - captureImage: function (fileName, lowRes) { - utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "captureImage invalid number of parameters", new Exception()); - utils.validateMultipleArgumentTypes([fileName, lowRes], ['string', 'boolean'], ExceptionTypes.INVALID_PARAMETER, "invalid parameter type", new Exception()); - - _verifySetWindow("captureImage"); - var msg = constants.CAMERA.WARNING_TEXT; - msg = msg.replace("{file}", fileName); - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); - _console.log("simulated saved image as: " + fileName); - if (_self.onCameraCaptured) { - _self.onCameraCaptured.apply(_self, [fileName]); - } - - return fileName; - }, - setWindow: function (domObject) { - - if (_currentlySet) { - _currentlySet.removeChild(_img); - _currentlySet.removeChild(_buttons); - _currentlySet = null; - _img = null; - _buttons = null; - } - if (domObject !== null) { - _populateWindow(domObject); - } - }, - startVideoCapture: function (fileName, lowRes, maxDurationSeconds, showDefaultControls) { - _verifySetWindow("startVideoCapture"); - utils.validateNumberOfArguments(1, 4, arguments.length, ExceptionTypes.INVALID_PARAMETER, "startVideoCapture invalid number of parameters", new Exception()); - utils.validateMultipleArgumentTypes( - [fileName, lowRes, maxDurationSeconds, showDefaultControls], - ['string', 'boolean', 'integer', 'boolean'], - ExceptionTypes.INVALID_PARAMETER, - "invalid parameter type", new Exception()); - _console.log("started recording video"); - var interval = window.setTimeout(function () { - _self.stopVideoCapture(); - }, maxDurationSeconds * 1000); - - if (showDefaultControls) { - _buttons.removeAttribute("style"); - } - - _videoCapture = { - fileName: fileName, - stop: function () { - window.clearInterval(interval); - var msg = constants.CAMERA.WARNING_TEXT; - msg = msg.replace("{file}", fileName); - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); - if (_self.onCameraCaptured) { - _self.onCameraCaptured.apply(_self, [fileName]); - } - } - }; - - return fileName; - }, - stopVideoCapture: function () { - utils.validateNumberOfArguments(0, 0, arguments.length, ExceptionTypes.INVALID_PARAMETER, "stopVideoCapture invalid number of parameters", new Exception()); - if (_videoCapture) { - _console.log("simulated saving a video as: " + _videoCapture.fileName); - if (_buttons) { - _buttons.setAttribute("style", "display: none"); - } - _videoCapture.stop(); - _videoCapture = null; - } - } - -}; - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/Config.js b/lib/ripple/platform/wac/1.0/Config.js deleted file mode 100644 index 4b949efe..00000000 --- a/lib/ripple/platform/wac/1.0/Config.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - notifications = require('ripple/notifications'), - constants = require('ripple/constants'), - deviceSettings = require('ripple/deviceSettings'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - _self = { - ringtoneVolume: undefined, - msgRingtoneVolume: undefined, - vibrationSetting: undefined, - - setDefaultRingtone: function (ringtoneUrl) { - utils.validateArgumentType(ringtoneUrl, "string", ExceptionTypes.INVALID_PARAMETER, "ringtoneUrl paramter is not a string", new Exception()); - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, "Setting default ringtone to: " + ringtoneUrl); - }, - - setAsWallpaper: function (wallpaperUrl) { - utils.validateArgumentType(wallpaperUrl, "string", ExceptionTypes.INVALID_PARAMETER, "wallpaperUrl paramter is not a string", new Exception()); - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, "Setting wallpaper to: " + wallpaperUrl); - } - }; - -_self.__defineGetter__("ringtoneVolume", function () { - return deviceSettings.retrieve("Config.ringtoneVolume"); -}); - -_self.__defineGetter__("msgRingtoneVolume", function () { - return deviceSettings.retrieve("Config.msgRingtoneVolume"); -}); - -_self.__defineGetter__("vibrationSetting", function () { - return deviceSettings.retrieve("Config.vibrationSetting"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/DataNetworkConnectionTypes.js b/lib/ripple/platform/wac/1.0/DataNetworkConnectionTypes.js deleted file mode 100644 index 1ff87a56..00000000 --- a/lib/ripple/platform/wac/1.0/DataNetworkConnectionTypes.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - _self = { - "BLUETOOTH": undefined, - "EDGE": undefined, - "EVDO": undefined, - "GPRS": undefined, - "IRDA": undefined, - "LTE": undefined, - "ONEXRTT": undefined, - "WIFI": undefined - }; - -utils.forEach(_self, function (value, property) { - _self.__defineGetter__(property, function () { - return property; - }); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/DataNetworkInfo.js b/lib/ripple/platform/wac/1.0/DataNetworkInfo.js deleted file mode 100644 index cf86d0be..00000000 --- a/lib/ripple/platform/wac/1.0/DataNetworkInfo.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var event = require('ripple/event'), - utils = require('ripple/utils'), - _console = require('ripple/console'), - deviceSettings = require('ripple/deviceSettings'), - DataNetworkConnectionTypes = require('ripple/platform/wac/1.0/DataNetworkConnectionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - -_self = { - isDataNetworkConnected: undefined, - networkConnectionType: undefined, - onNetworkConnectionChanged: undefined, - - getNetworkConnectionName: function (networkConnectionType) { - var foundConnectionType; - utils.validateArgumentType(networkConnectionType, "string", ExceptionTypes.INVALID_PARAMETER, "networkConnectionType is invalid, expected a string", new Exception()); - foundConnectionType = DataNetworkConnectionTypes[networkConnectionType.toUpperCase()]; - return foundConnectionType || null; - } -}; - -event.on("DataNetworkConnectionChanged", function (newConnectionName) { - var callback = _self.onNetworkConnectionChanged, - msg = "Fired onNetworkConnectionChanged with newConnectionName: " + newConnectionName; - - if (callback && typeof callback === "function") { - callback.apply(null, [newConnectionName]); - } - else { - msg += " --> BUT there was no registered callback found."; - } - - _console.log(msg); -}); - -_self.__defineGetter__("isDataNetworkConnected", function () { - return deviceSettings.retrieveAsBoolean("DataNetworkInfo.isDataNetworkConnected"); -}); - -_self.__defineGetter__("networkConnectionType", function () { - var value = deviceSettings.retrieve("DataNetworkInfo.networkConnectionType"); - return value instanceof Array ? value : [value]; -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/Device.js b/lib/ripple/platform/wac/1.0/Device.js deleted file mode 100644 index da16c3c5..00000000 --- a/lib/ripple/platform/wac/1.0/Device.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - exception = require('ripple/exception'), - _console = require('ripple/console'), - utils = require('ripple/utils'), - notifications = require('ripple/notifications'), - ApplicationTypes = require('ripple/platform/wac/1.0/ApplicationTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - _applicationTypes = { - FILES: "FILES", - MEDIAPLAYER: "MEDIAPLAYER", - PHONECALL: "PHONECALL", - PICTURES: "PICTURES" - }, - _self; - -function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); -} - -_self = { - // Properties - clipboardString: undefined, - widgetEngineName: undefined, - widgetEngineProvider: undefined, - widgetEngineVersion: undefined, - - // Methods - getAvailableApplications: function () { - return constants.PLATFORMS.WAC.APPLICATIONS || []; - }, - - getDirectoryFileNames: function () { - _throwUnsupportedException("Device.getDirectoryFileNames"); - }, - getFile: function () { - _throwUnsupportedException("Device.getFile"); - }, - - launchApplication: function launchApplication(application, startParameter) { - if (!application || typeof(application) !== "string") { - exception.raise(ExceptionTypes.INVALID_PARAMETER, - "Invalid argument 'application' at Device.launchApplication(): expected to be of type 'string' but was of type: " + (application ? typeof(application) : "null"), - Exception); - } - - if (startParameter && typeof(startParameter) !== "string") { - exception.raise(ExceptionTypes.INVALID_PARAMETER, - "Invalid argument 'startParameter' at Device.launchApplication(): expected to be 'string' but was : " + typeof(startParameter), - Exception); - } - - // rudimentary implementation for now - var message = "The widget has requested application: '" + application + "' to be launched. \n\n"; - - if (startParameter) { - message += "The following start parameter was sent in: " + startParameter + "\n\n"; - } - - if (_applicationTypes[application] && !startParameter) { - message += "Launching this application can also be done with an optional startParameter which was not provided" + "\n\n"; - } - - if (!ApplicationTypes[application]) { - message += "Note: the application requested is not part of the common values specified by the WAC API."; - } - - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, message); - _console.log(message); - }, - - copyFile: function () { - _throwUnsupportedException("Device.copyFile"); - }, - deleteFile: function () { - _throwUnsupportedException("Device.deleteFile"); - }, - findFiles: function () { - _throwUnsupportedException("Device.findFiles"); - }, - getFileSystemRoots: function () { - _throwUnsupportedException("Device.getFileSystemRoots"); - }, - getFileSystemSize: function () { - _throwUnsupportedException("Device.getFileSystemSize"); - }, - moveFile: function () { - _throwUnsupportedException("Device.moveFile"); - }, - onFilesFound: function () { - _throwUnsupportedException("Device.onFilesFound"); - }, - setRingtone: function () { - _throwUnsupportedException("Device.setRingtone"); - }, - - vibrate: function (duration) { - utils.validateArgumentType(duration, "number", ExceptionTypes.INVALID_PARAMETER, "duration paramter is not a number", new Exception()); - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, "Vibrating for " + duration + " second(s)."); - } - -}; - -_self.__defineGetter__("widgetEngineName", function () { - return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_NAME; -}); - -_self.__defineGetter__("widgetEngineProvider", function () { - return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_PROVIDER; -}); - -_self.__defineGetter__("widgetEngineVersion", function () { - return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_VERSION; -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/DeviceInfo.js b/lib/ripple/platform/wac/1.0/DeviceInfo.js deleted file mode 100644 index 63878bb3..00000000 --- a/lib/ripple/platform/wac/1.0/DeviceInfo.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - deviceSettings = require('ripple/deviceSettings'), - platform = require('ripple/platform'), - devices = require('ripple/devices'), - _self; - -_self = { - ownerInfo: undefined, // return AddressBookItem - phoneColorDepthDefault: undefined, - phoneFirmware: undefined, - phoneManufacturer: undefined, - phoneModel: undefined, - phoneOS: undefined, - phoneSoftware: undefined, - phoneScreenHeightDefault: undefined, - phoneScreenWidthDefault: undefined, - totalMemory: undefined -}; - -function _getDeviceAttribute(attr) { - var devicePointer = devices.getCurrentDevice(); - utils.forEach(attr.split("."), function (dot) { - devicePointer = devicePointer[dot]; - }); - return devicePointer; -} - -_self.__defineGetter__("phoneColorDepthDefault", function () { - return deviceSettings.retrieveAsInt("DeviceInfo.phoneColorDepthDefault"); -}); - -_self.__defineGetter__("phoneFirmware", function () { - return _getDeviceAttribute("firmware"); -}); - -_self.__defineGetter__("phoneManufacturer", function () { - return _getDeviceAttribute("manufacturer"); -}); - -_self.__defineGetter__("phoneOS", function () { - return _getDeviceAttribute("osName") + " " + _getDeviceAttribute("osVersion"); -}); - -_self.__defineGetter__("phoneModel", function () { - return _getDeviceAttribute("model"); -}); - -_self.__defineGetter__("phoneSoftware", function () { - return _getDeviceAttribute("osVersion"); -}); - -_self.__defineGetter__("phoneScreenHeightDefault", function () { - return _getDeviceAttribute("screen.height"); -}); - -_self.__defineGetter__("phoneScreenWidthDefault", function () { - return _getDeviceAttribute("screen.width"); -}); - -_self.__defineGetter__("totalMemory", function () { - return deviceSettings.retrieveAsInt("DeviceInfo.totalMemory"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/DeviceStateInfo.js b/lib/ripple/platform/wac/1.0/DeviceStateInfo.js deleted file mode 100644 index 36a3b533..00000000 --- a/lib/ripple/platform/wac/1.0/DeviceStateInfo.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - exception = require('ripple/exception'), - _console = require('ripple/console'), - geo = require('ripple/geo'), - event = require('ripple/event'), - deviceSettings = require('ripple/deviceSettings'), - PositionInfo = require('ripple/platform/wac/1.0/PositionInfo'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - _self; - -event.on("ScreenChangeDimensions", function (width, height) { - try { - if (typeof _self.onScreenChangeDimensions === 'function') { - _self.onScreenChangeDimensions(width, height); - } - _console.log("called DeviceStateInfo.onScreenChangeDimensions callback function with width = " + width + " and height = " + height); - } catch (e) { - exception.handle(e, false); - } -}); - -_self = { - availableMemory: undefined, - language: undefined, - keypadLightOn: undefined, - backLightOn: undefined, - processorUtilizationPercent: undefined, - audioPath: undefined, - - onPositionRetrieved: undefined, - - requestPositionInfo: function (method) { - utils.validateNumberOfArguments(1, 1, arguments.length, - ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid number of parameters", new Exception()); - utils.validateArgumentType(method, "string", - ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid parameter", new Exception()); - - if (!(method.match(/gps|agps|cellid/))) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, - "Invalid method, expected (gps, agps or cellid)", Exception); - } - - if (typeof _self.onPositionRetrieved === "function") { - var delay = geo.delay * 1000, - timeout = geo.timeout; - setTimeout(function () { - var pos = PositionInfo, - errorObj = {}; - - if (timeout) { - //create - utils.forEach(pos, function (val, key) { - errorObj[key] = undefined; - }); - pos = errorObj; - } - _self.onPositionRetrieved(pos, method); - }, delay); - } - }, - - onScreenChangeDimensions: undefined, - - onFlipEvent: undefined -}; - -_self.__defineGetter__("availableMemory", function () { - return deviceSettings.retrieveAsInt("DeviceStateInfo.availableMemory"); -}); - -_self.__defineGetter__("language", function () { - return deviceSettings.retrieve("DeviceStateInfo.language"); -}); - -_self.__defineGetter__("keypadLightOn", function () { - return deviceSettings.retrieveAsBoolean("DeviceStateInfo.keypadLightOn"); -}); - -_self.__defineGetter__("backLightOn", function () { - return deviceSettings.retrieveAsBoolean("DeviceStateInfo.backLightOn"); -}); - -_self.__defineGetter__("audioPath", function () { - return deviceSettings.retrieve("DeviceStateInfo.audioPath"); -}); - -_self.__defineGetter__("processorUtilizationPercent", function () { - return deviceSettings.retrieve("DeviceStateInfo.processorUtilizationPercent"); -}); - -module.exports = _self; - diff --git a/lib/ripple/platform/wac/1.0/EventRecurrenceTypes.js b/lib/ripple/platform/wac/1.0/EventRecurrenceTypes.js deleted file mode 100644 index 63217635..00000000 --- a/lib/ripple/platform/wac/1.0/EventRecurrenceTypes.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - NOT_REPEAT: "NOT_REPEAT", - DAILY: "DAILY", - EVERY_WEEKDAY: "EVERY_WEEKDAY", - WEEKLY_ON_DAY: "WEEKLY_ON_DAY", - MONTHLY_ON_DAY: "MONTHLY_ON_DAY", - MONTHLY_ON_DAY_COUNT: "MONTHLY_ON_DAY_COUNT", - YEARLY: "YEARLY" -}; diff --git a/lib/ripple/platform/wac/1.0/Exception.js b/lib/ripple/platform/wac/1.0/Exception.js deleted file mode 100644 index d0099b7c..00000000 --- a/lib/ripple/platform/wac/1.0/Exception.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = function () { - this.message = ""; - this.type = ""; - - this.toString = function () { - var result = this.type + ': "' + this.message + '"'; - - if (this.stack) { - result += "\n" + this.stack; - } - return result; - }; -}; diff --git a/lib/ripple/platform/wac/1.0/ExceptionTypes.js b/lib/ripple/platform/wac/1.0/ExceptionTypes.js deleted file mode 100644 index 559be66c..00000000 --- a/lib/ripple/platform/wac/1.0/ExceptionTypes.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self = {}; - -_self.__defineGetter__("INVALID_PARAMETER", function () { - return "invalid_parameter"; -}); - -_self.__defineGetter__("SECURITY", function () { - return "security"; -}); - -_self.__defineGetter__("UNKNOWN", function () { - return "unknown"; -}); - -_self.__defineGetter__("UNSUPPORTED", function () { - return "unsupported"; -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/File.js b/lib/ripple/platform/wac/1.0/File.js deleted file mode 100644 index af095d21..00000000 --- a/lib/ripple/platform/wac/1.0/File.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.expots = function () { - this.createDate = undefined; - this.fileName = undefined; - this.filePath = undefined; - this.fileSize = undefined; - this.isDirectory = undefined; - this.lastModifyDate = undefined; -}; diff --git a/lib/ripple/platform/wac/1.0/Message.js b/lib/ripple/platform/wac/1.0/Message.js deleted file mode 100644 index 629de8d8..00000000 --- a/lib/ripple/platform/wac/1.0/Message.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'), - Attachment = require('ripple/platform/wac/1.0/Attachment'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'); - -function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); -} - -module.exports = function () { - this.messageId = Math.uuid(undefined, 16); - this.callbackNumber = undefined; - this.destinationAddress = []; - this.isRead = undefined; - this.messagePriority = undefined; - this.messageType = undefined; - this.subject = undefined; - this.body = undefined; - this.sourceAddress = undefined; - this.validityPeriodHours = undefined; - this.time = undefined; - this.ccAddress = []; - this.bccAddress = []; - this.attachments = []; - - this.addAttachment = function (fileFullName) { - var attachment = new Attachment(); - attachment.fileName = fileFullName; - this.attachments.push(attachment); - }; - this.deleteAttachment = function (attachment) { - - for (var i = this.attachments.length - 1; i >= 0; i--) { - if (this.attachments[i].fileName === attachment.fileName) { - this.attachments.splice(i, 1); - } - } - }; - this.saveAttachment = function (fileFullName, attachment) { - _throwUnsupportedException("Widget.Messaging.Message.addAddress"); - }; - this.addAddress = function (type, address) { - - var addresses = address.split(";"); - - switch (type) { - case "destination": - this.destinationAddress = this.destinationAddress.concat(addresses); - break; - case "cc": - this.ccAddress = this.ccAddress.concat(addresses); - break; - case "bcc": - this.bccAddress = this.bccAddress.concat(addresses); - break; - } - }; - - this.deleteAddress = function (type, address) { - var addresses = address.split(";"), - filter = function (orig) { - return orig.filter(function (address) { - return !addresses.some(function (x) { - return address === x; - }); - }); - }; - - switch (type) { - case "destination": - this.destinationAddress = filter(this.destinationAddress); - break; - case "cc": - this.ccAddress = filter(this.ccAddress); - break; - case "bcc": - this.bccAddress = filter(this.bccAddress); - break; - } - }; - -}; diff --git a/lib/ripple/platform/wac/1.0/MessageFolderTypes.js b/lib/ripple/platform/wac/1.0/MessageFolderTypes.js deleted file mode 100644 index b3430384..00000000 --- a/lib/ripple/platform/wac/1.0/MessageFolderTypes.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - DRAFTS: "drafts", - INBOX: "inbox", - OUTBOX: "outbox", - SENTBOX: "sentbox" -}; diff --git a/lib/ripple/platform/wac/1.0/MessageQuantities.js b/lib/ripple/platform/wac/1.0/MessageQuantities.js deleted file mode 100644 index 9bd1bb3c..00000000 --- a/lib/ripple/platform/wac/1.0/MessageQuantities.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - totalMessageCnt: undefined, - totalMessageReadCnt: undefined, - totalMessageUnreadCnt: undefined -}; diff --git a/lib/ripple/platform/wac/1.0/MessageTypes.js b/lib/ripple/platform/wac/1.0/MessageTypes.js deleted file mode 100644 index 27caccb9..00000000 --- a/lib/ripple/platform/wac/1.0/MessageTypes.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - EmailMessage: "email", - MMSMessage: "mms", - SMSMessage: "sms" -}; diff --git a/lib/ripple/platform/wac/1.0/Messaging.js b/lib/ripple/platform/wac/1.0/Messaging.js deleted file mode 100644 index 6daa5d97..00000000 --- a/lib/ripple/platform/wac/1.0/Messaging.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'), - utils = require('ripple/utils'), - constants = require('ripple/constants'), - notifications = require('ripple/notifications'), - _console = require('ripple/console'), - Message = require('ripple/platform/wac/1.0/Message'), - MessageTypes = require('ripple/platform/wac/1.0/MessageTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'); - -function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); -} - -module.exports = { - onMessageArrived: undefined, - onMessageSendingFailure: undefined, - onMessagesFound: undefined, - - createMessage: function (messageType) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "createMessage invalid number of arguments", new Exception()); - utils.validateArgumentType(messageType, "string", ExceptionTypes.INVALID_PARAMETER, "createMessage invalid arguments", new Exception()); - - if (!utils.some(MessageTypes, function (value) { - return value === messageType; - })) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "createMessage invalid arguments", new Exception()); - } - - var message = new Message(); - message.messageType = messageType; - - return message; - }, - deleteMessage: function () { - _throwUnsupportedException("Messaging.deleteMessage"); - }, - getMessage: function () { - _throwUnsupportedException("Messaging.getMessage"); - }, - getMessageQuantities: function () { - _throwUnsupportedException("Messaging.getMessageQuantities"); - }, - sendMessage: function (msg) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.UNSUPPORTED, "sendMessage invalid number of arguments", new Exception()); - if (msg instanceof Message === false) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "expected a valid Message object", new Exception()); - } - - //TODO: Must be modded to fail and to then call the onMessageSendingFailure callback - var message = "Sent " + msg.messageType + " " + msg.messageId + " to " + msg.destinationAddress; - - // insert fail check here - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, message); - _console.log(message); - }, - moveMessageToFolder: function () { - _throwUnsupportedException("Messaging.moveMessageToFolder"); - }, - copyMessageToFolder: function () { - _throwUnsupportedException("Messaging.copyMessageToFolder"); - }, - createFolder: function () { - _throwUnsupportedException("Messaging.createFolder"); - }, - deleteFolder: function () { - _throwUnsupportedException("Messaging.deleteFolder"); - }, - getFolderNames: function () { - _throwUnsupportedException("Messaging.getFolderNames"); - }, - findMessages: function () { - _throwUnsupportedException("Messaging.findMessages"); - }, - getCurrentEmailAccount: function () { - _throwUnsupportedException("Messaging.getCurrentEmailAccount"); - }, - getEmailAccounts: function () { - _throwUnsupportedException("Messaging.getEmailAccounts"); - }, - setCurrentEmailAccount: function () { - _throwUnsupportedException("Messaging.setCurrentEmailAccount"); - }, - deleteEmailAccount: function () { - _throwUnsupportedException("Messaging.deleteEmailAccount"); - } - -}; diff --git a/lib/ripple/platform/wac/1.0/Multimedia.js b/lib/ripple/platform/wac/1.0/Multimedia.js deleted file mode 100644 index d247e008..00000000 --- a/lib/ripple/platform/wac/1.0/Multimedia.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var event = require('ripple/event'), - VideoPlayer = require('ripple/platform/wac/1.0/VideoPlayer'), - AudioPlayer = require('ripple/platform/wac/1.0/AudioPlayer'), - constants = require('ripple/constants'), - _volume = 5, - _audioState, - _videoState, - _self; - -event.on("MultimediaVolumeChanged", function updateVolume(volume) { - _volume = volume; -}); - -event.on("MultimediaAudioStateChanged", function updateAudioState(state) { - _audioState = state; -}); - -event.on("MultimediaVideoStateChanged", function updateVideoState(state) { - _videoState = state; -}); - -_self = { - - isAudioPlaying: undefined, - isVideoPlaying: undefined, - - getVolume: function () { - return _volume; - }, - - stopAll: function () { - VideoPlayer.stop(); - AudioPlayer.stop(); - } -}; - -_self.__defineGetter__("isAudioPlaying", function () { - return _audioState === constants.MULTIMEDIA.AUDIO_STATES.PLAYING; -}); - -_self.__defineGetter__("isVideoPlaying", function () { - return _videoState === "playing"; -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/PIM.js b/lib/ripple/platform/wac/1.0/PIM.js deleted file mode 100644 index 5bcd076d..00000000 --- a/lib/ripple/platform/wac/1.0/PIM.js +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - exception = require('ripple/exception'), - Exception = require('ripple/platform/wac/1.0/Exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - AddressBookItem = require('ripple/platform/wac/1.0/AddressBookItem'), - CalendarItem = require('ripple/platform/wac/1.0/CalendarItem'), - utils = require('ripple/utils'), - db = require('ripple/db'), - constants = require('ripple/constants'); - -function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); -} - -function _toAddressBookItem(contact) { - if (!contact) { - return null; - } - - var addressBookItem = new AddressBookItem(); - - utils.forEach(contact, function (prop, key) { - addressBookItem[key] = contact[key]; - }); - - return addressBookItem; -} - -function _toCalendarItem(item) { - if (!item) { - return null; - } - - var calendarItem = new CalendarItem(); - - utils.forEach(item, function (prop, key) { - calendarItem[key] = item[key]; - }); - - return calendarItem; -} - -function _getData(type) { - var data = db.retrieveObject(type) || []; - return data; -} - -function _saveData(type, items) { - db.saveObject(type, items); -} - -function _getContacts() { - var contacts = _getData(constants.PIM.ADDRESS_LIST_KEY), - gord, - dan, - brent, - pj, - mark; - - if (contacts.length === 0) { - - gord = new AddressBookItem(); - gord.addressBookItemId = "0"; - gord.fullName = "Gord Tanner"; - gord.eMail = "gord@tinyHippos.com"; - gord.company = "tinyHippos Inc"; - gord.title = "Code Poet"; - gord.address = "121 Charles Street W, Kitchener, Ontario, Canada"; - - dan = new AddressBookItem(); - dan.addressBookItemId = "1"; - dan.fullName = "Dan Silivestru"; - dan.eMail = "dan@tinyHippos.com"; - dan.company = "tinyHippos Inc"; - dan.title = "Co-Founder And Chief Technology Officer"; - dan.address = "121 Charles Street W, Kitchener, Ontario, Canada"; - - pj = new AddressBookItem(); - pj.addressBookItemId = "2"; - pj.fullName = "PJ Lowe"; - pj.eMail = "pj@tinyHippos.com"; - pj.company = "tinyHippos Inc"; - pj.title = "Co-Founder And Chief Operations Officer"; - pj.address = "121 Charles Street W, Kitchener, Ontario, Canada"; - - brent = new AddressBookItem(); - brent.addressBookItemId = "2"; - brent.fullName = "Brent Lintner"; - brent.eMail = "brent@tinyHippos.com"; - brent.company = "tinyHippos Inc"; - brent.title = "Co-Founder And Chief Operations Officer"; - brent.address = "121 Charles Street W, Kitchener, Ontario, Canada"; - - mark = new AddressBookItem(); - mark.addressBookItemId = "3"; - mark.fullName = "Mark McArdle"; - mark.eMail = "mark@tinyHippos.com"; - mark.company = "tinyHippos Inc"; - mark.title = "Chief Executive Officer"; - mark.address = "121 Charles Street W, Kitchener, Ontario, Canada"; - - contacts.push(gord); - contacts.push(dan); - contacts.push(pj); - contacts.push(brent); - contacts.push(mark); - - _saveData(constants.PIM.ADDRESS_LIST_KEY, contacts); - } - return contacts.map(_toAddressBookItem); -} - -function _getEvents() { - var events = _getData(constants.PIM.CALENDAR_LIST_KEY); - return events.map(_toCalendarItem); -} - -function _get(type, id, fetchIDFunc) { - var items = _getData(type); - return items.reduceRight(function (match, item) { - return fetchIDFunc(item) === id ? item : match; - }, null); -} - -function _getAddressBookID(item) { - return item.addressBookItemId; -} - -function _getCalendarID(item) { - return item.calendarItemId; -} - -function _getContact(id) { - return _toAddressBookItem(_get(constants.PIM.ADDRESS_LIST_KEY, id, _getAddressBookID)); -} - -function _getEvent(id) { - return _toCalendarItem(_get(constants.PIM.CALENDAR_LIST_KEY, id, _getCalendarID)); -} - -function _add(type, item, idProp) { - var items = _getData(type); - - if (!item[idProp]) { - item[idProp] = Math.uuid(undefined, 16); - } - - items.push(item); - _saveData(type, items); -} - -function _delete(type, id, fetchIDFunc) { - var items = _getData(type); - - _saveData(type, items.filter(function (item) { - return fetchIDFunc(item) !== id; - })); -} - -function _validateArgs(min, max, len) { - utils.validateNumberOfArguments(min, max, len, - ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception()); -} - -function _validateType(arg, argType) { - utils.validateArgumentType(arg, argType, - ExceptionTypes.INVALID_PARAMETER, "argument of wrong type provided", - new Exception()); -} - -function _validateAddressBookItem(item) { - if ((item instanceof AddressBookItem) === false) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "invalid contact, not instance of AddressBookItem.", new Exception()); - } -} - -_self = { - addAddressBookItem: function (contact) { - _validateArgs(1, 1, arguments.length); - _validateAddressBookItem(contact); - - _add(constants.PIM.ADDRESS_LIST_KEY, contact, "addressBookItemId"); - }, - createAddressBookGroup: function (groupName) { - _throwUnsupportedException("Widget.PIM.createAddressBookGroup"); - }, - createAddressBookItem: function () { - return new AddressBookItem(); - }, - deleteAddressBookItem: function (contactid) { - _validateArgs(1, 1, arguments.length); - _validateType(contactid, "string"); - _delete(constants.PIM.ADDRESS_LIST_KEY, contactid, _getAddressBookID); - }, - deleteAddressBookGroup: function (groupName) { - _throwUnsupportedException("Widget.PIM.deleteAddressBookGroup"); - }, - getAddressBookItem: function (contactid) { - _validateArgs(1, 1, arguments.length); - _validateType(contactid, "string"); - return _getContact(contactid); - }, - getAddressBookItemsCount: function () { - _validateArgs(0, 0, arguments.length); - var items = _getContacts(); - return items.length; - }, - getAvailableAddressGroupNames: function () { - _throwUnsupportedException("Widget.PIM.getAvailableAddressGroupNames"); - }, - getAddressBookGroupMembers: function (groupName) { - _throwUnsupportedException("Widget.PIM.getAddressBookGroupMembers"); - }, - findAddressBookItems: function (comparisonContact, startInx, endInx) { - _validateArgs(3, 3, arguments.length); - utils.validateMultipleArgumentTypes([comparisonContact, startInx, endInx], ["object", "number", "number"], ExceptionTypes.INVALID_PARAMETER, "argument of wrong type provided", - new Exception()); - - if (endInx < 0) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception()); - } - - startInx = startInx < 0 ? 0 : startInx; - - var contacts = _getContacts(); - utils.find(comparisonContact, contacts, startInx, endInx, _self.onAddressBookItemsFound); - }, - - addCalendarItem: function (calendarItem) { - _validateArgs(1, 1, arguments.length); - _add(constants.PIM.CALENDAR_LIST_KEY, calendarItem, "calendarItemId"); - }, - deleteCalendarItem: function (calendarId) { - _validateArgs(1, 1, arguments.length); - _delete(constants.PIM.CALENDAR_LIST_KEY, calendarId, _getCalendarID); - }, - getCalendarItem: function (calendarId) { - _validateArgs(1, 1, arguments.length); - return _getEvent(calendarId); - }, - findCalendarItems: function (itemToMatch, startInx, endInx) { - _validateArgs(1, 3, arguments.length); - var events = _getEvents(); - utils.find(itemToMatch, events, startInx, endInx, _self.onCalendarItemsFound); - }, - getCalendarItems: function (startTime, endTime) { - var events = _getEvents(); - - return events.reduce(function (matches, event) { - if (event.eventStartTime >= startTime && event.eventStartTime <= endTime) { - matches.push(event); - } - return matches; - }, []); - }, - exportAsVCard: function (addressBookItems) { - _throwUnsupportedException("Widget.PIM.exportAsVCard"); - }, - - onAddressBookItemsFound: undefined, // function (addressBookItemsFound) { } - onCalendarItemsFound: undefined, // function (calendarItemsFound) { } - onCalendarItemAlert: undefined, // function (calendarItem) { } - onVCardExportingFinish: undefined // function (vCardFilePath) { } -}; - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/PositionInfo.js b/lib/ripple/platform/wac/1.0/PositionInfo.js deleted file mode 100644 index 9cf3697f..00000000 --- a/lib/ripple/platform/wac/1.0/PositionInfo.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var geo = require('ripple/geo'), - event = require('ripple/event'), - exception = require('ripple/exception'), - utils = require('ripple/utils'), - _self = { - latitude: undefined, - longitude: undefined, - altitude: undefined, - cellID: undefined, - accuracy: undefined, - altitudeAccuracy: undefined, - timeStamp: undefined - }; - -utils.forEach(_self, function (value, property) { - _self.__defineGetter__(property, function () { - return geo.getPositionInfo()[property]; - }); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/PowerInfo.js b/lib/ripple/platform/wac/1.0/PowerInfo.js deleted file mode 100644 index d2dfa857..00000000 --- a/lib/ripple/platform/wac/1.0/PowerInfo.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - event = require('ripple/event'), - _console = require('ripple/console'), - deviceSettings = require('ripple/deviceSettings'), - _lastPercentRemaining; - -_self = { - isCharging: undefined, - percentRemaining: undefined, - - onChargeStateChange: undefined, - onLowBattery: undefined, - onChargeLevelChange: undefined -}; - -function _getCurrentChargeState(percentRemaining, isCharging) { - var batteryState; - if (percentRemaining === 100 && isCharging) { - batteryState = "full"; - } - else if (!isCharging) { - batteryState = "discharging"; - } - else { - batteryState = "charging"; - } - return batteryState; -} - -event.on("DeviceBatteryStateChanged", function (isCharging) { - var callback = _self.onChargeStateChange, - msg = "", - batteryLevel = _self.percentRemaining, - batteryState; - - batteryState = _getCurrentChargeState(batteryLevel, isCharging); - - msg += "Fired onChargeStateChange with batteryState: " + batteryState; - - if (callback && typeof callback === "function") { - callback.apply(null, [batteryState]); - } - else { - msg += " --> BUT there was no registered callback found."; - } - - _console.log(msg); -}); - -event.on("DeviceBatteryLevelChanged", function (percentRemaining) { - - var callback = _self.onChargeLevelChange, - lowBatteryCallback = _self.onLowBattery, - msg = "Fired onChargeLevelChange with percentRemaining: " + percentRemaining; - - // blah, stupid Options returning strings - percentRemaining = parseInt(percentRemaining, 10); - - if (callback && typeof callback === "function") { - callback.apply(null, [percentRemaining]); - } - else { - msg += " --> BUT there was no registered callback found."; - } - - _console.log(msg); - - if (percentRemaining <= 10) { - - msg = "Fired onLowBattery with percentRemaining: " + percentRemaining; - - if (lowBatteryCallback && typeof lowBatteryCallback === "function") { - lowBatteryCallback.apply(null, [percentRemaining]); - } - else { - msg += " --> BUT there was no registered callback found."; - } - - _console.log(msg); - } - - if (percentRemaining === 100 || (percentRemaining < 100 && _lastPercentRemaining === 100)) { - event.trigger("DeviceBatteryStateChanged", [_self.isCharging]); - } - - _lastPercentRemaining = percentRemaining; - -}); - -_self.__defineGetter__("isCharging", function () { - return deviceSettings.retrieveAsBoolean("PowerInfo.isCharging"); -}); - -_self.__defineGetter__("percentRemaining", function () { - return deviceSettings.retrieveAsInt("PowerInfo.percentRemaining"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/RadioInfo.js b/lib/ripple/platform/wac/1.0/RadioInfo.js deleted file mode 100644 index 396f7adb..00000000 --- a/lib/ripple/platform/wac/1.0/RadioInfo.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - event = require('ripple/event'), - _console = require('ripple/console'), - deviceSettings = require('ripple/deviceSettings'); - -_self = { - isRoaming: undefined, - radioSignalStrengthPercent: undefined, - isRadioEnabled: undefined, - radioSignalSource: undefined, - onSignalSourceChange: undefined -}; - -event.on("RadioSignalSourceChanged", function () { - var callback = _self.onSignalSourceChange, - isRoaming = _self.isRoaming, - signalSource = _self.radioSignalSource, - msg = "Fired onSignalSourceChange. signalSource: " + signalSource + ", isRoaming: " + isRoaming; - - if (callback && typeof callback === "function") { - callback.apply(null, [signalSource, isRoaming]); - } - else { - msg += " --> BUT there was no registered callback found."; - } - - _console.log(msg); -}); - -_self.__defineGetter__("radioSignalSource", function () { - return deviceSettings.retrieve("RadioInfo.radioSignalSource"); -}); - -_self.__defineGetter__("isRoaming", function () { - return deviceSettings.retrieveAsBoolean("RadioInfo.isRoaming"); -}); - -_self.__defineGetter__("isRadioEnabled", function () { - return deviceSettings.retrieveAsBoolean("RadioInfo.isRadioEnabled"); -}); - -_self.__defineGetter__("radioSignalStrengthPercent", function () { - return deviceSettings.retrieveAsInt("RadioInfo.radioSignalStrengthPercent"); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/RadioSignalSourceTypes.js b/lib/ripple/platform/wac/1.0/RadioSignalSourceTypes.js deleted file mode 100644 index e56ae67f..00000000 --- a/lib/ripple/platform/wac/1.0/RadioSignalSourceTypes.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - utils = require('ripple/utils'); - -_self = { - "CDMA": undefined, - "GSM": undefined, - "LTE": undefined, - "TDSCDMA": undefined, - "WCDMA": undefined -}; - -utils.forEach(_self, function (value, property) { - _self.__defineGetter__(property, function () { - return property; - }); -}); - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/Telephony.js b/lib/ripple/platform/wac/1.0/Telephony.js deleted file mode 100644 index d3b366d1..00000000 --- a/lib/ripple/platform/wac/1.0/Telephony.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - exception = require('ripple/exception'), - utils = require('ripple/utils'), - db = require('ripple/db'), - constants = require('ripple/constants'), - Device = require('ripple/platform/wac/1.0/Device'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'); - - -function _throwUnsupportedException(method) { - exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception()); -} - -_self = { - - // Public Callbacks - onCallEvent: undefined,// function (callType, phoneNumber) { }, - onCallRecordsFound: undefined,// function (callRecords) { }; - - // Public Methods - initiateVoiceCall: function (phoneNumber) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "initiateVoiceCall invalid number of parameters", new Exception()); - //HACK: should this be hardcoded? - //I am still not even sure this is the correct behaviour - Device.launchApplication("PHONECALL", phoneNumber); - - if (_self.onCallEvent) { - //HACK: shouldn't be hardcoded - //also what should the context be? isn't spec'ed - _self.onCallEvent.apply(_self, ["outgoing", phoneNumber]); - } - }, - getCallRecordCnt: function (callRecordType) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "getCallRecordCnt invalid number of parameters", new Exception()); - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY); - - return utils.sum(calls, function (call) { - return call.callRecordType === callRecordType; - }); - }, - getCallRecord: function (callRecordType, id) { - utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "getCallRecord invalid number of parameters", new Exception()); - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY); - - return utils.map(calls, function (call) { - return call.callRecordType === callRecordType ? call : null; - }).reduce(function (match, call) { - return match || call.callRecordId === id || null; - }, null); - }, - deleteCallRecord: function (callRecordType, id) { - utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "deleteCallRecord invalid number of parameters", new Exception()); - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY), - indexToDelete = calls.reduce(function (result, call, index) { - return call.callRecordType === callRecordType && - call.callRecordId === id ? index : result; - }, -1); - - if (indexToDelete >= 0) { - calls.splice(indexToDelete, 1); - db.saveObject(constants.TELEPHONY.CALL_LIST_KEY, calls); - } - - }, - - deleteAllCallRecords: function (callRecordType) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "deleteAllCallRecords invalid number of parameters", new Exception()); - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY), - indexesToDelete = calls.reduce(function (result, call, index) { - if (call.callRecordType === callRecordType) { - result.push(index); - } - return result; - }, []); - - utils.forEach(indexesToDelete, function (index) { - calls.splice(index, 1); - }); - - if (indexesToDelete.length > 0) { - db.saveObject(constants.TELEPHONY.CALL_LIST_KEY, calls); - } - - }, - - findCallRecords: function (comparisonRecord, startInx, endInx) { - utils.validateNumberOfArguments(1, 3, arguments.length, ExceptionTypes.INVALID_PARAMETER, "findCallRecords invalid number of parameters", new Exception()); - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY); - utils.find(comparisonRecord, calls, startInx, endInx, _self.onCallRecordsFound); - - } - -}; - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/VideoPlayer.js b/lib/ripple/platform/wac/1.0/VideoPlayer.js deleted file mode 100644 index c740847c..00000000 --- a/lib/ripple/platform/wac/1.0/VideoPlayer.js +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _self, - _console = require('ripple/console'), - event = require('ripple/event'), - utils = require('ripple/utils'), - fileSystem = require('ripple/fileSystem'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - exception = require('ripple/exception'), - _currentlySet, - _currentVideoFile, - _state = null, - _loopCount, _video, - _STATES = { - "OPENED": "opened", - "STOPPED": "stopped", - "PAUSED": "paused", - "PLAYING": "playing", - "COMPLETED": "completed" - }; - -function _validateVideoType(fileUrl) { - var matched = fileUrl.match(/\.(\w*)$/), - maps = { - "ogv": "ogg", - "flv": "mp4" - }, - type = matched ? matched[1] : ""; - - if (_video && _video.canPlayType("video/" + (maps[type] || type)) === "") { - _console.warn("Attempting to load a video that might not work in the current browser [" + fileUrl + "]"); - } -} - -function _validateAndSet(state, validStates, callbackBeforeSuccess) { - var i, valid = false; - - for (i = 0; i < validStates.length; i++) { - if (validStates[i] === _state) { - valid = true; - } - } - - if (!valid) { - _console.warn("Attempted to initiate VideoPlayer." + state + - " in invalid state. current state: " + _state); - } else { - if (typeof(callbackBeforeSuccess) === "function") { - callbackBeforeSuccess.apply(); - } - event.trigger("MultimediaVideoStateChanged", [state], true); - } - - return valid; -} - -event.on("MultimediaVideoStateChanged", function (state) { - _state = state; - if (typeof _self.onStateChange === "function") { - _self.onStateChange.apply(_self, [state]); - } -}); - -_self = module.exports = { - onStateChange: undefined, - - open: function (fileUrl) { - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, - "VideoPlayer.open invalid number of arguments", new Exception()); - utils.validateArgumentType(fileUrl, "string", ExceptionTypes.INVALID_PARAMETER, - "VideoPlayer.open expected valid fileUrl but got ->" + fileUrl, new Exception()); - - if (!_video) { - return; - } - - _validateAndSet(_STATES.OPENED, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED, null], function () { - _validateVideoType(fileUrl); - _currentVideoFile = fileSystem.getURI(fileUrl); - _video.setAttribute("src", _currentVideoFile); - _video.setAttribute("width", "100%"); - _video.addEventListener("ended", function () { - event.trigger("MultimediaVideoStateChanged", [_STATES.COMPLETED], true); - if (_loopCount > 1) { - _self.open(_currentVideoFile); - _self.play(_loopCount--); - } - }, false); - }); - }, - - setWindow: function (domObject) { - utils.validateNumberOfArguments(0, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, - "VideoPlayer.setWindow invalid number of arguments", new Exception()); - - if (_currentlySet) { - _currentlySet.removeChild(_video); - _currentlySet = null; - _video = null; - } - - if (domObject !== null) { - _video = utils.createElement("video", { - "id": "multimedia-video" - }); - domObject.appendChild(_video); - _currentlySet = domObject; - event.trigger("MultimediaAppVideoPlayerCreated", [_video], true); - } - }, - - play: function (repeatTimes) { - utils.validateNumberOfArguments(1, 1, arguments.length, - ExceptionTypes.INVALID_PARAMETER, "invalid number of arguments (expected one)", new Exception()); - - if (typeof repeatTimes !== "number" || repeatTimes < 0) { - exception.raise(ExceptionTypes.INVALID_PARAMETER, "VideoPlayer.play was passed an invalid number of play times: " + repeatTimes, new Exception()); - } - if (repeatTimes !== 0) { - if (!_video) { - return; - } - _loopCount = repeatTimes; - _validateAndSet(_STATES.PLAYING, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED], function () { - _video.play(); - }); - } - }, - - pause: function () { - if (!_video) { - return; - } - _validateAndSet(_STATES.PAUSED, [_STATES.PLAYING], function () { - _video.pause(); - }); - }, - - resume: function () { - if (!_video) { - return; - } - _validateAndSet(_STATES.PLAYING, [_STATES.PAUSED], function () { - _video.play(); - }); - }, - - stop: function () { - if (!_video) { - return; - } - _validateAndSet(_STATES.STOPPED, [_STATES.PAUSED, _STATES.PLAYING], function () { - _video.pause(); - _video.setAttribute("src", _currentVideoFile); // hack - }); - } - -}; diff --git a/lib/ripple/platform/wac/1.0/Widget.js b/lib/ripple/platform/wac/1.0/Widget.js deleted file mode 100644 index 8f31ce39..00000000 --- a/lib/ripple/platform/wac/1.0/Widget.js +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var event = require('ripple/event'), - _console = require('ripple/console'), - app = require('ripple/app'), - platform = require('ripple/platform'), - exception = require('ripple/exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'), - utils = require('ripple/utils'), - db = require('ripple/db'), - _self; - -event.on("ScreenChangeDimensions", function (height, width) { - try { - // TODO: are these per spec to call? - if (typeof app.onMaximize === 'function') { - app.onMaximize(); - } - if (typeof app.onRestore === 'function') { - app.onRestore(); - } - _console.log("called Widget.onRestore and Widget.onMaximize callback function"); - } - catch (e) { - exception.handle(e, false); - } -}); - -event.on("WidgetWakeup", function () { - if (_self.onWakeup) { - _self.onWakeup(); - } -}); - -event.on("WidgetMaximize", function () { - if (_self.onMaximize) { - _self.onMaximize(); - } -}); - -event.on("WidgetFocus", function () { - if (_self.onFocus) { - _self.onFocus(); - } -}); - -event.on("WidgetRestore", function () { - if (_self.onRestore) { - _self.onRestore(); - } -}); - -_self = { - onWakeup: undefined, - onMaximize: undefined, - onFocus: undefined, - onRestore: undefined, - - openURL: function (url) { - window.open(url); - }, - - setPreferenceForKey: function (value, key) { - - utils.validateNumberOfArguments(1, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "setPreferenceForKey invalid number of paramters", new Exception()); - utils.validateArgumentType(key, "string", ExceptionTypes.INVALID_PARAMETER, "setPreferenceForKey invalid parameter! Key:" + - key + ", Value: " + value, new Exception()); - - var msg = "", - prefix; - if (app.isPreferenceReadOnly(key)) { - msg += "Cannot modify a read only preference. Preference key: " + key; - } - else { - prefix = platform.getPersistencePrefix(); - if (value === null) { - msg += "deleting preference " + key; - db.remove(key, prefix); - } - else { - msg += "setting preference " + key + " == " + value; - utils.validateArgumentType(value, "string", ExceptionTypes.INVALID_PARAMETER, msg, new Exception()); - db.save(key, value, prefix); - } - } - - - _console.log(msg); - - // Trigger storageUpdatedEvent - event.trigger("StorageUpdatedEvent"); - - }, - - // return value or undefined - preferenceForKey: function (key) { - - utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "preferenceForKey invalid number of parameters", new Exception()); - utils.validateArgumentType(key, "string", ExceptionTypes.INVALID_PARAMETER, "preferenceForKey invalid paramters", new Exception()); - - var prefix = platform.getPersistencePrefix(), - value = db.retrieve(key, prefix); - - if (!value && value !== "") { - value = undefined; - } - - _console.log("retrieving preference " + key + " == " + value); - - return value; - - } -}; - -module.exports = _self; diff --git a/lib/ripple/platform/wac/1.0/WidgetManager.js b/lib/ripple/platform/wac/1.0/WidgetManager.js deleted file mode 100644 index 9453a9c2..00000000 --- a/lib/ripple/platform/wac/1.0/WidgetManager.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'), - ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'), - Exception = require('ripple/platform/wac/1.0/Exception'); - -module.exports = { - // This method is used to check the installation status of a specific widget. - checkWidgetInstallationStatus: function () { - - exception.raise(ExceptionTypes.UNSUPPORTED, "WidgetManager.checkWidgetInstallationStatus not supported", new Exception()); - } -}; diff --git a/lib/ripple/platform/wac/1.0/spec.js b/lib/ripple/platform/wac/1.0/spec.js deleted file mode 100644 index d7c197a9..00000000 --- a/lib/ripple/platform/wac/1.0/spec.js +++ /dev/null @@ -1,147 +0,0 @@ -module.exports = { - - id: "wac", - version: "1.0", - name: "WAC", - type: "plaform", - - persistencePrefix: "wac-", - - config: require('ripple/platform/wac/1.0/spec/config'), - device: require('ripple/platform/wac/1.0/spec/device'), - ui: require('ripple/platform/wac/1.0/spec/ui'), - events: require('ripple/platform/wac/1.0/spec/events'), - - objects: { - navigator: { - path: "w3c/1.0/navigator" - }, - WidgetManager: { - path: "wac/1.0/WidgetManager" - }, - Widget: { - path: "wac/1.0/Widget", - children: { - Device: { - path: "wac/1.0/Device", - children: { - AccountInfo: { - path: "wac/1.0/AccountInfo" - }, - ApplicationTypes: { - path: "wac/1.0/ApplicationTypes" - }, - DataNetworkInfo: { - path: "wac/1.0/DataNetworkInfo", - children: { - DataNetworkConnectionTypes: { - path: "wac/1.0/DataNetworkConnectionTypes" - } - } - }, - DeviceInfo: { - path: "wac/1.0/DeviceInfo" - }, - DeviceStateInfo: { - path: "wac/1.0/DeviceStateInfo", - children: { - Config: { - path: "wac/1.0/Config" - }, - AccelerometerInfo: { - path: "wac/1.0/AccelerometerInfo" - } - } - }, - File: { - path: "wac/1.0/File" - }, - PositionInfo: { - path: "wac/1.0/PositionInfo" - }, - RadioInfo: { - path: "wac/1.0/RadioInfo", - children: { - RadioSignalSourceTypes: { - path: "wac/1.0/RadioSignalSourceTypes" - } - } - }, - PowerInfo: { - path: "wac/1.0/PowerInfo" - } - } - }, - ExceptionTypes: { - path: "wac/1.0/ExceptionTypes" - }, - Exception: { - path: "wac/1.0/Exception" - }, - Multimedia: { - path: "wac/1.0/Multimedia", - children: { - Camera: { - path: "wac/1.0/Camera" - }, - AudioPlayer: { - path: "wac/1.0/AudioPlayer" - }, - VideoPlayer: { - path: "wac/1.0/VideoPlayer" - } - } - }, - Telephony: { - path: "wac/1.0/Telephony", - children: { - CallRecord: { - path: "wac/1.0/CallRecord" - }, - CallRecordTypes: { - path: "wac/1.0/CallRecordTypes" - } - } - }, - PIM: { - path: "wac/1.0/PIM", - children: { - AddressBookItem: { - path: "wac/1.0/AddressBookItem" - }, - CalendarItem: { - path: "wac/1.0/CalendarItem" - }, - EventRecurrenceTypes: { - path: "wac/1.0/EventRecurrenceTypes" - } - } - }, - Messaging: { - path: "wac/1.0/Messaging", - children: { - Account: { - path: "wac/1.0/Account" - }, - Attachment: { - path: "wac/1.0/Attachment" - }, - Message: { - path: "wac/1.0/Message" - }, - MessageFolderTypes: { - path: "wac/1.0/MessageFolderTypes" - }, - MessageQuantities: { - path: "wac/1.0/MessageQuantities" - }, - MessageTypes: { - path: "wac/1.0/MessageTypes" - } - } - } - } - } - } - -}; diff --git a/lib/ripple/platform/wac/1.0/spec/config.js b/lib/ripple/platform/wac/1.0/spec/config.js deleted file mode 100644 index e9340196..00000000 --- a/lib/ripple/platform/wac/1.0/spec/config.js +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var platform = require('ripple/platform'), - utils = require('ripple/utils'), - db = require('ripple/db'), - constants = require('ripple/constants'); - -module.exports = { - fileName: "config.xml", - validateVersion: function (configValidationObject) { - var valid = true; - valid = !((!configValidationObject.widget.validationResult[0].attributes.xmlns.valid) || - (!configValidationObject.widget.validationResult[0].attributes["xmlns:JIL"].valid)); - - return valid; - }, - extractInfo: function (configValidationObject) { - if (!configValidationObject) { - return null; - } - - var widgetInfo = {}, - configPreferences, - preferenceName; - - widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || ""; - widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value; - widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value; - widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value; - widgetInfo.preferences = {}; - - configPreferences = configValidationObject.widget.children.preference.validationResult; - - utils.forEach(configPreferences, function (preference) { - preferenceName = preference.attributes.name.value; - if (preferenceName) { - widgetInfo.preferences[preferenceName] = { - "key": preferenceName, - "value": preference.attributes.value.value || "", - "readonly": preference.attributes.readonly.value === "true" - }; - - db.save(preferenceName, - widgetInfo.preferences[preferenceName].value, - platform.getPersistencePrefix(widgetInfo.id)); - } - }); - - return widgetInfo; - }, - schema: { - rootElement: "widget", - widget: { - nodeName: "widget", - required: true, - occurrence: 1, - helpText: "\"widget\" element describes widget information in configuration documents and serves as a container for other elements. It must be used in configuration document and may have following child elments: name,description,icon,author,license,content,maximum_display_mode,update,feature,access,billing. \"widget\" element MAY have following attributes: id,version,height,width,xml:lang", - attributes: { - xmlns: { - attributeName: "xmlns", - required: true, - type: "list", - listValues: ["http://www.w3.org/ns/widgets"] - }, - "xmlns:JIL": { - attributeName: "xmlns:JIL", - required: true, - type: "list", - listValues: ["http://www.jil.org/ns/widgets1.2"] - }, - "xmlns:its": { - attributeName: "xmlns:its", - helpText: "Indicates Text Directionality can be used. According to W3C spec, this feature is at risk, therefore we don't currently validate this.", - required: false, - type: "string" - }, - id: { - attributeName: "id", - required: true, - type: "string" - }, - version: { - attributeName: "version", - helpText: "Version must be in the following format: jil-rec-version-tag = major-version \".\" minor-version [\".\" version-desc]", - required: true, - type: "regex", - regex: /^\d{1,2}\.\d{1,2}(\.[A-Za-z0-9]{1,10})?$/ - }, - height: { - attributeName: "height", - required: true, - type: "integer" - }, - width: { - attributeName: "width", - required: true, - type: "integer" - }, - viewmodes: { - attributeName: "viewmodes", - required: false, - type: "list", - listValues: ["floating", "fullscreen"] - }, - "xml:lang": { - attributeName: "xml:lang", - required: false, - type: "iso-language" - } - }, - children: { - preference: { - nodeName: "preference", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - type: "string", - required: true - }, - value: { - type: "string", - attributeName: "value", - required: false - }, - readonly: { - attributeName: "readonly", - type: "boolean", - required: false - } - } - }, - name: { - nodeName: "name", - required: false, - occurrence: 0, - type: "string", - attributes: { - "short": { - attributeName: "short", - type: "string", - required: false - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - description: { - nodeName: "description", - required: false, - occurrence: 0, - type: "string", - attributes: { - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - icon: { - nodeName: "icon", - required: false, - occurrence: 0, - attributes: { - src: { - attributeName: "src", - type: "string", - required: true - }, - height: { - attributeName: "height", - required: false, - type: "integer" - }, - width: { - attributeName: "width", - required: false, - type: "integer" - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - author: { - nodeName: "author", - required: false, - occurrence: 1, - type: "string", - attributes: { - email: { - attributeName: "email", - type: "regex", - required: false, - regex: constants.REGEX.EMAIL - }, - href: { - attributeName: "href", - type: "regex", - required: false, - regex: constants.REGEX.URL - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - license: { - nodeName: "license", - required: false, - occurrence: 1, - type: "string", - attributes: { - href: { - attributeName: "href", - type: "regex", - required: false, - regex: constants.REGEX.URL - }, - "xml:lang": { - attributeName: "xml:lang", - type: "string", - required: false, - unique: true - } - } - }, - content: { - nodeName: "content", - required: false, - occurrence: 1, - attributes: { - src: { - attributeName: "src", - type: "string", - required: true - }, - encoding: { - attributeName: "encoding", - type: "string", - required: false - }, - type: { - attributeName: "type", - type: "string", - required: false - } - } - }, - feature: { - nodeName: "feature", - required: false, - occurrence: 0, - attributes: { - name: { - attributeName: "name", - type: "list", - required: true, - listValues: ["http://jil.org/jil/api/1.1/widget", "http://jil.org/jil/api/1.1.5/exception", - "http://jil.org/jil/api/1.1.5/exceptiontypes", "http://jil.org/jil/api/1.1/device", - "http://jil.org/jil/api/1.1/accountinfo", "http://jil.org/jil/api/1.1/deviceinfo", - "http://jil.org/jil/api/1.1.1/datanetworkinfo", "http://jil.org/jil/api/1.1/devicestateinfo", - "http://jil.org/jil/api/1.1/accelerometerinfo", "http://jil.org/jil/api/1.1/config", - "http://jil.org/jil/api/1.1.1/file", "http://jil.org/jil/api/1.1/positioninfo", - "http://jil.org/jil/api/1.1/powerinfo", "http://jil.org/jil/api/1.1.1/radioinfo", - "http://jil.org/jil/api/1.1.5/radiosignalsourcetypes", "http://jil.org/jil/api/1.1.5/applicationtypes", - "http://jil.org/jil/api/1.1/messaging", "http://jil.org/jil/api/1.1/account", - "http://jil.org/jil/api/1.1/attachment", "http://jil.org/jil/api/1.1/message", - "http://jil.org/jil/api/1.1.4/messagefoldertypes", "http://jil.org/jil/api/1.1/messagequantities", - "http://jil.org/jil/api/1.1/messagetypes", "http://jil.org/jil/api/1.1/multimedia", - "http://jil.org/jil/api/1.1/audioplayer", "http://jil.org/jil/api/1.1.2/camera", - "http://jil.org/jil/api/1.1.2/videoplayer", "http://jil.org/jil/api/1.1.1/pim", - "http://jil.org/jil/api/1.1/addressbookitem", "http://jil.org/jil/api/1.1/calendaritem", - "http://jil.org/jil/api/1.1/eventrecurrencetypes", "http://jil.org/jil/api/1.1.1/telephony", - "http://jil.org/jil/api/1.1/callrecord", "http://jil.org/jil/api/1.1.1/callrecordtypes", - "http://jil.org/jil/api/1.1.1/widgetmanager"] - }, - required: { - attributeName: "required", - type: "boolean", - required: false - } - } - }, - "JIL:maximum_display_mode": { - nodeName: "JIL:maximum_display_mode", - required: false, - occurrence: 1, - attributes: { - height: { - attributeName: "height", - type: "integer", - required: false - }, - width: { - attributeName: "width", - type: "integer", - required: false - } - } - }, - "JIL:update": { - nodeName: "JIL:update", - required: false, - occurrence: 1, - attributes: { - href: { - attributeName: "href", - type: "regex", - required: true, - regex: constants.REGEX.URL - }, - period: { - attributeName: "period", - helpText: "Possible values for the period attribute are: 0, 1, 2, 3 meaning: every time the widget is opened in maximum display mode, every day, every week, every month; respectivly", - type: "list", - required: true, - listValues: ["0", "1", "2", "3"] - } - } - }, - "JIL:access": { - nodeName: "JIL:access", - required: false, - occurrence: 1, - attributes: { - network: { - attributeName: "network", - type: "boolean", - required: false - }, - localfs: { - attributeName: "localfs", - type: "boolean", - required: false - }, - remote_scripts: { - attributeName: "remote_scripts", - type: "boolean", - required: false - } - } - }, - "JIL:billing": { - nodeName: "JIL:billing", - required: false, - occurrence: 1, - attributes: { - required: { - attributeName: "required", - type: "boolean", - required: true - } - } - } - } - } - } -}; diff --git a/lib/ripple/platform/wac/1.0/spec/device.js b/lib/ripple/platform/wac/1.0/spec/device.js deleted file mode 100644 index bb258c81..00000000 --- a/lib/ripple/platform/wac/1.0/spec/device.js +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - event = require('ripple/event'); - -module.exports = { - "AccountInfo": { - "phoneUserUniqueId": { - "name": "User Unique Id", - "control": { - "type": "text", - "value": new Date().getTime().toString() - } - }, - "phoneMSISDN": { - "name": "MSISDN", - "control": { - "type": "text", - "value": "15199999999" - } - }, - "phoneOperatorName": { - "name": "Operator Name", - "control": { - "type": "text", - "value": "" - } - }, - "userAccountBalance": { - "name": "Account Balance", - "control": { - "type": "number", - "value": 0 - } - }, - "userSubscriptionType": { - "name": "Subscription Type", - "control": { - "type": "select", - "value": "other" - }, - "options": { - "other": "other", - "prepaid": "prepaid", - "postpaid": "postpaid" - } - } - }, - "RadioInfo": { - "isRoaming": { - "name": "Is Roaming", - "control": { - "type": "checkbox", - "value": false - }, - "callback": function () { - event.trigger("RadioSignalSourceChanged"); - } - }, - "isRadioEnabled": { - "name": "Is Radio Enabled", - "control": { - "type": "checkbox", - "value": true - } - }, - "radioSignalSource": { - "name": "Radio Signal Source", - "control": { - "type": "select", - "value": "GSM" - }, - // TODO: try not to duplicate from RadioSignalSourceTypes - "options": { - "CDMA": "cdma", - "GSM": "gsm", - "LTE": "lte", - "TDSCDMA": "tdscdma", - "WCDMA": "wcdma" - }, - "callback": function () { - event.trigger("RadioSignalSourceChanged"); - } - }, - "radioSignalStrengthPercent": { - "name": "Signal Strength %", - "control": { - "type": "select", - "value": 80 - }, - "options": (function () { - var i, - optionList = {}; - - for (i = 0; i <= 100; i++) { - optionList[i] = i; - } - - return optionList; - }()) - } - }, - "Config": { - "ringtoneVolume": { - "name": "Ringtone Volume", - "control": { - "type": "select", - "value": 10 - }, - "options": (function () { - var i, - optionList = {}; - - for (i = 0; i <= 10; i++) { - optionList[i] = i; - } - - return optionList; - }()) - }, - "msgRingtoneVolume": { - "name": "Msg Ringtone Volume", - "control": { - "type": "select", - "value": 10 - }, - "options": (function () { - var i, - optionList = {}; - - for (i = 0; i <= 10; i++) { - optionList[i] = i; - } - - return optionList; - }()) - }, - "vibrationSetting": { - "name": "Vibration", - "control": { - "type": "select", - "value": "off" - }, - "options": { - "on": "ON", - "off": "OFF" - } - } - }, - "Account": { - "accountName": { - "name": "Name", - "control": { - "type": "text", - "value": "" - } - }, - "accountId": { - "name": "Id", - "control": { - "type": "text", - "value": "" - } - } - }, - "DeviceInfo": { - "totalMemory": { - "name": "Total Memory", - "control": { - "type": "range", - "value": 262144, - "min": 0, - "max": 4096000 - } - }, - "phoneColorDepthDefault": { - "name": "Color Depth", - "control": { - "type": "number", - "value": 24 - } - } - }, - "DeviceStateInfo": { - "availableMemory": { - "name": "Available Memory", - "control": { - "type": "range", - "value": 262144, - "min": 0, - "max": 4096000 - } - }, - "keypadLightOn": { - "name": "Keypad Light On", - "control": { - "type": "checkbox", - "value": false - } - }, - "backLightOn": { - "name": "Back Light On", - "control": { - "type": "checkbox", - "value": false - } - }, - "audioPath": { - "name": "Audio Path", - "control": { - "type": "select", - "value": "receiver" - }, - "options": { - "speaker": "speaker", - "receiver": "receiver", - "earphone": "earphone" - } - }, - "processorUtilizationPercent": { - "name": "CPU Utilization %", - "control": { - "type": "select", - "value": "5" - }, - "options": (function () { - var i, - optionList = {}; - - for (i = 0; i <= 100; i++) { - optionList[i] = i; - } - - return optionList; - }()) - }, - "language": { - "name": "Language", - "control": { - "type": "select", - "value": "eng" - }, - "options": (function () { - var i, - optionList = {}, - iterator = constants.LANG.ISO6392_LIST; - - for (i = 0; i <= iterator.length; i++) { - optionList[iterator[i]] = iterator[i]; - } - - return optionList; - }()) - } - }, - "DataNetworkInfo": { - "isDataNetworkConnected": { - "name": "Data Network Is Connected", - "control": { - "type": "checkbox", - "value": true - } - }, - "networkConnectionType": { - "name": "Network Connection Type", - "control": { - "type": "select", - "value": ["GPRS"] - }, - // TODO: try not to duplicate from DataNetworkConnectionTypes - "options": { - "BLUETOOTH": "bluetooth", - "EDGE": "edge", - "EVDO": "evdo", - "GPRS": "gprs", - "IRDA": "irda", - "LTE": "lte", - "ONEXRTT": "1xrtt", - "WIFI": "wifi" - }, - "callback": function (setting) { - event.trigger("DataNetworkConnectionChanged", [setting]); - } - } - }, - "PowerInfo": { - "isCharging": { - "name": "Battery Is Charging", - "control": { - "type": "checkbox", - "value": true - }, - "callback": function (setting) { - event.trigger("DeviceBatteryStateChanged", [setting]); - } - }, - "percentRemaining": { - "name": "Battery Remaining %", - "control": { - "type": "select", - "value": 100 - }, - "options": (function () { - var i, - optionList = {}; - - for (i = 0; i <= 100; i++) { - optionList[i] = i; - } - - return optionList; - }()), - "callback": function (setting) { - event.trigger("DeviceBatteryLevelChanged", [setting]); - } - } - } -}; diff --git a/lib/ripple/platform/wac/1.0/spec/events.js b/lib/ripple/platform/wac/1.0/spec/events.js deleted file mode 100644 index 03314231..00000000 --- a/lib/ripple/platform/wac/1.0/spec/events.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - "contexts": { - "Widget": { - "events": { - "WidgetWakeup": { - name: "WidgetWakeup", - description: "onWakeup", - args: false - }, - "WidgetMaximize": { - name: "WidgetMaximize", - description: "onMaximize", - args: false - }, - "WidgetFocus": { - name: "WidgetFocus", - description: "onFocus", - args: false - }, - "WidgetRestore": { - name: "WidgetRestore", - description: "onRestore", - args: false - } - }, - "context": "Widget" - } - } -}; diff --git a/lib/ripple/platform/wac/1.0/spec/ui.js b/lib/ripple/platform/wac/1.0/spec/ui.js deleted file mode 100644 index 70792a35..00000000 --- a/lib/ripple/platform/wac/1.0/spec/ui.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - plugins: [ - "accelerometer", - "deviceSettings", - "fileSystem", - "geoView", - "multimedia", - "audioPlayer", - "telephony", - "platformEvents", - "storage", - "widgetConfig" - ] -}; diff --git a/lib/ripple/ui/plugins/audioPlayer.js b/lib/ripple/ui/plugins/audioPlayer.js deleted file mode 100644 index 2460a536..00000000 --- a/lib/ripple/ui/plugins/audioPlayer.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var event = require('ripple/event'), - constants = require('ripple/constants'), - audioObj = document.getElementById("multimedia-audio"), - audioProgress = document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PROGRESS_ID); - -module.exports = { - initialize: function () { - var audioObj = document.getElementById("multimedia-audio"), - audioProgress = document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PROGRESS_ID); - - if (audioObj) { - event.on("MultimediaVolumeChanged", function (volume) { - audioObj.volume = parseFloat(volume / 10); - }); - - audioObj.addEventListener("timeupdate", function () { - var s = parseInt(audioObj.currentTime % 60, 10), - m = parseInt((audioObj.currentTime / 60) % 60, 10); - - audioProgress.innerText = ((m > 9) ? m : "0" + m) + ':' + ((s > 9) ? s : "0" + s); - }, false); - - event.on("MultimediaAudioStateChanged", function (state) { - document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_STATE_FIELD_ID).innerText = state; - document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_FILE_FIELD_ID).innerText = audioObj.getAttribute("src"); - }); - } - } -}; diff --git a/lib/ripple/ui/plugins/fileSystem.js b/lib/ripple/ui/plugins/fileSystem.js deleted file mode 100644 index 75a628c8..00000000 --- a/lib/ripple/ui/plugins/fileSystem.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var utils = require('ripple/utils'), - constants = require('ripple/constants'), - fileSystem = require('ripple/fileSystem'), - fileSystemPaths = fileSystem.getFileSystemPaths(); - -module.exports = { - panel: { - domId: "filsystem-container", - collapsed: true, - pane: "left" - }, - initialize: function () { - var fileSystemPaths = fileSystem.getFileSystemPaths(); - - utils.forEach(fileSystemPaths, function (value, key) { - utils.bindAutoSaveEvent(jQuery(constants.FILESYSTEM.INPUT_PREFIX_ID + key).val(value.uri), function () { - value.uri = jQuery(constants.FILESYSTEM.INPUT_PREFIX_ID + key).val(); - fileSystem.updateFileSystemPaths(fileSystemPaths); - }); - }); - } -}; diff --git a/lib/ripple/ui/plugins/fileSystem/panel.html b/lib/ripple/ui/plugins/fileSystem/panel.html deleted file mode 100644 index c1db8b90..00000000 --- a/lib/ripple/ui/plugins/fileSystem/panel.html +++ /dev/null @@ -1,52 +0,0 @@ - -
-
-
File System
-
- -
-
- - -
diff --git a/lib/ripple/ui/plugins/multimedia.js b/lib/ripple/ui/plugins/multimedia.js deleted file mode 100644 index e48a71c4..00000000 --- a/lib/ripple/ui/plugins/multimedia.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - event = require('ripple/event'), - volumeField = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_FIELD_ID), - volume = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_SLIDER_ID); - -module.exports = { - panel: { - domId: "multimedia-container", - collapsed: true, - pane: "left" - }, - initialize: function () { - var volumeField = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_FIELD_ID), - volume = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_SLIDER_ID); - - event.on("MultimediaVolumeChanged", function (volume) { - volumeField.innerText = volume > 9 ? volume : "0" + volume; - if (volume.value !== volume) { - volume.value = volume; - } - }); - - volume.addEventListener('change', function () { - event.trigger("MultimediaVolumeChanged", [this.value], true); - }, false); - - event.on("MultimediaAudioStateChanged", function updateIsAudioPlaying(state) { - document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PLAYING_FIELD_ID).innerHTML = state === constants.MULTIMEDIA.AUDIO_STATES.PLAYING; - }); - } -}; diff --git a/lib/ripple/ui/plugins/multimedia/panel.html b/lib/ripple/ui/plugins/multimedia/panel.html deleted file mode 100644 index 9488c6d0..00000000 --- a/lib/ripple/ui/plugins/multimedia/panel.html +++ /dev/null @@ -1,78 +0,0 @@ - -
-
-
Multimedia
-
- -
-
- -
diff --git a/lib/ripple/ui/plugins/security.js b/lib/ripple/ui/plugins/security.js deleted file mode 100644 index e9bf0ef6..00000000 --- a/lib/ripple/ui/plugins/security.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - db = require('ripple/db'); - -function _saveAndReload(key, value) { - jWorkflow.order(function (prev, baton) { - baton.take(); - db.save(key, value, null, baton.pass); - }).start(function () { - location.assign(location.href); - }); -} - -module.exports = { - panel: { - domId: "security-container", - collapsed: true, - pane: "right" - }, - initialize: function () { - var securityLevel = db.retrieve(constants.COMMON.SECURITY_LEVEL) || "trusted", - select = jQuery("#security-level-select"); - - select.val(securityLevel); - - select.change(function () { - _saveAndReload(constants.COMMON.SECURITY_LEVEL, select.val()); - }); - } -}; diff --git a/lib/ripple/ui/plugins/security/panel.html b/lib/ripple/ui/plugins/security/panel.html deleted file mode 100644 index 86baf5fc..00000000 --- a/lib/ripple/ui/plugins/security/panel.html +++ /dev/null @@ -1,35 +0,0 @@ - -
-
-
Security
-
- -
-
- - -
diff --git a/lib/ripple/ui/plugins/storage.js b/lib/ripple/ui/plugins/storage.js deleted file mode 100644 index c3d8f6e9..00000000 --- a/lib/ripple/ui/plugins/storage.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - event = require('ripple/event'), - platform = require('ripple/platform'), - utils = require('ripple/utils'), - app = require('ripple/app'), - db = require('ripple/db'); - -function _updatePreferencesView() { - var node = document.getElementById(constants.COMMON.STORAGE_TABLE_BODY_CLASS), - countTitle = document.getElementById(constants.COMMON.STORAGE_COUNT_CONTAINER_ID); - - // TODO: convert to appendChild - if (node) { - db.retrieveAll(platform.getPersistencePrefix(), function (results) { - var str = "", - counter = 0; - - utils.forEach(results, function (value, key) { - // TODO: based of current platform - if (app.isPreferenceReadOnly(key)) { - str += ''; - } else { - str += ''; - } - str += '' + key + '' + value + ""; - counter ++; - }); - - node.innerHTML = str; - countTitle.innerHTML = counter.toString(); - - if (counter === 0) { - jQuery("#" + constants.COMMON.STORAGE_CLEAR_BUTTON_ID).addClass(constants.CSS_PREFIX.IRRELEVANT); - } - else { - jQuery("#" + constants.COMMON.STORAGE_CLEAR_BUTTON_ID).removeClass(constants.CSS_PREFIX.IRRELEVANT); - } - }); - } -} - -module.exports = { - panel: { - domId: "preferences", - collapsed: true, - pane: "left" - }, - initialize: function () { - jQuery("#preferences-clear-button").bind("click", function () { - db.removeAll(platform.getPersistencePrefix()); - }); - - event.on("StorageUpdatedEvent", function () { - _updatePreferencesView(); - }); - - _updatePreferencesView(); - } -}; diff --git a/lib/ripple/ui/plugins/storage/panel.html b/lib/ripple/ui/plugins/storage/panel.html deleted file mode 100644 index d5929360..00000000 --- a/lib/ripple/ui/plugins/storage/panel.html +++ /dev/null @@ -1,38 +0,0 @@ - -
-
-
Storage
-
- -
-
- - -
diff --git a/lib/ripple/ui/plugins/telephony.js b/lib/ripple/ui/plugins/telephony.js deleted file mode 100644 index c55b35a9..00000000 --- a/lib/ripple/ui/plugins/telephony.js +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var constants = require('ripple/constants'), - db = require('ripple/db'), - utils = require('ripple/utils'), - _console = require('ripple/console'), - _optionTemplate = "", - _textTemplate = ""; - -function _addRow(calltype, number, name) { - var row = "", - option = function (key) { - return _optionTemplate.replace("[key]", key) - .replace("[selected]", calltype === key ? "selected" : "") - .replace("[value]", key.charAt(0).toUpperCase() + key.slice(1)); - }, - text = function (key, value) { - return _textTemplate.replace("[key]", key) - .replace("[value]", value); - }; - - calltype = calltype || "missed"; - number = number || ""; - name = name || ""; - - row += text("number", number); - row += text("name", name); - row += ""; - row += ""; - row += ''; - row += ""; - row += ""; - - if (jQuery("#calls-list-body tr").length > 0) { - jQuery("#calls-list-body tr:last").after(row); - } - else { - jQuery("#calls-list-body").append(row); - } - - jQuery("#calls-list-body tr:last button").bind("click", function () { - - var calltype = jQuery(this).next().val(), - number = jQuery(this).parent().parent().prev().find(".call-number").val(); - - _console.log("called Widget.Telephony.onCallEvent function [" + calltype + "," + number + "]"); - - if (Widget.Telephony.onCallEvent) { - Widget.Telephony.onCallEvent(calltype, number); - } - }); -} - -function _initializeTelephonyView() { - - var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY); - - utils.forEach(calls, function (call) { - _addRow(call.callRecordType, call.callRecordAddress, call.callRecordName); - }); -} - -function _createCall(index, row) { - var call = new Widget.Telephony.CallRecord(); - - call.callRecordId = index; - call.callRecordType = row.find(".calltype-select").val(); - call.callRecordAddress = row.find(".call-number").val(); - call.callRecordName = row.find(".call-name").val(); - call.startTime = new Date(); - call.durationSeconds = 60; - - return call; -} - -module.exports = { - panel: { - domId: "telephony", - collapsed: true, - pane: "right" - }, - initialize: function () { - jQuery("#calls-new-button").bind("click", function () { - _addRow(); - }); - - jQuery("#calls-save-button").bind("click", function () { - var calls = []; - - jQuery("#calls-list-body tr.call-details").each(function (index) { - var row = jQuery(this), - call = _createCall(index, row); - - if (call.callRecordAddress && call.callRecordName) { - calls.push(call); - } - else { - row.next().remove(); - row.remove(); - } - }); - - db.saveObject(constants.TELEPHONY.CALL_LIST_KEY, calls); - }); - } -}; diff --git a/lib/ripple/ui/plugins/telephony/panel.html b/lib/ripple/ui/plugins/telephony/panel.html deleted file mode 100644 index 8c8dfcc9..00000000 --- a/lib/ripple/ui/plugins/telephony/panel.html +++ /dev/null @@ -1,44 +0,0 @@ - -
-
-
Telephony
-
- -
-
- - -
diff --git a/lib/ripple/xhr/cors.js b/lib/ripple/xhr/cors.js index e07bb87f..b197d7fa 100644 --- a/lib/ripple/xhr/cors.js +++ b/lib/ripple/xhr/cors.js @@ -14,7 +14,6 @@ * limitations under the License. */ var config = require('ripple/config'), - fileSystem = require('ripple/fileSystem'), helpers = require('ripple/xhr/helpers'), _console = require('ripple/console'), XHR = require('ripple/xhr/base'); @@ -34,11 +33,9 @@ function _XMLHttpRequest() { }; xhr.open = function (method, url, async, user, password) { - var scrubbedUrl = fileSystem.getURI(url); - if (!helpers.isLocalRequest(url)) { url = config.getAPIURL() + - "/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(scrubbedUrl); + "/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url); } origMethods.open.apply(xhr, Array.prototype.slice.call(arguments)); diff --git a/test/assets/config/config.xml b/test/assets/config/config.xml index aeb96406..d1473204 100644 --- a/test/assets/config/config.xml +++ b/test/assets/config/config.xml @@ -1,23 +1,29 @@ - - - - - - - - - - ConfigTest - This is my first Widget. - Example license Copyright (c) 2008. - myname + + + PhoneGap: Getting Started + + + A template for getting started with PhoneGap development and build.phonegap.com + + + + Ripple UI + + + + + + + + + + + + + diff --git a/test/assets/config/config_with_missing_attributes.xml b/test/assets/config/config_with_missing_attributes.xml index ff9489ce..fedf3bf0 100644 --- a/test/assets/config/config_with_missing_attributes.xml +++ b/test/assets/config/config_with_missing_attributes.xml @@ -1,18 +1,29 @@ - - - - - - - foo - - - ConfigTest - This is my first Widget. - Example license Copyright (c) 2008. - myname + + + PhoneGap: Getting Started + + + A template for getting started with PhoneGap development and build.phonegap.com + + + + Ripple UI + + + + + + + + + + + + + diff --git a/test/assets/media/short_video.ogv b/test/assets/media/short_video.ogv deleted file mode 100644 index 69954a24b639dca225cc752ccc9b99f13a57b460..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700699 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 z 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
`Aw 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%0AB=^jQ8>wa=)4b%_dy3@cI zvqWmY5-q;JWE=VU(|C}Tw|ie^iF3d6X#Z3<5c)8(>i^)tg7sb z>yC;%jjqLu&h_8`uN!cfag`x?N@n5* zWm0tZv}wQKmJV}=48o|777RZ4FVz>`1y^V7@SE+AAO&n>Dc*;MnM;KLK0%2T{~i^& zRAdP&Y&N*}>pH5Nqm$$A`rjj8zhRY#p9S*I;f`~FqkIJ!`d3ltqdtyBee^kk;-e?|Fj@MyJ^=> z03R%A)m;y|@(Dk{s9G>y`MqM#*e8jbu4v|8VJpk&mVkE=IW^EYrG#h6uGt=?^@@d0 zgt7d_U5KTY(^iJLZ3IYFt7}u5+j{t(8C?`_j(uqJuP^K&^{-B>^GuLJ*>wExQU<5!l zk2zs97`0!L0O~LT*Z|-{pkE&QA32dnL8a|588@MsbOUUn`8R+ZoPKKSYZi$DK=2mD zc@O<(yqm=7KC=a2tQwxiJDY443gD+s4nSVfJZ}B~%qCD`*HHlDjQ{}$O`s_=CzN`i zJh)pw=sezRSyqg`JkeTZw#Q8kAUlxB&1=}Z1q?zgFU(eD<{VJM1JLM55s(0d?oaQ7 zUSxuDzz+{oRg`bcpmhOscmGh**NmggImv+~=U5L`ZFH+iO)lHzVS3O+i*ux)3Zy|x zW)+1(uQzbsl=%bTehXo4Blyqth`CM;v;djdt-UJ3YEW`|%ilyb3twT@K=;N(0aR87F96&&0as zZ)&MACK^sDxq6NKqHjEVrE7~J#vQwGUtB`^F&wIHtbP0k-)xom&I0-AU#gEH%K6tS zS{E?b%UpEN|G?#AyIae0{#?p<)xMR|DnGL1ZI4nL3th)%=Ld7XDPVZqPWy4c9~6$y zeD?w}?fmYiDCvvqSVE!`Za~zSFk6TZW(xc7`~X$sdD}a3G)T!s+UF{CwAZcxj9Z-K zYpz>N$GXM5wFK{SVgmJiN_9ONJ+gaE<{5`8x3^sh{PxU+I_+xNSUS%X~J7)<`3I``ihFz3LN|I z@SVs06-RJsR(*NOw)JB&>GOek?dD`6T~MGfjQb=d_H+=o8$Oq7QCXjV(@8f`ae?#% z$nSoU2Lr&>lvibv5;PFD&ktw3c;q0%r;~&$^VbG?cO{s-K&r1>rvVxrmQ$x$K+{iwd7d@>ab+NYLb4?wn{}EK0J+gRTH&t=JHTSZ z!=2)f0L06*5N=P<)U!!|oN@#}b>PkGlk8UlYCisngu}2kJmEe+w9LgJVgRwh3d%^I zStTCm=2j&0IjNL80(zV|Cylm121cpJ0u+UF={G@N)+kAaX2XrHtCX4uSIe@TP{EfO z*aX6A=Oe(A7CzAK3x@1QN5b?*Z}#Fub<ZaJI5*f)ObSkR>|{m$V{) zyn%*}P@QM2iJFk1$0ptz4%#?l?pHRNUlBf`Li7V31+;?&6Y4u<>OWspz|bN82jHFU zVEIuVp20<3{tr2vZII(l-DfGDw5Sk_-Gn~U1QTa?u1z{HA%c@9_3ke}D55&Gh-{U5 zH#CSUpLguLYHL&?lV%JPxUr}p0QW@6`pjE6%H>m&CQ>TJC`|Pc(K@S51^0N%lo{a} ztJK_y=C)yU#kkUkvA#C0)3}T|O{6|LX0hECPjpe>P|IY^ADk#?xoT*J$TkSv1v&}$ z3uvOIr!UJZ4BwVBs23(O^`SmLJ8Kg)5A*HM@co&*|DMMN`iBU9#MrC_% z=FE8ZbFtuvX8LDe)4W58L2*0wtC206bYskZsFeu<=IucQn|SqATHPv`f5|!{5;yvwYws zdjc|&OpbJtyFuteC4eQw$wHqOk;CGnz)UXx$OAaRw|2m|SAw6F&|g29@8IFK>;L_Z z2b9gIceKG5+>A&P&|~k77bdM5o~^HvH#>yp33OEs#7LjnDRX#l?gdMPBzprLDCl#t zO;2*xyPF39(#CNgpgGxS-luYSW+70i|CMV0Nx$wlzxqV{BZWZl@z8wL9YG6`?g0CP zGIoT`+4=70f1!3jy-eTVY<788PShOk;B~y;tLa2Q=fh(6epGeQ8!r-I9m8n5x7Szy zP>A5?B)K^?&Mv%Gv>ac`v+V(B6S)t{sc+K zV1ZhlnOKCQ6`|uWE>7f^2Y}JR%@m=W;MEiw&?MZ?fnu%|1e<#xf4~R=E9D?T*1}>B zDK33yJpxt%H#(-`V8R!;2-_C`k)l3*z$jKWq-x8!e4VsTs6@pm;7|Q z2ip70Y@~%4oWg5qMZ|Kr^J!i9E6R&G@r1Hn<U1-GgoC z_3|OMzveWlbQh^3i7b9G*vyQSEDzKKd@9aq<8;_L&yYzjI zJ?ZU#yFK6^hI*mR>Yu*0eS+2vwcsBb_IqBW0^4ic7J)_k*#EfK;6~AMAR_mH6btC~ z$4alwEQ|wXSO%+C<|E}Z3+I7ce*T;rx>3-;N?_evVvoJ_2d4PLLie{yPXD!1CXl`B zz~8mv6oUW}OmngC>_Eo^R5X?(x!Cu_faSuV9+w;zXaUd~o;Dc@GJzz903%xxX}&el z(EogA0Ig6?X3Q*nStrHE%t^vll1kHc8qPfq*u4ONf|2RO&v}bH_hp|s^Vojy!U^vy z&AdgopX>dYEab<737efmio<(Jk9A~2@0IDgt1?wE@kLpd-Fk9ab_e;-Z4c|pxX_RB z&NLIyy8rj2`Hv)-HmPUkp@qzS@0@8yke4vLq8w~%vdMLu8ZdDgfSV6)+zjAuJZUax z4j%S5aUVI;1aqCpBjO`%ug{9ObL3?_PZVG$dx}fP#Wb>@WCK9bCe!BfN-iiv6DeY+ z4#to1PDQ1~HzdXQ@uJu%%kylISJd2mryd%{P2|xI>8xS=9^>Ibn)(pAs^B zyS*&g8;I>+NlrLF-`zQLGlBHCq&VSF$83#T!M);#n*z*^Y3nT|S`_+7n`trVe^b+3 z?%b?kkAXW#re84m9^ffF8T%w{UTVb!j|mvgYW+-=l+lXm<$Tv z514md+^0Q_5BfYn{eGYx0>dU+g|@{C&?bh;71yc8+g2W?@d4V7FhHoH{r_O~|3w2u zAfx;9>r3Kbn=rS6)aBd*!Sok+CCG3a6oo*D7p85pK{w;!lu7B2vwE$4!p6A$UrD^pB^7|Ps2Y6UH=Ps zkcM-rb(#@{S?dacYQOFV^%qUIwP&SuisHL*a*U!*Ao+}B>(`p(spfAO%rslO{gQ!Z zBUEnt)bdY#`Fl71{^J|)iiTU7@xWFqs2!ZHVb$vY*EIii?*F%MR@Usk2=WH2s+aGq zV1Y*3#yHG2V&LZgzshmDcG^Dc5xZAkBNb$(mCo1$<$#)N9)U|B+RC&8!)09!1|5v7 zPXhQF6Q9)mp=e@6wz3?3-WSCPnIRKD;Wf5T#Z7&-Nr2dQoEc2`xk2l7Opv~;^1S`l zHiz3Omb=6!7DH7;Qw}vBzCtJ-AZaq-$LRLNs0g#G<+r@;aP8ctAgly1$eVs`OIhx~ zukVBoI15;008RkQFh1zSOEmv<3=1ZQblneBewMCgv+;cZLD+$0{uXMh}Qm#iE=Fa>p4hPPWn3H9Wq z<%m$$tIm(7yQke~XyN-Zr8lV;n#oN&Vq^rJxlyJBXSIr$+Vuynq^I4dF}NTs`-o%0 zE;s_#VL%u#_+u{vLt(2GJ;4%`lUV)KKr;c&>3H7(7y(2~kGL_v^3K{QT?rXZ@1UU}Toy}Zf>Cw}{J4D>#OXD6aPNT) zjI626u&=L%nNgEDc7orcRN`&SlT#5 zUi2_DqepQT!5P8%|A><`A@kz>xNZtulI#hNQ>+ zeUIWi&v9j9Tqd$`C{k3NuKKft)ayRNqf+ByJO=HL(sLSjR&3~x#X#31B8J+mOi97v zpylotMb(Hpn8@f&V8BzOL+n3%tYw%PrbH$Isf`3D20V5#N}?FP>E;K0qbLDVc027w zfN>=~%yq{mg`Japm(=|J?hboj%~+*Tz>uVn$ZR5WSMKaf5fARZD0(Y-aDUAh7vJ8^ z)zIPKI;`b}A6;RoNJVEYbIpU9*DBtt6qW+9XieoHYPe|CU`Wr341}xsoSX8D$x17b z0-uE^5P0GJK!}@LWfyTFp5({u<2GCx_~jiGNzilOufq?qI2Y6P8|!(3ygvN4B5wRD zpA#uG&XaAS=JyYDYKGuP%QvQ8cbQ=^nlco1j+=Mw+S(VW6Xgi9HUnYz6MGl|JSu~k zKh%14*$LM)(Hwu?!>28V-`i1hWZ(4V5qC_zQ&M#|gXfE_N!Wfva!~c!j?qz=3wuT~ zRx=KB!@JrGmWNblkTDxBsWy5PfYe*zUbij@t@a0v9sTJq{KnOmiAQo~WvZR-0R%N_; zuas2CA?@A{F@=YAdj~lt|51;W1fH%B?pxl3IS`$hPl7s?DX;4#6m>`@0Xeiw?)6yc zM9bRBd*8ec#Z{(oPM9!OHd>DAhMHg(uWpTTBq8DV2VJx*yWkGPo|i4^&}5f@rJ-SB zrF+kf%5lm0mc#Y6FTR$`8zjI@lb}VO(6RqXmKWlfgrp2tC@p`Y!V9F=9v>`)ig1N{ zmF)~;f=Wb>%~+*Sa?;N1*)g^I5)WH`mZvNtte}Z+vnoPR$y2pV^QydU)u+VOr5MjR zv$&zLD6l%qZ6O99ig6{!vtVB{l6wfUHddyqxZ(PSaNv=y6YlJlD^rZrK{RY<+BC?6 z(F_m^T@KNPG-}eUYbRW}I{EJ4HF8A|69a-m%hFZb7caE@xTsgBy~7qL@H zE|K=X&Glttn|mQ%X!3W4S@))hBVQR}clPaw-5^D6-B!Mzi|9iUWWSi3dr;<@%ryG4 z2`Rs$jDt7*d37P>Gw#?0GyRr}Gkzt9bsOgoCXlra(|{uYWLvs%IuqO=o- zOgrq>Ge9KT!?l>w>_XNZ2CHO-peR7#hB{YR?-E`o4`z7w=mcK zhKli6aFMof4kNubrm#1n>HL|~>Yf%V!j!TEi^tH$E3Uv3;{Z`Bh`{t^ahTTGPnCJR zX_x{f0XtuQ)$jX?o2%+jNeK-5aX51z$tYd^eXh{ctK&QuC9fALZqOb#c~TsR$$qATCcmRyIOa3 zu89OMVMWz_yEdnpur@0pA%fd=hHtVcOCVyuTxBad0+GVz$7Iq z2IgI1nlia4b-gR(?YKGWO^J{@4U>=n*d?sp5ecs(t=Z`WD-dGNx~I&JF0*N(knUE)pJ^S)qgu*hex^jkfvhxf3tlzXb(K=OM2e8h3< zu8pzfLXVj$tP&G=NohKQa-=szWq*%#mXAF=pq_&n7cwdK$Uzw%ZKO+T7l!a^_1>5G z$zQ;r@19`@3WJK26Sy+>3_Pk;fxrzHwv;}}$4oT`-j91dH7Am;He;2Y<njIDAeaX17EC*Hb1Zfg{Y9g94WYWesU)N}`n_>F%16@Yoh#XgtSu(*`yNLX^j9LsPpnHei^=T%UjrI-f zrW;H4i1~y9E(5R`NoGIey&mJ5@M0BdDZPG5y=HKonzFg2BJJJXteHl-{lmC{17y{P z{;{?gxJ{=v!nG^YP1^ zps1F^+mtSU?P)BU)9X*e-#D_a{!D~FPwmPjl-Z#^e`-~n!BgN3LcG^mgpIP-M}_Mz z%aInI(Us2@?y}^Snav9c*2?N zN2{y9d1$!Wbru|lDiLr|-WP(qwGmgap@}iwekJGB^46u}br#o4uOIW*4G$n+(Nkb? z82bG%oVC$HJ%41lcl@G<Uh-(XUTsXl+WAombDbZg5^rLfXa7D4n?ImE@GoXc_sORHHMf z2sg|}!PH?@kWCv>9`0V)t+??>jf(<`)oM9S3(m&SfaL@WsexImNi;vqekFlj)_8V& zzX$;#0C%gnSYDC4NgLA1+GRE)Sd_N2#cfQu?eOO45^Vy*Zcl!6Otu35mvfks$R5Vs z$kk0p*0%CetF`zT#uMh2S|kBdyN1k`_VgP#+!s0In4Jk4!Q8NCovODf=w@w1NS)G$ zvhO49aY-g&%zQ*dzsB$-a(S9+le*@0v>MwE5y{B8j|S@0RJR+VV6m=x$4Xfd7aALc$QgrEcT zU9oa-de6(;Dr59%KZ_zUF22z^w61RBpO9R;$HNm&pS&iNX9|>rhw7>1Xu3cihL_g* zDHJj&=uJgv$jnqx2lGQsqV9uRd*t4cXLLNx{b@o!zDD!*8^!xhPTG)28p0~90vcm! zc;+{Vb{_{*vG)#I=*sg&3%At9ne*Gslv&b8AsQk?^o|af_tr)ecpY_+38MrnsKKaw z#Nvva!C}i95Yf22?QC5vf+QgN#E-r^P{7|#NhHQ1_&|@rT*R<1@dYK(Yk7-)Cf)mW zgMPET?h+$SDd1TTOr<(_U_xJ->A z8F}OxbUH5Zv=}k-=Qi@RshN8A(O}@0wVI39nMU*D;xugFqHS7o0(=+AsDolv>FPPY zyUJ2tU3Gf0O%KFl0{4n)cUh!y`Z76crIr}^kVf2^n4tMvSZS7S)sxUH1Ky*AC4a)0 zp)(*fD9;bNvrFyD8I`D8+f-xvRln{Yt8V&ckeHbmmlH?l)s4mv%JCO``zlyqD&{0@5k9!x0&%T`>wVKow>w+ue~Yp0)L31;;2ww@66I<9A;k8 zKXkW5;H?*4lh)PMUeD}bu2vy|b!*hU=Xpq8C{psM$s{B@RjW_ZPTr5Z#I(ufoBrw8 zOT9XPUi|)`fV!bqm=LEsR678z#(CAqZyMeHWE>ADn#*`d@fGns&Z=FvVH?$AntO`c zN0u6HG@3R$?=1{dwytw?Wm?jdaBn-KMO)7VVUEf1@F;{X zahf-m;Cdb74Z_VWO1yyQS4$iz1v21*O=X=eK0^hNnQ-T4oD4MuB_+je@(I#rzy?IA zuLlvC^?9ZM$aIEG_6Jse@`ZIBJSiOpOn)kja)ZQ|245?;VZVFGsK9aKU?|HIt!!9BwAuaYk=s zDDkt7r+?A(s*?p{xP)r*mp|hus)woSmvX|5#&Q+6`b>`fz;WMMqYY|TEMeT!)6Y1M zo2Gondes@H<5!(ix4^S^%V<=8=+7IXp>I}x+@V4_i(zgzG)kmWYT;HE6J^Z$Y(tYe z8z;jwv@v-2Ee9-b)n!^DG4ZQn4HomV_M#Nji5H*CcDTXw!Gf;u1L=F7GOEVVG&o!W@F*D|5kfsl|T=B z3#|lm)h@xvh7n4zoFCuZLJcAsuh1bM)_I)d42cN^F27}v23{5=Acq<&5%XV_gfHS)n2#$!1iThQ{F#V+f~+y>hQ9 zM`*Wh*`N171nxJ4)xBwH!LCW|gJE6f&bC2RM(Y~=_jZ1@Z6#qHMw;ChaJv;TK0`4a zQPZ5-X=v>%livv6OU(>m>^zU87?bTyT2DtXuaII!{j=!@VFb4%i}=?+RQPU<|i{-gBd>0puvrd%KcJ6MyYBPrLO1V zx^2h*Jy6G^58Wue&-9~8Q;~rT%171MjaPr=on4M?Aksk`H6#F z?pLjqPcvIe-Mh~d&h2QG9)G)+=+EtZ9C9b^Pu;E;g*1b;(Ce@Va6lI+smxlz(WpmOG)+xM~1YhU;;)3N&~;#a?`kb>*WO*NuL<)o-+Rv|Bf34M_$46dV0rnt6d z0&RdRPrmhWAH~jsn{-ZZnx4|BufgsQbBlS zq4fm{{ba%2mB;V>&Fr>ntILgbz7Lbw|$6LPPISW=cx1Jcd!y(<72{Z*^YhwEUV9jDpNuNdcmI#+F%~b4s|k&hLfO z{b?C8LjXi*GNK)~%!1aRf62(oCo_C?kdW&46s@JAeD$lun8Uxwf@4pO^*#AkhWKBC zw+ND3gt473b`heoccl&Uc?T(*(h*DG6`oNZOC3y}H8npansAcwB-%7@y82>QdY{)p zj1suuOLT!vp75@`P1x)Xn$V5Vtax)~O^hl8IrLc2469q}gD{%@yOOH8A;)BO3tzep z$K|baOpoi=ts530+hN$~BT`ihF3F2<%s~LW5}B+)*!Z`mH5siTJ@j_RJ^EF^$g=W} z`I|~ctQ)B?cf91BRMn(Uo)I-U7-FW;&&nv7BAmZK%0__yCd^=b9D#vz#M`%FY7g3X{hPtR?8=_~zA z#EtJMdUV_O{(Yxz`QCer(<4fJ$6=|K481{3hLiPBXe!SO1eQUnkG4q^3~%yG%Nu32 zU+p?QZDuvnxuPiWoJv|k z-1i)Hf>14&Q(sBa)cWnIcx+a(Q*CtuG(bi3S8|W9r)lj%nJC#dU!(T3goISKd<6{2 z9eF%`a-dFyC-B8-DuSZ%1TK(&(0ZDP@hd*O<={&e19nXejZ#pyZl6P!M%`zJZm3~z z&rD)8-`$l<4I<^?DOA|a>EkZG(a~#NZn6VY3;pqI7W9Tep4Y4Jg}d9Xd&2zuOGsMbLVYWaQk8V&13b`y5WQY&l35 zi4!b@f=WXYQrtS2|Er~)RY51w&6xv46%B%CP?SZ;`QE%oWdA1Zn`{I*LHG;J)1&J? z$2FkG89i1>OHqw%@SGoq5fToQYb8J9BDmvca$6*gmCB}_yvOzWdWU}f zjQym6QsOwN#FxLFucpRTzag;Cy&)fA2wkIsW4Ss!lPFNrBdA)Dh)>_Up)4z*BuYz# z;Wb^|c&NzkR2o;6Q8RQmAG@Uv4Psoy)(OcF=8vFQdEZ;GAfyp|(%nT5yxQrt3e=Ky1V0N@r%aEsiA$d!^__cELNg1D0SLB7r&ld%%_l{2Elbg&0 zgy+jm6-LKW;BxVpoI%ri-5FhCv?KKNr7#M4em6d5Z8TJ*#)8o@H`9zGc!MI-cSy5Mq^bD+@rBLJ|qSL!J!6 zPU~*8nicgCth2I<{Euc_|7Ak0)7)4SSEHo&+r=0ycQabbaiiH|txm2Ri>2g}h!c`0 zV8%-I_Vwv?5~JFzcP1CDc3zr~9@5g+J)_bEPQ@58AFZf6<7lm~7oX4K&MV;Jwp3m_ zoK_pw2QhI@<^z($g869(e@Z=~SzoV>B2Ou}(PJdh1kacy#LX1#`g?kXc+lHO*@v`aMqeu)^ zLNQ|W%S5Q;W)-XC?OmKfi-pk}y|B(A`ru&ET58)_6?wHV&h;I0hfJpWT4$#SX1L9hfBKqqZLuYCQ7u%Tn=2Xq@p%AIk zT5t^cLFD>l^DTjEc=1(n%NcOMU4;)fpH`=;2)aW*m|%^OdWTBPViT|}@{AN!lR^L3q_^6A&K}w-!)=14Qstj%oGo7I#G#27m zU6rlx+TIJ!6{ksD$LkZ5JtfcZrxOz6n2>xa&E&Yf{}ReciX##{4ytnLk$%87`X0v> z>W-T{qa{~y%L#~G0;FUQ@QL~JDsb%NrQxzVn&6sz8N-`{HKQo!kaKkzO0zyqZhhav zm#1XlhmTpZ$9eU{1-C4*c0R~>K$9ziJ<&>=BE(Uh$%%Jb7~TY^W%*7%j&jt2z^eU? zs5N?PmnI6BThs3pEoM5BNJKySsprMtbU56xPw#LI3eW{I0+&(FlmB*#p?nl3SW|rX z(y_i%&9}FdrW^7(7i!GbL}y;Kq+cE;%UlmIhn{uhqQK;}48PwL zhs?`a{dXlSA~f)EambOw?-oo6}W>U0ajM*9r~a-X=>WPY`^6D<%Cv6o~WvK_udy zQd_H!i||=A`>L&1McEZRqh;vEDBCwth$eC?b&?Zp>0OpUof&E#b05KutUt*d ztbaB;R*H`{@4~Yh`MAdw3i=%~jz*r+$Gul8>3$>)THfU67mje^rc&dX+781`=#rn{ zLS9~eG;=rk7MW60Pc5>8nwbJp42q|94v>rs-u{}V*#xhK41pyf0wpQ5^Ny3JK)8B9 za2h5CkTKpHn8c{4{)QB->Dg?iQSQT#d(k|XT{hO7kq0%oFF;SF`wOQwlE>#YSw)aiq4~}y^GLt6j7(hXaWH@MO}kfb+vBJ zGz@Bv_%{)s+^mb2^y6m{ryQ=`NE>nOH$en!y{67s6KUstAvur=al3xK1;l}MHt^w^ z)_ac2kZ?H4g(}oukrF5o*78yrZBQ5xW0ZR_hHK$Jv8ksUt`Jj#ode# z^C}REyOpMeaRJOnoFnvpq)Pr!?b7>o3acNmRv|Ttxm` z+v^v8su$(2*Td8c$P2?I?h$YJtLFUb<`eWGt(!D<*Ym9Py(3Fj%TMv{T~EFcm;Xu~ zuC?={$F{Py_R)&_58Zls^~jg?@xN9iq&4qC4?dIO(Y5$OP($7VhB@0 zVX%vbbyIHrRqBUSp2Mw0vWpYL7+Jd@m1+t1^HgV=R-a`@rKp547U~Ao_B(Ht2}t0S z^HmXo_gnMn^h4tfZMD(25JaOAc*ZcuK`h@ihTTH?D5Yf?6$F>enn3}FDAPL%&g0FE z=hR#f-)cvkfJBBzlcNX{0C?;x@?&Z@V(ugojw%#=vHV?V;pcitS65hHdTc-o)nr^2+7M$w^gr&3RCk^Y>j`U^O0*O|4kcs{{L zfU_?zmoOj8STek#MOV);aHIbucl5x5qK#&n-6Dz7>zFmsY4QEK&5AR>$$b;E^4nD? zM$L}USA8Hj8o{Shn!FUERRKp^Ge~qfO=V4t%QIB=u=xC@9aLw0I0RGI;-{;a0xE;C z=76{<|J~0OF@Nqn2F`)j;&MS)$aP4Jf@pdebM zf+3Kgv;u+(1!^#;kbn}Jv?SRWP)vgKRhCd11!)qLgr;l|hz3ep0fD>!-#5;^W1R8b zhcnJwo^~GgZ~xX@bImm;&Yk=;9`4r^Zin$KV#8IrAO`}F?LC63m6C2(Os%^P1(=D) z3qMa3#HUT+nFWA@)sI1Ah4e2svCSD!qmro*QQ|ewAdSukBPj>UhA;*$SovPhESN_V z$qrnw39_|P3wQR$d7KF(#ky=Q;r&UDAWJj|73PCP668>p=&!!NL;y*VH#~4xP#?R& z+ptm{^V=~5?@tejbuXpbL!w|u(tRG6G6IjVJP0aQbjDuZrzrfxaH@pL|9i?Wgosr~ zob)#umefrvfA^~}I0^y{#$>3kAEm6gtN%%`kAF*}40t3xjWnrDFU3QcbOW?23GLrZ zzh?5`o(tYKCKz9^-(wGAs#xCyZW>z>h==Tw(nGumprtSGtEe{7jZke%G}w=wyW}(A z$!|$ySp_EYo+Ho<0mqV{qsyf{Xd9+EoUi@&!C(6wwa^J%mj zgo)-#qYYLrWBrY4U~UN>d~h=y@uN~qPqa4Mj+5#*^2L2PqOu! z4*W{6Sb>H9E1FD~(MjJA`L9p9^4^Nx6%qfCLGsRjRQdCI7r^B&tYlOQLlQ`es+!auX7c_Iy zTQKpGd=nn-mze46MO4fYEp&tdIiSw;p*tN`L+<;Uw4`rw3X0c76PjEwmu1xKm^zYRiMq8Aj5=8W5XOl%v~GTo#v zB>KTu<#C}HqiLKp&oH5r~=z_?tU$`#AGNKr&*0mM+OxB(e)OqP)Xx)#PP6a zIRHg-tDFZvm=9cVzc=i*lS1YDlx75gUT00mL9lM3WUbI8C08j(>HxLxN!O~q`ZzPU zZZ?y*j@a1)weqO;MzvJlLC2TEt-cdT$(MX=nT{lqE1#h+;^U);pMMM>Gb`?Qml_~& zay)#jM1*gT3bcPYhnL2M;@g#3)GZzkq5Dbkl7QRn%LKi_2ExD!JZpFvTviWRDQBYeO*R4uHmhT3OFcI7b zwFohGwISiuswT?kG90%G8M4K~Cs1vh;th^Ghnb#P@_J9{mh@yQ233;}V@2|Fr{qXB zKnW@WJ97$Ij9ivegnk>yBw$Y9PBx+A3k!5RbIa(fLN{GUnDj|P%^Y}Agofl#j>+w< z;rCsOiUc4B0dX^Qd2-6hRt)}kxZ!NxNv#CRz8Zw=`aHD|d@j`TF{&mpJp$_A+uDhrTZhX$O4c|Q-=e30SDAE>42XDbU6ZXFoYtF z0F&%hEJ9p>3fp9^4OBh(uY+DN(}?I@Q&10i!9g1dxb!U^&pNS@c+3Q3wc@&~+9p^> z3AMtlrgb81xPH>eD9R;CQ&12)32(5JfZ>+ajy4_)=yc{2p~LPfl0S+>I^R*j(7>zY zwqG^yk@i6ONM}9%t)GZWlB`^*m=><;#Yc9OLvurYC(wQpcv=QxTR-wrEt<7C^bFNT zr*yPYsFI;!@38U}8NLq~R#d8dO$Z1zgs9g58qF)CSb{v6z4{1u)9<<$te@0~&M%=p zmg+DoK8e!T>`2)-(92)TI}vz>53^y^v_) z1so!fi8~%+uXHEdRDgqbOTcQTH9F3~hv}S@ClZreg~lldbBIY&;W7=@^+_HMKkRvG zSWPD(p&)BJY36oKNO|d&)sm-jHU)bxD`R87_TwZgol0tk6=`*UEJ?}@_h&k$IMFvH z+dz>FaG*on%X^7;BUd?+;Yz5#to>VfNYFjmSC%(Hp z^k>3*7fev-&l8FG_Hcm)yClfK^kB^AIhB>#Y-!+YzB1);gIN4m%87nI;U_gIpz<0V zeP6()d(^~*f;LAEb)s5~=|iq@1P`}VQ?Q^k2|bGaPcyhOP=YQS_6C4ug@`08GYNP| zZ$J)6rKO=i%a3&)<3<6*0Yi1YC&&iRxbY({bLh(?l8KOv1N8@gj}ql_V>JT&$(am?$}GPYDchk+e<1#8=UOpMSg5^qJ<&VTj@wfL}Q-R^DVX`Jm-G*^JNu$Z<19kP*Qf6 zfWKkiGHjza_$ox$5@UmBT9NAU!3|KCevcQ}f2n%6cb#;#tA8)A$Oj9p%vL*+tHXl| z_RU(ERo)ZpOe?X70Kh8m|BN4=c@#iOjTUiTJs@XwnshMp7Hz`gyRn$B!d;m~UU93+ z3Us`ZNeV>dQP}P0VS}&Pw-u!xSk(=7`^cV(vfA@w416bnv`wOlP#)IeqHuOez~Z#? z_jbj2KXRi(9dyR4N@1sFS=j^S$-${Dl&LsZe;I&hfxBV3ev?Vd^2OJEnP4}-B&{&8 z!G${WJ|d8khy1%x5=8Q}v>?_S0kN;-iGhIXK{;c$>yk1-xg6Obc65WvCGvMLcMwp`qC9@a0CG> z?a-?CxN(6$F;pDr+6I`${R9Aa4+_P>qzHs(P7a?0tw+Db+Y#_mF&k-mw^SBlr6zg5 z#bMvO+mb+|_UFYK>z^L>=Cva+)q0ZCN(!Z1C_yK9+yu+5HwW--Kd-2Q8u^o=us?JG z1vNLA3Z0zE3Ty!3iF&}C&_W~zZ~=5kE^zxxbUHlR56X3U&CzN#P~&6_p(sEAUzSUa zpdbe6Zj`;Ar7RbG#&S{>sFcY-$qz+8kRXj|JOsM7D$uYX8R*Wx37wkPQY;lui6q={ z+xc6l6wA!gf(K=~NcbsnkX{<_;dVp>yde9QH)vpI`I=iKt|rc(!h2X_sidFXHS!cS z$hmATCl*+PV`ZLR@t3vMSW_V;z9gMtnufLeg0#)x+?g5Qj%c1l^6Ko(fFXEan;A5qI!> zodl5+9=Lp@`VdzWYe!!~os1!d6{E@2PKmWG^jyJg45e(hcAajacp{#$jv$Yh6o647 z3?#HR^*rR46pPFFxxFzsjLFX~L@TOMj^JVC38`xZd>W)i#xy#N$pr^~@D;krL+x}p zwaA^lNC{JK$6>&Jhcc?P+7U=hnM9~F5b_YP|EJ5ChvHE-^c*psfmPYpsY?;+laDqj z(Kc$1Ko@#GEi2R;FI?jr-j)xKBF(!t*b(~-Df)wFf1Ccoblj7Z`o`|)kImnT?jH{N zYdNDNw`TV%Q^!5iGkptYQ9tdzwInY4;`TAW)cAyLuk1q37hka7`+h&vPPbwonCbq_P+p`^$T34>WtTA!L)lL_Nk&ABG1;5y~)6qHi*!dqfTQ@8j zG(FM!Jo5heo{uM5Te?vP7~3M*Fvo4V#T(vUmy0vz7fw|^)UUx*ZEKh`w0cSFw%2Q4 zYp;}?&hs57cRtRqT)Wu4EU#3xdvlWEU7>BKdw6TM)^VTUGwQDy6%3(Yeqz@@k$*^A z8dsufzxyqS2P2cu|30O-JJ3NWdEht)Cba*fUc0%s(#mOT3IWv_x8kuPxzCGmg{sKb zlDEDvSK}9%-}c8tQWF?csQ#PKZvOK`#rzJ{7VXzs-wjEStr$K#MjLF={cHadz1ibG z9MUpv<8J-Ezm}61#5m+4w{EK*B@#D&$-Xc(RE0Rw7rVVo0W94AQ2$+Ru}s}ZxaZQz zBKQGt6MzzCOT>Ibpz)N6T?~&Uc*=WE1i^dVSX;7h1R-qiVV}VQV5toR^CyGl6|eEO zIJ#&`B**|Evic3R?`{&dnPpl2_GIdk(uSbNpb9x(pYM`{uP^mY46whn3r}=?&uU;uadimxYmXqMvOW+3*B0KogwIO#DxP|HMwqH1S4`c*}pBU;=iz6C5MHK=H)%zg%R@}O$vD{Ez+5LNNT zQR>|S%Tc{dH$2+?(!dun9tx9utHGrCJ6%O}(KGK*Xe0J|`pZFqaglziyY=eXL3_X0 z8E55{o2OkW*&HJ&-O&`^4Hg_x*FT>R9H8}pLFsgUy;xWqg7GVl3>@@~7F_4$rr0J- ztg-_$k*$VS!t7C>UzPS^&4md_IQ(p(Fd+FF+IvGPip1u;{v=gY26ygVRiUCajGNY}Rw8>oEz2{LfOFDuxc zG=*WXJILT-+&0&>`0djjWXa(Up5Y%3R+n#?Yh?qLS-iHkPQcWAVK6YE0tEQ#6WoZqZ)}`Gmi${Y>kxM>}U15jy0?tncWRo7K z!s!jYgTE^R610(n6)#7<&#otT^VQ94+8^vAw%+#VNL{*w*v~(uZ%O{)T33q}&v9ed zdOFQa`YlYD9yVnPDM&B|0Q(^QC$KyhQf$Q9r9@fu34MivKcY1P^m-p}PpNoz?rZ;erwq<4G za@n|2Y$I09yo-{zO36JaNcwr>4fp%u#J3ESG!f-P3Fh=zww+z1>a7DdS(A`>TGpCl zaIgphgp4G|o9pQDrD7OU6mz$Eapq&&e{KY?ptD;T2%qI1TQ!Ea+WyU4+F#t$*eX-c z8@)g6%km=twXGdRPoFnA;NM8-CZgLL#ltqx%o$*_gYe-@6kwfHaGw3cDs?t*n4$4C*SV@JXEOQ5iyMGh>VR{4eca zZQOE``r>NQovz;|o#U!+yNePU{e*!=G*Au<-8P&XnXc+Je`RXsJZlGmt> zApl}J|K0gR%w^QbMA?nf!NIGOJ2QLpt0muM-fjo92X_sxixiU|NzIq=Wgk}B9w`){ z;_t*ywfgEM!dgeUPoT}%D7$0WyJ{|V!mj3_2#IDcyD2WPUosNuFjCV-(63W+HJiZ_ zh?xAJAc5f<&h?dum&@w)YjUxXeHjk9Ln$Zw2rNgSpk7%15Kt|IS}t7V0+7mw{f;aG zS*%0G9s6ShgJ=I!Gt%P*DGN4YQ8)=riYeCCn@?~VNK8oi zBI72^j_rT-DZ+e;QGg&B?_3+Gi98pFc{SrdTNb)s^y=$pg7ioKNJ;=P2+kq#i0UZn zCV&l?^zeGgPOCIGV6|S$qgT&95xL*AlOXqtPhC6^c6w3C*GZ6_c*x0EqrX?geDBwz z%|-4A83=bAM6~IoM8AB9*<%IwRkxf&0A238#;$`~$(1x?3*1#dbXJ6D=QS4jgZZIO$?h;_1L#qTDKo0`HlZDR?x1zyG}NN zgL-VsL)5WN0Uduj0x!YUT#J%?H6Qx0RBrgqO-N1mTdQ2gG4}ebHt-8gXG ze08EW*AvYK=3bFqSG4Qmsq>yweL+a-=A1G{m$oqfrY5< z+pa!*4Jy#|N^tyM>(lGbv+doFj!MtG*0;G@LnAfG(XPFN*3+BUFT5}mEx$Tljn=41 z@===NbI;97x3X#%?Oc5u!I7k`CAP+dwyHTR4rwJfZ_%oX0`=oAZNg(m?~fk(wbP4D z5FsfxDE*U=9d)!>OoQqz4(HNdgFE;uRmIsSzwN9Q7v=;u-)o8wUv^16G?*@jsEue zN2~Io!QOU!nexW8q`;~Y$X2fjxjobIs1wV~?BRA8gf6HxVna%I=4V zI91__Sx$Aq7E0i@s`Z#5*UgDOSV3n$g>NcPY=22odqGwR3JO$`uR_Olr$j&W+k4xi zfEpn|LxGo0dhF2TPt93}xLD_3azX5MKUv}r$EhG zUpIXTILle*e>652rN_;epo(q&M+gCa;ZCQ*6<>F}UwJug=(h4s(iMc2`a@%Uy3_K= z#X|A|r^d+WU1zLu?zwYe3+>o%HxDE$>FZrepj57Xcc zOS|rQVCE)05GZ(0nqUCq0!_2^h>=_ zehHMgphu)lxaFZCfgL%JEq}B4uELrkC*7(e<1xN1>d;s0y|EPkegr2MW3AwDv9@Yh z{dnRKp6kQsOLx-0<>8tu0OWw_G!Q%@;yxY7Mqxi`9D9cc(P+*;+UAd`%Dm364Tp>k zM%CdYHj{;zI)e!!MYx~3>z_pDOD;4SIN0ba%96(;;M;?5A3s$~sDH;fw=cX1hqWOw zvZD_~5q_I*EURUId~qlo&(Q{;pnI7MlutT(wwSy*fP^{HcM_*kUE-CoNR7(!DDpov z__DNCI;&+`w!Fgq5ts0hjiV_NA%jp z=AyeuJucuARA#POg`1!_h$^WfPlktw z=VED3dV1Qa`o}A{t5=rVm0>XwuRT@q;nn7|*&!uF;e<{IL#Sie&#-CtJC*l5!n&U? zLHWyqQZTaz_!N93fb@Xf-OK1EV7Gy~u9Pt#qCr*EI>vD6bo!TsHs@C^CCSdjD8u9W+X&(L;pU)R&<=3!O9YKW z+r8sN9M5cD_#7#OXe%L(^b>kS3mXjUT047}hm;-X0Ht?u!kQuZ%ayGt21)SX}zYUl5E z2+OGo-DK33*+cN{w$OYu;mPO{r1#eih^7mBq>qkVHvliLj_2FcG6~ED`fA(=tuH$lsf>c;@i^EWwj>J9k3=EBO-lonGzn4BPT@Q}=WhzoPS4qW69O#M?;G+} zhsQ}Sme+lr9;g(LXnj_Q`ah!S@hqY+&|Y8Lu^#LylSJ9{Tv`s;A@Nu^ zym?bfX|o-%r<(Ei{+yCv)@ayU^sqm}vAuW6Y}&QK7=6{?d%sJ(*aPzAn6;mMmdEO( zA`&5a>?~KZ6Gjo9Z{uA0qv=8NBJvI(D8qOoLfh=NZG7{N8{S@q+(Dy?4^~9N3zA3L z12XR&M^Uj$apom={&cs~zp6!{5}ehpi2W82#JZRw8m*-Ot~#McQ#6+_l3_ocIp$ZA?mY=8I=7`@61+&VA{h?+i>Bxm z97+KgT=#?l>7WRDQy9E`2Ja0C*%EG}H!P277F z+VeLpI&p+(L|ErC0?-qPqy zPjqYlr$5ekURSim-Jg>E<_hWL^9xF;@s|B#3iry^($C6!|Gv&ujk^ z7D^Q*T7Rl_`~GQe4yh5sdeI8Ddn{Z14M#HGRE#X(NoWfLqyTZZ9}qyT6DKoM>M;d} z&Ks#_UTd_czx%8}_G*D9DnN#60y;efxfrh@3p5~_s3k^W9;3^D5;%;J_!vka3x&CMhOM>aYikQX;(|h-pAfVxxWPo;h7%RWN3;uShmVM zBJe_t@u)g3A|bI`CXts}PYO%3(!^BQyOxR#D74`2D--G7ORoiQ$VBB-lY z_PV^)nDt$mwKB4bJF0?7AM#V1R@HmzyEJ)R#10KXFnCpNbgWJ7R|unW%Q=Y#s~D7#igxNpcCQG|g&(y9$HbtQ8_8A~r~NwH2vpI_{G*(uT(F?a%DSG~p*MQu&- zY1M|f>qt^+_W6XW$NoPQceIW4sBrt-R*u}%{zrdepZn3*XY3tf-VC+si-vU4dQnYL z?KacjjooV=a(cAAZfn%ZcNfEX?R^wao3QrD#F8s>+=7v~+Q!gbDSGc-hpqkHLHw!8 z>)}OSI8|o^f8UnT(Al0w&D>&1!(a8`2tVZ=ME#ermMVl|FcM|nsImD4x2QLftobx8 zIucOU>oZw@@?!@$v=Ihf=SPu0Jhkk8=|^9WPZ^wrY+K7XLXP+nHurS=+=Wk%qJEIK zwc>W9+ri#+nl4{^`}w=qm;J|LoPAoJb$D-cT5{aW>v#{++vnIkc34UA^!??9lfH|JVB zTl$ZU6$k&qA(5E)W2mzK@8R3d>pwg}#T@c}d_Oz3_^SO6?u)JK|IJ?5`J~?IKJnAK z?Rn#mlgNwkvHfFrmMp*}T*e+d_tn2f8Ew1%aJK7Z4D(lidvibHkDQz#C-cqsH})CI zZ+ts$x#+d0b-eJ_k$YQff9TJ&uxR16-^~+j>Su!5-X#2!vW?^C(zUAobyxAl^`Dip zur$Z-4%v6Re(^l#yyV|cM!#-z&fbJEIUNq&-J7B)&w=5?0$N{ena<> zfvnf7^=ZjoLk4%Z)`{i^Tq=^+V`Gv^=NjS4lZ{R(^OdK5_*~I4oCMYj>c|g9tb$s7 zqFj3}Fr2t`8)-?)UT9*;STW^N3u1Wb{`}w0?)nik^=7}|P>D_2FS85AMaqk#7j5i& zxmt1u!`bxePkqhW^pB~hPoklzW1-I{*TfU|+%nS+s4oSX$l8WQK>uC3rd}1TH z9?PVxr9PMAvr;Ux2h4zmZ;d6bSViA>(ad-*HK6DywSM32T83=5HrHhk2Gf|rVB~fn zIOwUCsF)`$bOzGi;ycB+X`(kj% zeUGfs?x!m*HJUogJ$vQHpb`rGMwAQ+pa0tLB@YPolo~2COZG5!2IKk|hNVI{%5Qv; zVRZ=4%0SJr42x#pbsVAuck=NlD(1-prok~e@vRKxRVRYky6Pwr@s~0n;I;(J6i6YH zxCTZdw`>SCV~sn~8uzkoQ8;-*%&xDI00`R&9H341;fKAM+bA=#J^sNgOWVG~zp^CA z6cKm2qj5VRK2mGIc=b9`NN9v}0_$VL-U(uu%Cgu^>^+%*YrxB;AAy{lfgfLhnQAI04A6Ut0ul=sV#-BNcg zAd$%pTb{@s!YdSne&h2x<`YNP73x;aO=EW4v3|?8-a-l8?|yS}nHQ6+z(oR~s0Vmj zX)i`tF6yq7PppT17?#(Qph5rE$F)t17i(rpOjTeDnE0KH<@A8sC$$ctObL*#!4(<6ZWQ2``QA@KxmI9@3U-t&( z@wiC-+zeKaCH`R5_FmC80=fX>#0^w_bDyqT-#ZCDE&qn zZ((fl($0G{+7P)igX{jcWu0<+;yX?~=k4mK8mUL)gZa;VfbfaLt&wi4Nw2coKbL$} zQo;^3QCj5;5Jgki#pbS>8?uVZPcvPadxevVMPXz3OJ2z!-lrxrq40b2R==XvZG+L+ z=9m5qJ#?Hpr-2S5CTccNNj8hBSRHL|#yXgU)UqEx8b5nNOjZ6Ysi{~WrBAQBNf84@ zItM3yy&ipXQ7?Td zclGVN6!48tPRDtrE9!KL?{U|plgy8-d)Oq0HWR}p@%D$v8-^miRk%Ht?u^m#1{P|?dlTc(qX|P|M@%oPx04aiLnPN3njNFcD2au+DH_O7XA@%GH zw2pRScIRdeR{FqscJoW6WaC#;a5_KQ_kO53NxEq+&#&m@fw2*T^9S{R9zE^P-aW8; zlV*Wk_$L_=)`v~$^<=I5P;b=nRrvZY?JGr7IvpUMQTXlXA3!kEs(Wh_9-XW%=ayZV zX+^;JR7Ra_vulJP3P?vU&ZK-v30z!5#Ay*Sn-B8KpH7PcUWc9T9kriys53TNuu~gJ zoqE>v2<;Qq!5JH=>Qudny}t1Df%mS*xoxLk8{O4x={J4&wP!}AGT3c7h(rqeDKuBc zwh{9mO+f|lCNw3AF2{-7*f9Y<^<1@+umJ%5&C0Y~S9GkP49!T>*lkjla)jpH%CQI? zgR1X%IxAxi0Tk0TX-j#mK#1yF+l15=oH$UW)}{=hs@kK(!J6il$`_N5E=lXX$k}_T zR&&X|?)da8Gbq3BolgQ^)^L;56PtxJNr;}D0^2vO`hC1nuJfeoht2c;xg+!Z4U#`;1*wG*PP{{~_;Rd#T^v+Wya8&9h zumn#pjJ0|A24x_FQQt(V-yRFXRFZZH{J(1OJ#ilRE{jaL4OuZMfmS*o(>M;@&azQ( z{iP7_rOJkIe_|eS$)O%fdxsqp4Q0lg6Tt8m56cERXzLqp6WP6Z)^1K2TGd^30kvwk z);ntP)$e!xw&}AoP(A-$gE^ngVe4TR-V{C+r_I=`-cp_1e|2R4LfYKXGrO$MwBazr zaY3l^7UZRsM??DIvJ(q&K_o}F4C|4Zst;0E&)(rwJ;uH+>|O5%4jl3ux4jAa`SL=7 z)Xb=-!91({GQoMMJu)9z`sZpjYm0zdYczqVk27$a0{iWm#XYnO`aYuqWX2xP{B2ZT znuOQgTtVGIvYB@%;0v(ttA#pJoV8w;+4IN$D!)yV_ry`0D!5&5CP6PcYgjFdSFME( zo9f5mHuER2HV7Npr>f6qU@*%xOv_(XAXCfhzWPsUZ;RG0GMp?xk?~Xve{6>m!*t z5ZRjeZB(v*d}gMmRKP3M{>sq?(&Qc_KZeQF=bF4bp`=krtpx#EbhLvjw+%vZ?UPfs zm39}3>8_+G_#2I6y_gNq1svlq$syKis?>;`vg6LY*1PW(Rnkrt;cZD$GkozgJQoWW zum-pHSMJYgrlV!?LwX{|;GMzOes%^*JUyEx`T)5x7vPsS77>YGpw`k&EJ}QqCxFXE z(yG&OhD!OBSto;!r&Z8?xqAu;Tjmv3Oq80DU9CrN!VRSYdYOaW4CX|x)a+Y zdEM5eVE3`hTyJDK_|v(4Znh*iO72*K#Ru?y=+Hk0-Ox^pKmHWz>r=yHlI=cmi~Id) zq%95F>AK=M{{}F~;J+$2B|zeysUyYss+fb*Q9^oV56_eh{5!Sq&hbSiK$rCKgU z{X`tU4rwY0py!nw)>JPgI zNjAYqY1&Z7Dw0X9io4~+Ss3+Fq>OhLb~ z%AD&^i*Q3h?eE$u;Gny0HqQ0B7vT5?;H<5!upbKRzOQM0}`UVmg zOP+@JN3m>SfBLBAt6R%H7&cd9PDc+#UzPn^`LyGxY(yJ0gKi`0$HTwXo@HSA<tTjMuw9f^NQ8R1ZxA3vQs9n`HIpeV*7Ff5hUAFRfKfj zH*U=h2UOAO#mn|HvDm#HLEFOFp88ERk)A;u?hv$T)PCZK35IhZ(U;cM(~s{oQcBGLCRs?Ve)#OCLzv1>7!UiMoD= zqR7f$x#V*fT5o&@wDmPSU=}`=>rQ<~2QnLbsI>$NBfp_#JHbz3r!wl-Hp|Qk-L>t@ zXZ$UChvbrX&5~t@`Y_%b*3W%dcdCNn4d+~JeD`Zl-4xc1L1^6HhNF~Qg$!b&7TJnV zH8}?Z=fVz!Uoz;U*3@1ebz1?!;`0*%DJY;YJZD{MR1cKOPoFa-Imk>8F3!anEqj(f zV%Kmwk@~5$>2a{t({QPCMAS!jj6r#3A6{_;Brn`WJ3OvNJpf4u)(r+(_!U;B$0^#hg$teHwTW$hJ88{OUs3tGgaZf&z@>})cOJQvS$^&Pl_N~ zEafuCxKAPm930z6gBKW9cZle$QtD&V3({RX%4&Hiz_ z49hx&hNz;_$i33iv!%_|@s!|D*TCq3`|sL)_-mFXhkgrawfpE5FV-r=8AsdtL;$n< z@$wK)#F}~$5sU;LTx)U{3Jt=S1 zkDi$n%KjTQh~R|L>B!nB#@O@Zp5mEY{&@evlZ$(&a;|;WWly)6b9n3yos1e%K>V=o zN^Jv<{P>4X2E^01l>B&e=iuD-i8W&5FR}sTb+nCSM2$3JVZ5D=4|oxN1^E)SE2}YH zbFj$bqMV_LxI93LE+WYLV&+VqrEjaR^-a}po%`Q$1*bpGOfem%$t-)-_ysI=7^_hr z#Qj&y6DMiujL&jHm=Yy#AN@Cl*g2u2WZ!eo{G2Z#scNeLSj_SS`O2!Y@9!KYv7 zFI<$DEMB}HT!vjW=sZ(?&smSDWjp*vLpn(lfN`f8$V*o`w zUm172^sV1%E`=eipx8*{a`mK#_aySMAk;~NNcLI`kL*V2ZZMbtmF{ALsQxr}EkZT95J2p0V2`llDuBJ}B z;6FIdNS6C~adZJB*|W{gZ(&FQ0Bg_BElJE@Dy(dUP=zk*s3@iV_0nN%$V^v|OKp3)sC47R}yN5RU4=pri7c%&S@jYuE&Rx(M zMVxmI8Cu==YKQaknIDCLKMj7|^K$)->Zh3VyuI~L;-XDlEMI3ckKgbyT5fU1-*i=7 ztE_2d;UM`tW248zB^!6O8n9V+v*%yKnrp8R?bYX}h93m_texNZ=Hum2`|oD|kou;- z_nE{DnU|)26VP|t*fIUW#w(XUAh)>hTJikOANTIvo42iBQk$E;$27w(eb1_0hZ;i$ zS0gJ=*m%U|7^yxUc#-((*WU&WUH>}#+u+f=KB)5q*B7vF(%t{YI&_WKk$=1UezRQq zx^H{-d4sxD%hpAee^Y=_efQpcx_M-4W$42+_X8%*H=x(bmwH*)WJzZ3hP_X)SaNXX z>hRI6Z}**lKZ4t(bt2y#bg67_p8tZ|y2d?qlYQH$gX?$K;Y~)o^T8>*V|Mv3Bk$h$ zpuaABUF^k+U8jD(x_*_}CVQBt=(FDzf23F4?n`0I#xBPGdt$V+YkP0zH_p1k-#30M z{ccFBxr|}o`{<*JAl*H6=Wud=jMuw$GF!#g{la;?* zv)wjNN!o4bvf57M`0Cdee{4(d>>ICpZyx#X@wwsMFS7HN=kg0b)83w{81xxE?0EOg z?!zl?I%gjKbaQb1!A;ez2XZIYH!l62ns#E9?$NdwlzZRj$z}eRUEbgOaq0HQ%)*#@ zr;kR3Z+ouSn}_ZEx^B&i^uYUJ!{J{Z-0^bV5p!k9QkR8>?RhCn^44ZNG>?1zptkd^ zga3X}(Z0HLJI}P4&Q3P!+|PHTZ*%_6ec2JY9UM&A1+xX8U%NXtAC8HQIpl2IoN%pR z?eLeCN4IBgoB$tF-EipImP4_h%ws10`eUU-(#coLEyEJ(Y8Mhvzg}I=Z@K%Tm|fQ! zm9(yUc|^6@#m~e4{Kg+=?4a*k{&3Hr!|Ih^jLt`SQjBw%Kdta=e_#BtV8xrxzjx1# z;X1$FwjzVd=39-Fn({LGlHfDXBRia&)sCUP4p#;hE#xlBS2wvEeB5-SA$&)WCrI!{@W7KCB9hL}6 zfbYz_0{@rd{@|*q-RU{nyrY2+vamsJ@>OE>pPp%*f2>^GZSnrvesRr|20IbtsHB6M zY~)i8+OWI~_;3vl;e$IsUu5&CdzA*pgpf^XV$E(fXv94h(UuizoN>~+qRRgClajp& zPYEsW@UX1rH?_4Oamj-8FUM_O@r0U_FVWucuh*re z;u~|3rsJWG`}t=-RqTgWNo-_`)lcG1l1QOTum(%OL8b?eNV?<#H3$hLH7DE)Oc z`lC+VC0iV_D7U#3!*Zz64soLOSFG{2%Wnx|tgMK^eNXCZjisu5P3YY)vWdNj^UmSx*e&!x=x-Z_nL^w_^yGcFIsSOm}Mtz^58 z2o6m%D`t8EMs&w#&6twl)1a&Xv!%!A<{=i$Q+Fjp>AHl%%gXQXD|Rn#v#`v5Y(uCO zpjtHcP6{vO4iYIY^dzB$!$Bhd^Bz82heQ7BY;YjxMEUyqq1ZF+JnS@9Rg0bUSa!E8 z`PEn9+|X0R_u5*-jv6p9dhq|@?9GFk%DT5vR6wQM5h8+swj)GE83Hm2Dj*05Bqxy} z*n&)9Y6u~Wir7v;KoJB2#7G#Db4X~J34`4#pvX*)NSIoX1Ovea1e!s;hkoDpH+=X0 zaqFu}l~q=e?6db;&wAFg)>->S@>r%4j=Ej*mUFyI|HO`X)He<%5nVl<&)%^K@ikjpP-2xG>EJLq9Ijs37@CA z{syE4aBH)P8xMUiYpgiNEHt`oRE@kFJg?qYjB~M42~SV#!}wY9o))~n8~$9gva%}$ zkx6{^PE8?Vj0^Z|;+wMyLpb6+HaKoQ+$H2w^o(?f z{GTf9i%Sn_g>AUtflgh`dT3j{_^}TeDNekEoUW7HI^=LsRs^MW7644~a5^Nzy_`WI zKKc5cT=s^e{jFR1_0P(07F?!IFAXjSr{~ml9q->a>~H2qxTxkIz%tGK9_uPUKvdo7 z|H@+uo>~YlIC)8FV2`_2@9%m#lj((l`=5t9?F=BC{#saQd+}ONI9wSSrPW{Y{g%@i zQat9!q4=U?`5V^B_m?~hZia+?w6wiH{?qV<1yq2oBX()u&f0yOO4B2Q?<_{yn5Ul_ z0u(~7txOf}01)fM|F89Lwt&~xFSibWhldEh*NWwjI(@;p3>JdB9=}5ExoEU>F0|4W zX9$}P^^>DJ4K1B3A~``&4vH15Nh(Ck7qtfK=ginuftJ*P5noA}uz=-r_SO255YBbb zS6bmNG=Nr|o!<pKd^8^Q^m~~jYl~JNoo5BGTaO0 zsLze&KhM@x50oBT4bc*{Js*!9A9jD2h)hSmnZ5dLN@p8d;WJ@br?a?ak5v?0H!LN^ z+jwSDi!0Itzb{C|7r(YX`u?@S4REIz+09;b`TIQ6oVrMKuL5u1JogFz1*JLN_fvSL z4tIk?4C~wOKAZ6?uEZnU!op5u=oYt7&ACa<8U9~>FXN=#>HlJ7S4kadUEC`F-RIi< z4_Xwg{pCleUk=O^UciPxmUvLH?TyP5qxPEpT7N34&se%q6l#;X?CpjfvC#eqfF%TBDbqo$t9VO?Ee^>J8Q$ zy+Qh~Wh<;-1N{(`t%!ReG3}(iNLE zgm7NNeiVhch7_2JnbPBdzn@Mk5vtOw*#6RMX7RjheMi(bX=+GuE^^r!HrTleoZtR{^QeeJ-$9UmSx z@rt$y0O2!BVQn3D=_@yL$my@9wmmV4+YtRbS*r@CzXxc;8l=f?kv8NO{?z*Wbyc>j z1@26K=bvvDk>;Hd_gXs$`gUiqVQ0l$BuuW&{aCV(^|pWGO6WBeRZd-^_w$R_!)b{Q z-1JZBVKz!(|9LtYC(OT|?wj;```=~-hH>#Obo}|+4p%>)0si@Nt5?E={dLc%IJlmD zLQIW=@GApwXx&FUTes}ua%8TSHLJ0<&PyTja=iqZ;*nm!9X?7q9N$yLrzIZ$&0rr} zXgJPHFHmLYZy#nvHQ&>ZbSM5)XQQ`d`K&4@U~M5v6f0+p0JHL_HGX%W%hszCUp)jc z0f56SFn{lyu`I1BP6;wG8VPsDm;RDbsu}t{Z-qNwSN}bFou}*js2N+k`CIYqzEbM+ zrq8eajYj)cTgOoSGBj*6>a#AZIzD^CyTjiT3~8uowg>gv6zIurbwO z@^8TerT;?FSC`Xkg#FF8FNXeg<5~F??aKR&xlbXTNrDeD&(-)pOb+z42bFk)G;$#U8ctE zoR(%lz1f6HH{PeNfDDCO`Dxp@CwsMNnE`%>w2)p+`6_z;Ug>Xv?demE$w_JT^)AB& zNC92c&aD_wIK`r!Vu7+5ih!kgcK|oT$kvbyZgYNG_*Hj7LeKpANBQXgL0J?oBuPJCNLC)#3R2^=oG8ouod0L> z==Ai1`9re>%IrOXv-zFUZApP=k`pfXIT^s$&@sgax_3TADyVk!t+-m{x(^_0TrU1P zN9m27%NE?8$#44I?Zp+yYcdu83QNdu9~C$NJIz=9zd09L7PxRu3!`-i3ja-C_s)=Z zaoz5!hwvWC8Nq_u*4f57AG75CYyH$%7Ypr$N0j4bJb&p=3>MLP$oacael-wVi#B^| z7aP=r+*+8HUWiT{zwlwMEP;fdzG-zPF(Xu6SXlSQ&cmXoPl5Hd)SO`bqAW%j5PN|k z6uuWaH~nyq1@7YC<5dS#EVfwTM?8}+V#VgajTEl+Mm&jisEI}9vB)sdYouyt!t?QO z=j*J82bHbnadh|UqJaxRwY|b6H)-E#1&aa?E8FdsW=%;|@2Y6|pQS`Lw)z?Y^WZ|- zqyEaT0|ch?MkPy)iwlKtl+JY0vIn)it#R?Aum{FzX*n?@txMmv=4z>5nXqcaA+-Dc zs@vK2e%9pc&P6U3hr%s(T-KZ#*f#ywz|HY@w-1@TycYFgG- zxKb%MG=#-h1CQa>#Lsu-TwAL{v4+7weL=<=HQ_wJ4!Q%DCjx@lIS+9DXa$f5p_h3s z8Q4Q1PtcbH*}NSvMKKZ6%5QWqmxYAp;@2aP_wa=&aQM}@u=>b|@vwu(yMb8cDqrI1+s z_=s)Y_W{qRPB2z<{d*^MmZT}m zPM_sY!|<4FIm+2d{SEd7hF~8d)5Kl=M~2X;WqhsMyD>3Um7Tu+x$(`sttX$XJq=2@VJi+jkBc9)}fY1 zE;KLGRu(N??Eu-rOwzdRbz9!>Q|F+&Uh-}J?4|k#o9%FJiN`;rzqHo3BR1SRoIIDi zyafSTWTkfcPtgY{KM<|lxo5v!x@$ogW|cii{@wjzfVl6!9q)$L=JdxSXQii4$3lA~ zW$8)Ym+0v^dK13!$DlgLTbHHjQXA;o1lpWHt&abyEdMvQ{mGZ6Awkbx+s6Emq4OC1 zTW-kxX+z4r!AO5NEg#<~rR?=4e6?E8#K6b11b4B^59`AknH(z`mrpo|ObMBh(^8Tf zzo1dM4FI3|kK0&YzWiw)Cla|>db7tfZXtN{dLOv2r_XverT0DYaE2Q_toTze0&f)BFV^+(!F!?9j&p68Yi=#@|Pu$f50bMV7OX=J(KcxpvcFIMu!?6{7tcfgraCD_3@jKq^he*> z|0|}0Opd&_w$91|Y*X>FX5vASJVdr9La}}uqpF2J9b6<{DfBYWhL(x%%4Yq~FU)#af zG7xN)K>)9qWaEr;*bsgzbJ4eT_q`21PR2ua1%Z42K$NL9ek4I?hN{nzd1B-fjjn_r zaz^@Jd!<(gvb+|iLtHSr$u56B&os=T%{_J<9^!vEpWm*GI_SWb?II=>UyNxidJtGx z^YPHqYwMKPx$|yk?aAA5-+FrO9=j7}!7uJ0Z#A|y(~-R;Ll(?l1>N`=823FNdn+DL z)Bdm75)2Ss@kk`wx4~bB=RNIQGW69r;U}ms0h?BZ5agq1cOFjICJA8fvF0e~Jh-q-!3`vRrEYZ<4j^ zv(~mM`utMH`fDl6+C9+ls>QKiaKXW--7_78jQIhrsgSn|Z|j6<>ul?MpG7LM_lOw@ zj`Xyraq6#>W5vf5Xh;SB`8!GF`YkJ3c2xA`ZF%V%T&g2f(Mn2C)HHm2*v@5C{&5Yk zR~kLbH$Xjl*Ly+ev0PRHN?s%&QId_`--%>=mRc7l-U_2fw%k$}0xT|eJ4cz(D#;oD zEd(k}!W5f|)S0p$o}OHvMvyRWe-`huisMF3KDo8eMSFk2-F=MFrh%6^pX+0UJweBFk}6s%YRp|mIu2#eQB`nTNf$W zcxT4(hwf+Xi}YAV&)L0N|5FeO{$qCX?9ROLA(H{4iW!H8(oSUe%b+#6ZGA!@TXOvA z5MM|5eAFd)K;S}0djt`X0k8$p)_ERIC^JOMgjFn@1M>?Bv&vplGx?&o1W<6MA+Z0C z>y83;$-ryU2v#$w{}takQqw&+HG%Gr zP}P#Z*PcI+Qyxj%S!^oB;*n{1JCika6WGO0IQ{F5PMJ@%APXj%Ub<3AJadakFr@7l z1Oz{ZQRrn)Gi6$S8dtiabVz=swLKWPbo1OdG6SbjtuOVyLfroM)Vo5fshuZ zEIa_zLfRme3G+$gk+xhJvdJlef{qwpTP9ns_+(@l}dQ;<-d)by0WAp3zb_q`nF|t zXOaGwSuz8dXB-Q692txLB3Tf>-k-s%d8whdTrI02M+x2JGuhX*`AS=q=l}o zuAvV~s@GL#%f1zE8(^!hmjz(ueR@B3v_Fu1l6ANQHYJ>waSAB=<4miuz+Hmeqlu>n$?$N>*>yUtkS*j&Sm92DHzeccmIxVxP|J~ zk1?yG` zj$cy9wly;Qwr*a(X^X=_aKga9tK?1sunYG^cL#lWlhVdO3zavwElyeeA~{}l@VMhK z752T+opy#6^p6Q<2l%hITYLVPkl;$*zG-6r9~;Zma<8!D{2nwsyjBtP;3!{_^ZDvl`;1cuG!N4AWqy`V_$_2Qg!S`B zRL;%jN=)P?F`B)3v&`mc?;HcK*r!J4|J<1GGkiUb^(mEpjwuTl)DoI75AWUKvffP1Y06yvao--Fw%dV*-M`z4(?hHB{3Z$d z59+;(8w83!^_>5C!#*XMfM-{?`}=QF>iA`DFooY)M0#xmv~^Iq&x&IlWMtm{etx}l zPu;x2kHMm@%`Y{7;E0Q|R#j8Nqb*DD!yd}4->*-QH*&{MIMrE${J4E+?+<3}=v0$CfxRZ))n{m&1 zx#|H~Mdrb&E2=rhmD$N{>z+Mj`rj{a3;a0tRz?nQV)PJgfr@79$L=ws>McKH$p@x_|%9gMH^GE{2*QgHgDa?4};$LQQ^y!(9N5lQT z+KaUXdQP8X>2aO;;reZ%wcNz|<`5^v3dW*-%dZ{gmmNg?E6rCoTJpKknL2^$p?_{z z_rmsI?6J$>+1hQJKbXS7?szzy2j&8f=wej3jV<7P!7;zMXt7+SfgB+QSHw^#o#inz z$r87gv<&2nAd-Y$Kd-cn+Ih#(xUA@K$K!#g4g#~~t7Oj0f^ljo(F$*JV0kQZ`qUTx zu~H4K);g5@Rk8J)5m@GZIC#!2aPK*K@a`5#_1M&mN<;CS?dt9^(AH6L>J!E>LyTKYCJN+@7=gt$reSk% z2y;PFF#wL*Fnz^B_UniFX6wtF@b%^ggH7KKFIto$*H%6Pe0w=GUX7#{+qu&ih#wjv z97riTH9BP5j{nr8Y#vFW>Vne~Xi}M926hjh2Zv8frsJk!vdTlz)7>@ie28r^r9^q4 z5AOxOSrujh9*|_22ZTd8l(l`VTwD3Sx6%U?o8hKu(6iuEG+OE0CwTQ;3{9bCb;cPt z&Vr+dE_l2}xpsC$E!_u6t^6Uv(sa?Osd@d4;MnlAp;Ib8k^|*k9>`&o1ON@X#d(4* zToV>J87nerQ3KozR9O*Qjnl!#D6j}1n&E5T5edgl>L~GW3pmGD$S6u7$>CXZO;Ic% zI7Wj=ODuk=37^wHCce8g5D<0UXnMLNZg8fF0Q~Z~(jB#q{v1Pq=RLsj%P2Vf-={%< zVJwZ)gd0WF_hOs;=##U@H&QP9xTl;d8!HdYW}xqqVe^JR}1&>G^V9Z!21;g%4uN_0JEtr7*M&kUM0$u@53f~RW#+>)6B_9j) z6TcpFF6o7gItwlDQOdPr7~b$qQ5>~XiD2OqG=J4&(J9C;iBZY{r+`bM=&(VG(hf!m z*ycApHWoPgZ5txjO`fGJ5XDa6}abq0VJes7rzqJwB&CAHS#}m-PD&*9QQHVJg|Fdv} z(~-a{T;%@xZ5pfTI3Qkykqh&f;u4mWqy znwH;*!Vd%2jJd!?bP-}Oi0?^Aq#^>93Y?-r-RI)izF)ACE&T)A*9d$xq))&xA->mg7_UnCvp>VGaP zmm=550$vb|!J0`MV;f^Qw~5shj}+s)R}|kEh$J4MzmwDfIxVCzD#Zho+OAlohIm&J z3BF{FL`i)abYvvA+e$GQu@l5t9MQ}Cf0mdF%u@(p@gA_%2K+QuUac}FcJ^t)QZPh3 znZZkGBSR@g#+y2NfQ@D~*%IwL+Zz2Pd$BkX0AJ#WA^!v7s_CH?ECHkDtk##^iM3#f z?!&Hpz7&pH%3T@=IlZlo1(h?5HvpL@pBNe%>iyU6BL}+X<6sy8n7^d&?0$capibzt zMB!cwS);f_ku|OCZqb=D|;6u4IMdAUzkOcV}umnyj!{9_i5=n!y8Sbqv6tOG+G{zNq z&3>8ZCKf@}?arzIQOxJOitGf0S>WH#yvZnvoQI^y2soLvzazvyKfYM~-)I75{M(Qr zZ~|1apOKh=tCZ-^gPx=p^{B6u0AyTAcF7SlLvzJ1Xh_=4K~#5wq&Pw{N^$q2O>SgcH)WaQyCL`>S{h82m?YOXVshgr}E#L zT?SqX1pG~Hpf|hzUZF)qt)%u`OnMB@wG)ukvD{{R3X&if8{t>z;`NaO-9??j4nD5L-_trg8toD|e)VN^@I*Q|GBJ|`L1 zLI;0t8**cBc`ooq?a*6P z44sexexMhWj{GR8k!NEJO-qO1@KX}+l;eV2I3(AZEcPRi(Y)!zBIs~5pi>7*3EI;< zaYqX$$zYZz-IMGK47PytT|PvLFS_JOJLhh`NEBQSKhtUxLHjB07=onOMkMx4DVQfh zJP1Ps#fAoX2=;F5i1`uBn*Il4{uRcNV9C6O0l-pBdn2`*4pKTTv4jspgy`S;|4&LZ z1N$+G%m)Xji;%G|F+9q3KMRQq6ytNzgvm)llZv+9s7_Z>ae7SlaloeomrVgAbUexP zxlHk>n3gV4!X)+6iG=|y`VD}+I^(Ii0M?9x!bbmTsAC$8j9MBsj}&_D?TD>|_8OXo z0kDUO6yIdwTiQ-0uc0(ApQUV90{eo&SU3`~&w0v!PDfHYJZ#G^&!J!A6iRFx78s2LWe@QX724Md%&H@FJM^V=YZ&OWIatgctbc57@6vftP+&` zE5HD)jmYaVxqy%emZbs%z@<7!6Wv;t@V0RM{neRfA0+}dZr%W_Q_o$PK*t_II=md< zJ2oDx&Ek7-vMG~ewr&=kVVR0T7zJ$=GE73(9>ceXNR}HV-cV|Us^h7A zorxW@OS6eZm}*o@JMf73-|UBFwiHUoWJJWxsJ|lp04cq66N!>?SivwG4%KZfk?>kM zj~61k%h3qwK)BJ`_97XHg#SfS{8@okT8`j*pBh2USHv%AQj1$%?MEmN5sw2oz2H)( z8U=;&!w^X5I{e(i{rPxTKv)Gy)@TlxWrGJ`l<8ag0U%>nRIV$KC8-2V!ED$OEJB&i zV=&mGb>I-fej`@rwSXcB{dess-~o7m*+)U-{=gvwvey2~(@RXzF3Oj*@}WE69N0&y zS`E>xt<8yrw&9!FDJXYa6(EEM&dcG^t<^dRfBz9#|No*vn8?Ll6}30TVD3OYv+-Ii z=jFi2X`?Yi-Ip-0K!gM&xJ5mW+;Rt`dqr~@dgmnCU|29b(-`b@#2I)w{EihyH@Of1 z@@xojAYD>iH$b^+&4wnl2g=u=gu3HhHv<&bE{JSHph~P-B+rnF5P89qic1S369A6% z(>0TWqkZrf5xAut9vE_ypvyCS+_NUO_KFdpMa*|C3q@Rj2TDChkz7wwZ+)l_UGI%s zQopFv=~9NS=w_Hxc6k7XSOE4jLXLcC0D=jMkYth)7gDNQ@esVY*GwLOW0m;E6@w_$D zXy^tUmj*A1RPd5U1z3!vL=`a`%HbTp82%59kxOG@ahnJO!#;!&qp_4zvs`c)d=Z-h zA!$;J?rDO$E3jM|DJ8&RJ_9BxJfe1Kf7->0km*r;EX5PhS7idEq}&yX2Og|O^-GGW zRAtk^rZ_2_8FBzg+M(D}kL%a`uqp_;h=+rQGOQ!Th*J@9O=3sim@SCWNd7}FksHEu z86d@qo^&1v8$iNLJ7OfyGB8+r$zCHCD7^&Z(OZC)j7#9SAOsBC1z!eEo<_3jV#FQuW#@mLJKh_C}l zi<(L$Kr038mqy&mAUNJ*z7sfE9oGl+GN6ZoJTkq+9pjFKoW?`ID-hw#m4Ge*IF&L4 zM;4(QkGZ-?KGEv3aRLpf1<54eg1vroIdsjO&}{SR z=@yIF``VNKV@5~|5**1J(Yu=jNfu(tkp@w>5;E?SnDi*CLz9tbJE4glzS`fZZkbQx zfupojOG~3KjkCaDq5~m%N^I(9cA0?NJqYh`e;HwJT*dA1U;1lsIVs9}Xyb*KUN6-P z+e(%!VJj-iVe~FcH5=A2C+BESk8vPYGWXT|j&@};k@*1ASpfUd^}P8!;t&CxCX4o# z4@ZvpMvaMF)0J~);64jdxk2tLkHNwAD$;NB!T2S*$ldWN5HJi|kAYcxtIxOd5x@8^ zk`9N1RI84v(KiW*V$eFNPIShTujCQ&HeuS8u41v+oUB50B^Z~^wWv`a!q>Rq3wMfZ zGH~S>gu=ZrC6z!d5i=6Gv#<>;NAlsUb5x4yyn9`_i5Vf!4qnd$LQQRA5!eydWKU0n zNJ1JAJ>D1#sWZ@gC=Yzk$XIGevY+7UU6MZF5xP1X{frF6!C2LD#Td5u?HbtpCq7EX z5XZ=QU0E~@{Rx2|qhjjc%n2hwqgnLrS~}Rgmh;c6;G3hyT-!4+SCHJRL~I7Hxbr#1 z80%$YI(M9~iw99Kdz{Gt>D>xYjC8RLOOU*!n0i^d`c&NPk!jU{AtU4un*oXpn+rwMbq*AKw%wx|iM;_^Ia@_?3XJA;a^O%Y9q`4G}5? zqALwLGDq@4XcMA0HI_n>)z%WgXBbWU4aU+^VC9q>EtY_OJEC2zVN&D2Q_65CcOJ_} z^O`C~(dg%$#e_UY5vJWDAL5he06!ggp6uJ^ez#SRJjXEiM$^l9)xft{PKt>s#g(7q z0b`Xdv6(&G))F{2Oa%x=GC49111y)@3zU`YZZZUbua$2ziHBf=Dz7D7Ud(*WJ^1Y$|~k6ds$Mo3lY z4VY^r7;z4zYrPjF@|99$=p_G=zLFH2P|Q!vQuTfw!0P zpL1AlL{{kzK-Tc6^EpY;;U!CTSBpR~q+5#Uq%`ii$0`0p1TPv-)OIPV2S5Vb{}8f> zd`?HE9wM%t1(TxH9Up-+e76o#nRbxSV|7*hl6(N>6*DBo)}~=2B%XR<+ya&Al5cki zQ9Awd4yP(Pds!z@h!+@%#*JVQIF>gwgb+E6Q8NcOzv2Np50ng>fLX==Em@(+(rkp) zMSW4uaP{0vSrhyI+3PVVIv;Gg)OBw%hZjhRxp%5+5zsV%FHHU~?)IDkRmR>ko8S_G zch=B7|CVTqk)N*#5+bs#P=XON2awm|XGRPgv{i8;m*-7P(qY^Sv!>AatwHrPW`DW+ zu$3YPFIDjw_JWd?jXFEk@SnF(bl?{LmLqD;yT5E&id(Y8st(Y`MBp19!eQ!6qproZ zFE}$+tJ_su`Q}k6qZm1uc7=<$G~(I+7zr1s3;-*Yb<6pDC>O@KrfzXoqg;^`n_J=6 z#7lnBzZ`)`Y_%055SYbh)Ip9US{X0t0NCX2Oo9*6RvxD$YvIN+JuTgD-gH-4$@Axi{Z>_kW)Lh8ig*0PdMLhkdeY*h%HZeA#* zP&|DAusWx_zigEGIs+zgvwBm&FeSub5VC?+i5ECe0MV_R7ApZE zXNb>fZ=uG`yE2)&RiUPRnH@2CpJPl?pbTPi%Yaes7&I971$7wOg4g$h7ZAc{);~Qx zk0%d#e2JQ)ANayF^N30=CIEN9B|*pYGits# z%kH#H+3qQuH7~1pWZ+lDse+a5GDi{;Hy!pl`0xv{pt4-rEm(=++`Vbszc1i;p3K%X z3I37YAm#b_t|PwtPyL)Ft6`y2&igo}*ne>SCS4piwBm6!cit@aVE(CfnOhRQfBxNA zUU4!2rD`qX`THLWvO6~&vP`y-{l)RM?Dq3}Y(p;uP$sCQw!`VaAF}Ug&=1I#Sx;r{ z`SRELz2ZVzgL3{lna7!> z6(}6%^PJi^=~8x zZB9lNmdou-?+`pPG1c52H5*Btp#Eklr}-fMuF1sC0-4QP0VOYNeonMIsK~j+jMXV~ zPA|4ncKqEUgu*&@^-YiaxrB7i`A3uT`)=-$ee;Opv~~G`%sK-N3mKW3O}gs@k0c7& z8v`u&*(+6~WhlxWuGI=r+AtD$e)qeEd+!!Cnw8gWOw}o@A?E$UeRQ;2>+ZfO6|_Ry z=8bkgS?Fx1@`h|3Z!E}8eRjH7mD0gXWd6Rd;|-Sm!Sp1vrQG9qthR6%BIKDzPMPLxK!?wZus<@#fEc*4X85taSe6befcSM zvK{xbEtao+3eniel=*WVcb$20SGLpED$9w@GEdHHg*y0W6xd>UTbNNxX%ScR3KX1Q zRAi~9^?Y%u`FZl^*PA9@2#%+v=f~=4$*fOsI`V$~)mLpd_G!x)q%qDVEI%~Qm9ZT> z9pdB^8fJrfRB zc*k#G9$en-7O3U_NbiL#=Ddvh#c=uG)0UeK9OPI$+kPlUCIPE=ILb+fdy^@X)vXoi z&&_(o+;R5^DK^3Kg1d|T6iScHuuge%B++ujB4eM7?F9$looFA&;u||H!z}hah?2S2 zEl9i=crC|beZ~3!3&xEv8!T*|YGFS6?6+^@^fNY8L`1qotOUNlDZA78W6aJ9s+3i( zdgypr@ZPHxn@ld8Pj4`YUc%YD877-^MQENXS8ODSXR=QdItMDkUisV^!Co1-7g-mL zKh${bYL02Jxj<3jMw@zZ{C$$_SBE*WId9>XrKE$ZXyRDPM9M33+9^qW4b2?f0UNBq(~n5868C<{L_xrW|LGB*Pp_JlCv$_ zNXboDmDRZ>p>&L65}~N5_(RnmP3=VVkH*GRnQpba-)d?eFbp!(jpSCRa`G!Jf$`fq zIo5aI57;+z9KC+-CK5=$v3E+FU2(UJAUMm+(#cchGrDHB4-iT^LP#Y(L~Iy9D$bvL z$g1gVBR`>+T#Aw`GyKB9vV6TKrNKa6GU}pvO1up)YL|FN-IWq@6`))+u<6X$=&B--@DHe-O6}ZHD`~CM z;nqloGlDN6G}18aqg`<&5jZJ+g$Qma3>D+rN$4WFsyyPDopJN???wjj?xz{wa#l9; zkdTh&=ongJcRAS*a<(|1wLnTp^PV7G_0*#YVN;kDK>+80hjU*-np*%NcgT87Bo=Wf z_=kivUb;=P&n5P8xX36Uikmsu(PuPZmUE(NsmB^pHoL4L1TI17Vin8VOpzG;bU#*l zk}gJ?u;qP_OO~C0@WjN@dnS0&%{lELF_Je9d+#|8bZ32Q&f%9H3l^0FuJv&(OlUTL z=rU3hut#^q)ScMli-!qm6vdAGOQszO@fdD>Bdp(Uhw{i*z|2gY%Jo#>D!! zLJ`x?t`wxtdG7AtN#uD)TY%coGoq}u2yhPrB5weZi4*9T#$01gs+lVR7XdPAQZ=lc z32qcW)2R3msC^Cx!(Pyw@$kft3zFiERUvUm@yVW|4%V>1ua$jzy2U_vgdWNxkY0)* zDtQRxPn%1)Cv-n+?(zs&dTtCES^);F3Z;2nb0J>dkRQfIXG!7(A*CBSFA23lB)+@2 z*Wduz%S@KqsceSdgS?Zf2uh1))LLNo6bPmo>L94#v6KU$2xvavAQvgheFZyUQ<#*J zFpoC(pEdVI0jZ`A49mO1$xh&{7^#e*TN{lx)k?~NTkQZpqZ4>sZ+F8wC~mbA9n{~C z^VNWffjJCbfD=+{CT9(Pk-tB;8K^u;H!cCh;M=5Q-G*5t?wpE`J0dit9Bu1}%5f}$ zU_UcgwMd4l@sD9mEU5;Roe9u54`+FZuNtvZ%)0^j=#y-($`r(9`S-xu=__T^!6Ic5bBwZAn( z2214{UN{wH%()DML;CewrsE?s96~A)k?2v=GfgSc!@L@ zl$SiMrh{b?=_RjZJu)nTD!o#m`5^qXeiWVJXEghz9X~fmE?S+jf^F37o&u|b%_%&< z^R%J9uWP97D;9JjYyL1ZYFKi>%qVnl5a6|KIDuGzDhuOUh~FvxnIg?%!qTweS-6z1l$4mJo-|%pr?(Ta4kryndU-D&U3>W2R@8i ztj3XU<^d18d@C|%b5L|0wdq|RyKedACt4NEiw_T9XneKKs%`S2* zMlLX=ypW+%E8~UGoxkWGxC2|Jt5{mp0nI7LqTAc?>Nqti!@v*e1_yJ|%;-$QmG*Yv zb~#$j9`^8qmjBK?d#KR|z(DT+hgx>{QnC(wXs?+&-gpy;o{r%HzX*1WTe%}fLvI-W zAp#Y@(U^mj=w2@+$MuC`fY-IpKE}cE?np?)vncwT0pFs8zu$RYVf3d0q8LuooIs2r z63BBJMXYK)q#k$x(FVWydc~uc^KfwMEd&T_u|iB+o~M64lxq2qelu%zC564$M@aKR z+^*RV3-k((K?qdQpVPHt?yeQNnqc1}&R9IKZrP3YSyNMq;=vS)+5AVCPCVS~eCYoS zsYV^YwKX%Nk;+mego*p9-^fcQiy4yAvqk3Zv1O-$YqKo>)#GrdW5b5<_9YW?LPB~?Et_+An4*3<}XXapAD|x2T z#~>e_2m*6}Yl+;TRl!lRA}ScEan-|fa{#>YlSN>XO6p#dXwo#~YDws_!K)^$zNJIC zgDtO+c8t@8y1veEcs`Wjc7LLqjPvTA$yzolS;E87b3n5QQb(q))-L5lUGu>s=bOq3 zL^Yu~02|>>X4O03qO&%;a)a#N8nfaBJ5= z5lDy`yR#T-a(LAVKlRGs~9QP3Fz{t{c+nQ=tK(PK-2CUt_8SDT$-3_W_91&(>Z@pK+d zo3vr?6N=>|Gw5?69!;w2L^K|@4w%S;LT;G*0W^L=>okOkC${6^>-)iZ{5H|5q+|$% z8_+~IQqQ*6-b;C=H}|B}?Y=(JN+S|YDo!f4*1(q$`HMe$7!iq!bI{|?&VaCHb#UHv z5O#Nf9e1?F12sq^7@4ekfDCtL^PeGv9AX7Dp&Tv?OQhI#JbPlB3rm!GKtu_?yek~+ zYH9ccN8Usc5!I7-4~9KN<%m=#Wa~=$G>)|ZSz}^R>s?8?nq$JseUZ`VJ+l)#qq$_D z68mWALYA!)Ac_WVQ7|6j){WRCbR8fpIb3$<0LQx8SsnHoy)^7+Xs+6>ZiRb2kC19P z{1)s(93APzE1&bKZ$X@Y=p5`3Q*{L_J5`#yv`cL!tkZK3#IMtn6Cxm`X#i4ev zUd3eWy_6D@;^RzkLeuZEHPH=`Y|R~#YNT~!e1mI$v}lQaqOx27a!Pe_n8c#P8}%=N zZAN^gdlRfD??vKT2?*nw$WNZ2TlrwD#nNx{US{y?X6hYqQCAdl6Wx?|DQL)EQmhPMAzCC1LoT}(0x)m+d&6tAq)aU@P)od3-dy?nUnXjkaoicKj);u z911NYA|1T>JOdwsS7W6mqI`N_y39$LSb~TDvYrUhH3w@-=6#;{y#`67*Gnr01e((& zl^NzpvAO&pxXMJjA_uajZ_j#pgW}qben3bs0ao9EMyz{Hd(AGzRJDb~@WCt2E=v*w zgKi-95`*cPLzA`;T7X`h<~+EY^%Tst>g3arrd{y3Kw$7}s-^q?A@5D2n#%UR!CP8t zm1BdTGT%oWFajk)m_fM;TxF1$oP;SLU>L$+VFNKi#X}?sxTi-?iRv?U!=-p#nL3pZ)v)rmcBMob?6^ zL5y%+4!Jl2H8>WYDRprE2rc{K>xr35a=bW#=F^b1rls2L~xF?v<^L4~>7#SRZ z<-{~9SL}gMdyMkmU%mDr`?h^r!1%nI)Ed|rrL>UnnqW9i>2orH?qk}WE#>PQwcRPl zyy^@?6C30ANG*0OhvZBtZR|feN^c+j1WpOFR{z^(@LXsyEsEwL%iZuq@|0b=HESYO z;@!%v>2I*!@oVR`-c%XC7jj(7l8U?G`+N`Uvp*K2oD=xwZ0;dLE_lykHYW>OGg8HI z0F+=D?dl{H^?a_wMhd*5l@oU)u+qg{Cfhyq>zN8Dh^i~Yr%}yiae?$>&~0#<-ZEc~ zf-(nJTs3+2^g-a-kn+Uw2&U!VaxK@9zW{_Ou7V~>)FpW0pjW!RDt<4u$vYdyV8)ve zI=RbBVu=ju@I`8Yf+`iORbD~t|{ z92^M>#N?D1bRJDqbd0=YPaKr4Z>WN4#IY%l0Gc_l%xN0U;9vD6@&{Po)z=29;8Su| z8dU_!XD>&S)Yu3Mg1Ty!=?E7;sfEaQ!J6)O7j#AHC?xpFtQwgmS$rGct*rG+_9FCi zMT$6xDWdOzyZzF5wq9QW9U7Y&9}YaL@is7KK}>C4Mj4pax+tsaou2v6`xtzyE{PVR z+S6Wo?`pd6$8q~a&bRcvUC^ph2TOag^(_2*DOB99@%+C{-QS&#>>EszXBcg%`p061 z(Z;10_8E8j^3GV{eW?Y=z{WV|5`)IpijtF+-M;`e3XKWbJ;`_2AeCL*9$bbG7l^3D37c|>~ zW(M5JFvb($PhB*6KqKEc$Vby@QsN^gp$TSpBR``*RBtT3wN0;NX+AdbL;~;wVG4NT z@$~pSFJKzT(X#J-fsN?V@SJY2hmF9Acu)i*C$*Q5d=JNIX>UsLvIdLkZ-LaZ2t_U? zAU1|nF+B+eK7M$rCYZNZxfRzJ0)LUV3J1LZ-}qq@OJ{5mE8weDh28g;(P96}=kKO{ z37{Dh>3}~9u7v3L>R|8832zD8%inkl_Bep)HaQwK-TVW`H^AX7EezNwv?`=TPISNN z3(%?aKY<(y(5aQ*_@M&%MV5~yBbrY~z}@ww z)fF+C$ySV@EV?YZCu?v;qtbNslw}^x=J*0!05LAGXf`ml!w2|9E(Z~wOh84?QD7BS zLKo4pP-IYw0yx36HO59Dx4r&7xKPfqmSydrxi z-Iv(#Qk{D#e6mPo^D=N#Ug4$g8~I&=VEeXLo$qX9QLImgO+50uyN6Ex>-IaBL7T=F zyE4wNw zO%?ChD+_gox0{&LZl7%PUVJf#c*bJ&EmZsamYy%7$UmLAKBbC}d%?(WUF%e&O5rv$ z>^27eG^+aP%kDFQsSyR&ukJP~FXw)fe1kP0kc-ze6$zgBS_lgF86DsM@c{1TuDb7d z5B_*JK3g$hX7Yj?bGi0hqZ4)WJ5~n6BW7fB_}RKV+W8&BHvJwGzMzT7PiJyHFz~y% zptI#8Q_-m@sYwm-JC7&ZylE<0O&ouBGTGmMDtw=J?0#Q|pW^a={hY;f-EGLa zaq{(ly1U24<@erT-hO}b)W6#PI%xEb?{6deqN5kTr;qpVyMi};QOM%l7%Ge&jvfwS zU*`yz+|Ua5;lxw1mnb~bcaL!4ySzZp@RuyBPcT7ZK;a;;~_VU6d&Zp$|eGVTNO8-o2 zxzYQuaNo|n;pm?S{N6F|?(96eRQ#%ilk~$97madH zFKM@K^$GYG{q*GlZtqwtfx0#JuXZW?r-R;6&kqkoU5^{Jj=KKWg=A6gqHj@m-~aT7mrxgo_x`odCQ_vS36}I`z~r~H2SzvQenvtN7^#`>J987lHCTvzbQ)c zj=S{u63b=k=ss3(Y{cO*(bk_SO{J|mQ{P>M0W&G>1c~MYIcdiDER~#%p?r)l6K*{=T%0cPaPS%C8YG&l!bI{+YYYt8e9GN!iPj zzpQb(IsAO^n>9zm$?iVxzKNZC0#tT8$`7_&tJND_xN+E~GId|6sqgfw?rz?mO`;^B z=v6J3*kU>=-DikCY$+SX2dwh2>3HbS!YcoE_+Fre&*;_&6P(Sha_QvmVp;gx7sEE9 zH{8A{v#=5%0^Yd74NN}0s%X`G?Za|z_#vZH-`(;dFY)hvTM#^|GHm1Wtn3V%`#u>S zdT8)x(}nWQpID~?B2sQ1=@!l|Vq!6cE1LMzYI9t@(C-xsoK46G|5o< zlKdv+$486|(pr zhP=Io>8o2?y`1c9sAHT1*gaPs%3_ii{)#ufq5p?r*1jFxn|jrL#~IbpY-4A+y~3~QE%^(o*MB}-&oFVJch z4>$59oZ8>ttH{lhD({#X&j^2pyv$s6!a?$*y~_{bYlx;FWAyT8P^>H5l%f_$zim7^ zy=Kj~fuD!T-{u&Un#|km9;Q#W?pa1pec-MT`y1)G8FC`-t8~@LL`~T~I zVF_t^HI~qOuMhrJ^N~rZ)EQ$VRoDuMq8*}XF_(#BLopm;$#{e3xsH_rCB$Oac*cj3 zLZAeYlS9dFup)PT(??yT3P!uB51#AjQ6N|s;YAFGSz%4JTX49O=c&>f-Pxix_r(be zW^fQ5KU$(Bnd_qH_~R|K7Z@R$3!G(O22jnLrZw;-68kk{nZ;9C=JZrFP}8C`L)SSc zw|eQ2V9hM_)_@I2Y$&p8$Uogi6NG~*5vqjI0RL+R$)Bb^SpvgdevS`nt~;N(G$kSf zMh9lmpdd*V_)!`4cdWd~kb0sm4P6IU`&))Ufo>g|R-p7r+Nu@@bkO-v*vSS&0#Lh? z=QAH4I#`emRorP(X*%6&H9}Rb6aX{j-uymqN|2--eyWiel$04n0!T_g&F<{PM#0oU z#2N%)O>22H^gYDbuEas3z9a%Igg|3Ac!e33HbiAl9)#cK_a*t_Cxlsm%solH2qaX@ z9HLqzspd3RDQn@82h#P7hv;=Sciw>O^=&e{VBU>M^S|<>LO4P6rzgX`6#t+Qh<+N{ zi)aoy9(`lY2L(v8ZyLN%9iGvI`IaJPQH4Y9cMx$cc$~TYWpbl)sTEpngo5YK7dV^F z@?lkE@N1AqbKj6d3L%^(!u=Z%5K;Ijo`xMF{Sa!uC^E@+yA$0wr?#dBeh;4gC;JxT zcnT37O+A`i1LntZO-EgtuqgNotzg9)#b1LlUDL$D%-ht>y&2mXb%Y@+cQHuWKpDEV zNDka62Z1SAid?~lorE9aAS^tXvE7F>4T4|iKn@Kj2ilSdpm=2nSdac`7ppE>7j1^; zo9c$3_*&~er4p(-pZhJGHPrx-s%&02FvNwuxfjtTSR$q`J=NjowQjTh8{rD6VEZN? z^St1OQrGPjIX;i1?b99l+CxXk#1mI*YP!^pZtsn?A(6PszH6$Qnk*85vUZtfdKJ@} zTE$zrn!ejq1-}GNZAbLFmM|1E@6u*G7Z~Of|7y0gAH?}$i`CcOQ7;bB+u_c#j8LEu zpYUpdT>CfYQMq-51S<1k8V_kUxTj^qarrvDMy8pR%?J>DyLQ(nYcK!PrO%|_H95|$ z0XgInMRpUn0XR-|CKh4D%D2Yb<(11&3q1;GjNcM9i_H1PAwpk;@(5TVOH=7XA*K!V z^cgVi&meS@?ZJ&zcL9;_Kh>m$$4y1gkMqQlI+v4g%=#aU{cm1Xm(9GZkeqbQM;^6m zSSxg>mF3rzWY*LO1mL$LmYNk+A;#f~2RidU!uMmATud<-wEf(L{zQKZv@D!o=)Qh) z8g)HeG);JSh3lv#M<`9W$QC(?=5He2uSVcmlpzAb?t7>79Y7_7Z&q1D&%a1P?)3q> z7A)NcEp%%iS`YV-G(Rhi3BRdbynIPE)E^wiD7vKzVob-p4dxz+9+vYpDJ%Pjn##pU z-7n=KV4CCu(Hg%RrScHY8TLgEW;O6v;PG+>S4_{G-$J5AMo!>KzR)NdtC@Abbso@% zKlZwHS|UP}LKsJ|_6;@ZeR4WJx8aUGM&{mt29|3E1jsD>rxTPF*w1Q09_XUs=jl+! zu%##g;lhi+67ih|tjH5ty^h=&Mnlpn4)ewGtCBs!oBA`0Tm?eBTUx6vY zl23lJtZkkPBE@}uh3qan32d`+ANo(B?`8%<^Henm*0*xWng(xBJ)0s@l=wj@+mm3v z%-76oJ||ZU#d}lB=*E%A>woki5bN`V(#X%-7mUzd@eVVLy8TF=1zFeh8Np6}nk(ysqQ=>^Bh0TC))N}B62e=W! zs{1bkq2P6{5NmM+t{fY)V&ChdlXHB`>GUB>xg{l9Nwjp8Gz2%+Lev=-(4kX{Ql2%z zF>>5Vu!GUF{KW}zJS8-ZHe`VYVI~`(B#=Eq$$SJJAL=1dxflL`LTeOMf&7G*_QCU@ zIBwsP(Ba14zjV?ndgMvJcg)~C8LmQ=e@&`(&?=4R{_tH7krI%MX`ce=-RB8>Iu^ga z0c|-KP4Yj2gQQg%*-eOXYP8{#TR~``L)#I&c+H*uTQpi<710Vs~ln9d?Z_!7D;}IJZ>~rxg?^&EP&S zau%}=Do^Wchqr*0gGK_%|C9f?7O-5eYJdqfg@KqaOp|67jMqZJZj+@V-*A|UaUXjb z`U&FIz^{@-T1wEEcAC%&p96{YR4MysOsurU(eHHw2+7m^Xk@Z65r{f1#Id*7pl@>y z$FUm%XSmeK6KerW;XsWT>n z{qqXJ=Tc86Hik~Hyd+#$4?KE@S)94do0#s1}2@B1t#BQ1g z8eSPy{QwFB5)3>k9)sjVP9L`8D&G@*@sGatPuQw(58OUSez}FDEob)0T9T$Csj`ce zgRhaXO+c3Z*~%$wL=1u@=y`;Gazl*+2aOTBNwCI*U*7!>AN5p*;P(!=V=mfY_P9`; z<~=O!fQ9Jk0b>$Rav`U3!;@-kcv>@f{8jeU4Q_xuTLmwLcf5X|4lQDMPHU6qzR_$+ zROk4VQ^Cq5cgb=YVsYFU!GA&oY6P+lprM7dss7Emf-VTdt;OW(nDf@K=ER*Js^D{g zi`INXVg*R5JCpvX1s3%@>QoJajm5`2cmq-iQgB^zf^>b0_xZdhGiRgDW$NK4zyxsf z0hE8HVkpE!`ki(QJrin4{g$vTjoRGH?_$?twm_^K`6%!*Pk}d}K^6Bdfd*6~szCJw z{+To#jfW~r4;Fw#%i1%|Y2e9;(d_rep>e(0AH{h~K8L9y(*}eSl`BP-f%f+!9Xc?` zUobjH-GT$|`C$yBt?dwH95e*LXm~2W1W&RAeSYrJ+xT+0g^0@057f2OWN8aQ3wjJN z{UV4bfr2YuU%bPbcGGm6BdwCl*8J1Hz`Yetupri|6J%ps&Ydt0*JyrbivgzSA&i3} z23d!ulLW=W$-o#yLu1fkkeeK1E%#idN7uk|AZN;fU7@oSh)N$CF`RdcBQqdx3*lGO zP>L1`f`PgH4)&NHEW-x(i#o-_PD}WlC9v`2t_OxP;xu6d!A5}>9WZ(sys_3{jkQqB z99aR6T4H40pqO)qT*{pKEs}a+tdG79kd%$LAw^zIO@g--yI=+gaeNzl_>3W}?~q@) z+h3H0haUE%yaom$aRSi6M5tokMY>*wbP#(o(-a6jBfp&&Ub#bE*)*>AJ8$54hE{7-;~Z~RI~lxX0)5q8381fV`KMKw|xW-Z(Ox3HVj zb77D|?1ddiu4`$YJr+kHyy@n+@FgD~8BYrIqvy|vLm?s1HJ$yeXE5^mE&+|Ja%T%l zdVrIu0~jG%LgD|k=V3rbyjy3Sk**z!14M6owbMDNPJpc>)&C>S~MduU1On z02!juOwgFuVr1SW6R0jnGie~qtkFnX)_SUI1T}{oW^3rtWG*uA)^<`nGYBscdiVDo z2K6*@+(c_8Sez{xP^cOxp^xEI=yg885X@}26E9aRj}a(j=ye}|X`F{Nq9ZQY z^ZFu~H&T40yPkPv^MS%SaK4q4QLrnjn%R}yu17C$J{G5zAXj_A; zsuleWSTV_I-qRib1rh=dNB=B0P%Hpr40j_v|^ zkdGb?%**ldF(waY%auU*9z^t-uD)&bg>fgUDAEr=(6_n5PG>N`!I%>vxl%D?k*gaV zL^dgMS4#zTAj2y9_gvXxOb?$l|JTb^AGSmPI-T488I9z_)xHo`&@UBz#dm_=KUPit zM)vy@89&JfQUC;>x7fxBo;1k*;ZA8~s__YwnC#)6XB2#QZpGkC~@&reqnl=kZUG;9r5 zpQhtC=ZdsoshxfYKP~k|)V&|$XPt3z@xMi;MK!M%1~{kD>p&|6{PG~MJ}?`OdopV# z4r|U@YYGYq_MA@?7kFOlD}HOV8CjRRfP>(hZDpxzNU`d|R(;29r*kwBu<}WzLV>Dy z7$c6ExAI^h*OtOcNObz18tG=LKt%ZGQ>AjWIn{R@X~_%;u@pP|Ld=ZU$Z`hbBBtJa z$$y+Hg0RLG)HA|!@Ms8>=`^ly;%RbTe_gS_Qqu||_+<{{@CvR3ZW6k^S2VEqT0*ap z7GsBb-L`*oGg1EFODv%T64qf!;)|@eTdMRL5Rpcym^BjiO#k}T&iSB}0&F_s5Y%k6 zwx2CnLetz!hHO2MP3C?~p(SFEKxgE2qHs}5oBRPls|fM$Q| z{B1}M^j1@0iSB<5CRs+pwyJBSBEUyQwn0UU;NEh}+_o)Dq%3E~;hFfgVz7NXZt~vq z*P40)U=g4(0}npZ8TT^0`L!4ueK;+R+R5>hil{CY5hkyZ%GZc4>@NJvJoSBwF4J9x z^pW!U*=kbX3bQPB;hUdug+g4E>|KrHU`9IIlqkG}5{R}t(a#u^jV7hUb z+~>$P)pdBwwt$o4!r{p9n*Js@R!L%CY$2?Oakc*qvRPZBc1q~ZWi;|T!~mqPiMAl6 zEH@`Edn|H-a9NqzAa*$?{Z4a&L|(I6fSjEHHF06rb!73ymNnnN%~Y9~o&%u3SF^(} zD52|M?LC~1@8u6(>qlYCi|1c%hchGx5h$sZiw%m*ZGawVH00oLaL|!lNWb&Vu+^AZ z#L?+E=+?SjmS+0ub-_i@QMCLA^#WxTLhZnVh3^LU7rVq!BDPuCV1Nh;=1>GjA)XZz z3=$k`oGI1T>Mj&LM~uTk6Ckf#OVB#fnYM^EAMQbOpA~;Zmoe*$1c*>Y55u=2@+?(kIcT;O@(J&pcg-kLe9Rc`E6%YpXtcGUJi{ zSfPXA$jM_ii^*=i`t0G+U`6#0$1We}Sr8On&R~cCn89M>j;%b+eZGgY%{;|!H?KLN za?zAp=aACOeZ*#&7Rw^GngwkAkDz@Dc4wfwvZbVM7dxxaVRupPNrs&((|J#6VqD^j z7S`+(e(Pq*y^-#px3(JoB0SA~{P@NjiroQ`cf@hu`T)wxTQ)0{b-MY!Q*(3GWE*qC zozdW;lR@7bw+%c_TDr$G>XMcJ=U?xQ5S3(mX~$cX$t^h*NZupp9_!Yp*m+nqbM>Tc zZTMhT^UdS2r;c4NO!`N2eZR+#EeWwP`K_12!}b&74M#?sLo=%PU8t)|z!lcqMgB>4hNI2tPV z$~Wx_WjWn)z@}bKb{jsGw6s;fQZ&~r!*3=Hj2hb>(=nztvo-|BU%3_OI+Ay(c0T>gp~vCi8ab1AXgkdoCA&Yh_<- zD;Qavd#g_g5?oCUvfH2V_t}{Kn;VI|&Fq_`qvHG4UkX>A9(P}=+jFT)!ec)kVfH7* z*zLZud6L*RX}i&5Jy1F;`mFudV|4gyOx!gKZvzUwFxP^kk^%!B9+>CsD%!9i*yCRJu*jmi=fM3&>;bGZ z)?wQ=7@ZC>i-|d<2tRIXXIBzv>mKVn?Zm|g99yb)ilLb#?W?=`_nE1fK-*0Lt(b0o z($&;W9!a((`Ic3aBFo;>QNH9BCuquzFbKx$r$dp`GRxMO_G3qzWB{9Aoe-5%Z= zapRfrl>Al;?6x&^yj#Of?Bl!MmJb{`HZ^x&_{!EjaTJ#nXzTj4x!OK`0c^=fXA+xb zQCX8gp~Fc@cDw6Mp4~{l&#~8~*Opw9MV-B#7@Oa^r+y#?9o=vwAUG~G3;cgZ9zPxm zX5r`dl#R~Kp3Z-`jd{ml-{q^mPH$4}zJIG2sZt-i0Gl2^cGa5|jz7{q$=t(f-L}?< z6>WD--Q5~(+kEfwm_Eflrnh>3Gb{An$mpG*eT2sukJEX^+@YR#?5*qf2W(Fc+~3OM zm0LJ1txWD<2gesYz7aF*k*|1ZclmNX<#KIenP`un(W7pC5cp<7!@*b9tS^O(UE|FIlC6i zwzk3irjf3DqYrBf&jb}0Z}dHIAAH!oYX6AX7-enAzgNf)yphq8mC=AX`_@}aD^D}J zIJIW?S{$6ljfTcXSlFg6&dOxKhTxHy@R*n+yItisj@jA;+1l9d<_4 z-H`I7=_7fz1$vckeLg-naQp^!X>a9H&-UZ3JdD`=A{CUS^!QHm;rnGIcq>CeV-2gF z@_XSqP;^$7q=dSrD_?tns+3$8Jjt}7E$t%P5k*gyghB1KPijF0kuKgB5+`=NF2H;( zWVHcWQ$2@jA!RoqSiB{*0m=eo*Zg(Ko?38xBT>FYYc0Br)bK%=M+3@v`r7rg@E0Er z$pqxt&^yNDt4zcn%EBIlF=XwY+9l9AQppBQmJnHx{*~4gY*c`@7KyC2V~KXi{Q>BP zzzxPz1!L)GnemRsDvdKpFbK>)NZ4;U5VhvBE(#O^!4d;yS;C=%DtHWxDrJY^r=Y6_ zurVa~pa|BjqgX@(k80MI>${1ljtqB`47iJB23p^f*_BjlGKrrfw}gf}dx)HnNPl_; z4oVZL828>9uS4RzqM->q#J-;G^E8(Vs0{E1E z35~NuW9#p(c!I)}SQY%(KNYQyROf&GBB`#6%o)I$PpP03e|i}FB|t(LBcoTt6=sXk{sY~u^%dr4%O3VvdUwU5%$b9^$mq?rH+W<*4;00P< zdlLZ#fy*!scUL12ndoZ(@8lzzR(-`RG93(7C;Oqv)FG!tG~Q~b3Q3HOM8gXqPLr#K zhb7m9K|&_i8c>?`#!-==aHW2&9~MAiP&b%kL3oX<1r+H*2aJ(~bnt-!7YTEGk0@^$ zfDkB5eeN!ygv&_;a!>^13VfsfgNY^A6I`6A7cA!wih<7d%89=IA0OWP_z=l~e^*~y z`g>!a5&ewU5P?G41i_4pQefvZCV^}aLs$eHb4!qycVl<1KonUPk%I$D$B^&IbFM2w zFQSdf@PrGDB!JS=uXVYv=yVdud|E`~?l6%K&^Dx@g7zw@)ScbnYe7)_yRJpk0F@ah z)k3Li>}t3Qbflg;3fbtA1yB-GxiwzE_agjLqv_%}(){t}kt*p!So*40)yyHcDU+*S z4QF<7CjAkmmCM1!6p+l^0(DKct2SqCckw2Sp=XhG@Y^mXm^~SSG9u=FgYjBGMxG-M zGG{ya0F-}%r$e(KuQai=RikAM+xbHuis`v`1Dd=E_KnZ|A&T!B)(22Z@qGE2{*xb- z0fZsuIS)Un$d5KDP$8V4qe<^T;nNk+F&AV_PbFL>Np|T`Ei|4=VZU~ygpp{lusgTS z9x+iAYYvM2p%_qRDIS|6^dcVVeP9)%Va6n21&84Ef)XO;XOgxD@V&9@!VtgY{+~JM znDKh|R%^5o;w8W{X$VXB8BK$F`OFuPKnzwA2|5e16Chb9Cv;g%A`>a<>=__LdW8`y zPz9VZeVm>u71I+AdG+`_0}fWt__TS)~7HeB5XO8^HCVpC`f zB}_h;t?v-?YO8=fxCsUg;WKcR73L4nf#IDX0mWjRT^WNMw9Ex(py?>{?4_IQ!m;Gi z3deRiok9Rfx^v&ajl?miEax>6f9*@Gy7zT0+Y@Ig>TEBrnC-s?#~-Zu{C3AVOT>K1 zqUZ1oAc8^B2aiL5Ff;V1CrSpAUd8)opFt0h z#X*c==Kg$Kqeyn(7QWd+8Y9%xEv%P_Y!|TC#bMmUaWUdA;7gm($UEx5VVbms{eCOM zacJ7#C7dDtUGuR6($rVod#9oP(FhGs)%+dMI+w4CFT0hf0S#p4908X5G<5z;Ykl>r(>S4y~=&imdBnX=1t^*iSiSbP~0zN(>JM z*JHq5XCfZ?ukTGjY>^+_--HO?XAvzMU{+5$c?~EN+5tc1!EH(_uWu8dk!ZkToUz^! zB=UUeWG1i9bhqIHC>)jtkx6?ki1;=<-jpG9c2&TyscqI?C$LB3y@sG$M%zaZXfQ0M z@=E&{C?#RIY!%c!eFA`jTCc> zTs;H@jp#7MlU}t5B0L5ejuX!N2Rx*$HlT>@m>%vl(R^eJrX%&-MX*+w)S{XMu(zKw zo9^jyW^igREe&lkTQCl&Id&R~ps#~h!oVvQe(M)Gab29P-l7t<-sBe@AFK|@8ku)q z*5&4Ak3Lz(T6yL_+m^}1Y!Xk?4Wt==w<#|}7KU5qejho*bMXnO%|h~!8Ckwm#=Yy$ zoClh0}RZJt1+`+h}AhEFxF|1Isy588Oyv`6!Bherx`v zkun!u77pwDLJ04A{tF2h0_Vm@F&fL|t$0aW;XKgt+a2Fu=>%nhS=)$>lLTJ4lTSL54AnILWApoLOT zCrH^MYkv@C4BUJ^S0E=YL1}kUYRy|CWBet)1&Q|mi3y6~sy@h}t$2JqWDk{bQ7df$ zp{61znjY#D**^;Z5sBu)=&@Iz$5?I({|*ucmdXT=<4EJ3Iu>^wRKsLo0=YhfZfa~1xZ$r8?oHc*MA9Jo1@Tk zB*DI4{d&+H=V%Xsy6X=6)i6ky16IY0bPEbYg7YB|wKgU>VAePIy>@S@0=|V@QHFt< zx<;u?2a8ovrbY8Ad+A|`U(%44pWJSx`qHCH-DOkRO$W9f_x`0yl% zbkI>W#g8888Ht+9q4e5mP!o9uOTNOq>)u*#9Yn(j0XFKacEQmpBr3K32Mo_3Bgt7& zS_UfS!$8|xAkG)$XlHvVZih8Fx9ID+Tx@23Z&Qs1loNk!Fjv89fDF{oX^6}OEFlpd zVAQ%;5IahY$AB1I4^*gFcnk*sbqB<51Ihx}b!aeI?Jxt5w8%WhJzZ`Qs7nYUyb&D* zSm#RsAMV0}+(!LX5)o3X9h5+(O9Q342v8etLvC$6Nga_I1yDB^PQcy1LJ#9#d-WOp zK4MUo&#<{Ouh&@jHvr^$+TZQjtV)He-eipasEhPssq>%f!gHXHg1gG`7*zMQyrO0~ zWPjIKcWLFII(^zV!XlUw6(x zY7gdgC`?b|3F%mh?hrQUXjXz3i3Hwe`!yZ4NMJ5Q>P=lQoj+0blLx}b7|~Pwkys>9 z33X4C9K!VQbEE`k@c_X`f{Qr7^9Tc7>U2C?a0S!Q2f1b4F6o3hSfH;G61=8Km^P>% z*hDbx)P}b*`gua|epw^dU?#bWcSYN~r3Jtz;q+($7J-K~RC{3ycxAhO3f`fMfaL@Y=s0#l zz-t@|PJ@peJcfd+04i`-oGClpt~Rz82b9qJ+ZC2Ay$=R}(6tRfM}M-U|fVwFN&&t{y!@7fcZ+dh0c%=m;m z4vqV&9ep(ol@We>f*MoMU`_XU{ZEl>t@A_U+gqnm-XO!&}=Y-cYyA{jF28+(rUjt%9O97pFYr z;EdaH0u~^o8XY*eNKD!sKtqi^05@0Vew9DrSNX4z>;HvAz*PzlaUp=+?;$*{0~LzE ze@Fn~RY@lj3lJfpnvFDmy(EHzD%rq>XdJ5IOV{QK=E&C;F(*h>yDe!iUBHYgyH055 zdL5Hy!YC1pXYuftXz1ox4^$>6LgQ(9m95gu>;z*p_ny`d+=jw;iJ;>xheIsTclVzw zjn3@!?}ExT{S7b3;30mL74Wz`QIDlXpY#qBph_s%n9yS}M^M0-#bObE0NnyvVadvo zvx+u@LHGq#*bPP^*`S!q6LzX;zqD2Y~z9|7%Ln zCnQdbqNkyx(sXSf^zov**s%(xAkLW1Efz#30GT%lgickE|K!)Z09)R8-P2iG~~UU zv;)O6I;-h~%*$kL)tE4K`OTS{*vxt}W-fwGF~gnV>%6<83e= zcOqL9NnPl_Pd>QbWh>J08U)+mha^-FKq)l`xSxw0*|0Ak8wIc-6c`7(FXqtY5PPbC z0sk3AmB4BQZBe{9O0n{!p9fo$SF=Q-N!u`5^uyac50FvzgWD6u$W_TR#R&W=zR;Hl zP49fb#}a^dhb(9>RpP&1MFWaUj{^xlXcYoa3NDAeN}qy%74erbP1f)RtiKz0c__gv zaTe>NgatQAR{#V?BjFs5?^yjLknRZ@p;MX&R0zRGke3HfKj~!h(5P%~O$i$B2`jy- z#0;cQAj`)hq`}Yq>k<&T{9It}dQfrcC|YyE+x+=NJW~uBgoquQ2V7VlPE$cKv`*(R z2@FN5yVDXiEwyZz0?k6P?!u!~!DB2L*c7IT7{ITgWC#{Pfh88Cj*cc9(4Tyf4bv60 zKhn{&EML7Y2xZC*I6Z*QtT2yMZgYw6RJoV*q_YOE`1>eB zfL+|Qq3@>0+HJ+zJ+f1)Z1Cycr=#Ixx-ZF*Oja=@-KzbJjR#rze%<@ zsQ=*>(Y(ht>0*G{oHw2|@VA)3a!>ij(DM9Tk?XjTf+w7OSS7^cy%W7qH_VU|D zjqI-K{|MUgE`ufv*guz1ZNt4kyYjo@M9x#wLdArnI;DO?z$(#}o44)qIXjdWy`3+* zIjCJHBOHEreQNr>>p$NYmkT$VXjSx;a_3j6ds~>zGo!25dezmHX182432VEUyYIpZ z%hcZPeuCQ#*YufFQ^6_c4#c`@XZ$VqlvSH5ISC_^3)k-NJ(T{TwlpmkGX@hqkr6w zFLry1b6tL`5A6?~TZy(2x-mj0ye{nR56~K)vNh`s_P7c@G{7&@Hdp!E%~Dh8ul~}M-DvXeN2lKulFCn0Ye5%lq2O+uuXpVRU+jgIfj?yUwa!;e_4~i?ZK3ln z%CvFH+Z#4}=4jzZ!=lAJSE<{IYT-gg9yLrmr;N5~woU!MF4jGKMeoP`M2b^Oz&{DyStlqHveX+cUFI2smGCTpjz+z4~$;=<(2CFzAMc9 z6J-^5cURX=_LX{jInBk`nn?F=>TR4=JSxvm_Sl^H{LPI=?6z_GXeO=Ha`J&UaX;sB zje05|ICY`cTe7t}tX1Pa9z^LLE`?T}Ixeh;vDeBsev)%)9rEk@l^o-0i{9h;!i^i< zlILRkN>x`jwrvSp&Z-V;j2rjj+&@tH0o`9)hO|_BAJqSQbNG3_+MyHXu=gK7)zP>F zmZ(dq<+k;DyB*h0jdVxvTVXOi-`omVHT8}By1+I^YdSn@8j~+>Y+&y&HO2LY+)r>_ zmJzYVZ_!C5=kiKXFl(!yv-vaR$eef3R9GM8dx0xV4o#oS7kb6{#?8MQE6<-x zx>T9voypb*V8XO&yZt7LP?uY?M`s_0TJ780pAQe0tb{whIVi7oOAOP>aLQ7X0kwx8 zh5ZLrUTxAl>wjf6=Yq3$l=GGHZKgxvH~#?Z{C0n0{>`#D;g;2W-KoUx7hxX(osJ(V zG`*|+{bL4}6x(IR<{|4KyoG)4hOXyOlxookM^Z=r;bVZIs;|hnQ1nLAr?_RA?oM}zaoddl?u)5+gD3k+W^cf>bvB&GI|&w zDB&L}KTje};Hntkx+HAkhmN*qt#MIUZ0^Ip++I16!fp_F2YENJ(6l%;Qyhs}!2PQ+ z-?iWwaFRkkVLw~Mc{lwxQ0-xfv`~DUn*V~CTrHL9HJvTcEJrLK0-2*yIgk&$x2R`C-G(RCzjstl~R_tgD-^J$ev0RPj*46}6$tkK6D1cv*EH};YoFY7N5n29;K_l?d=5;h7ob^R=&D7u zgE0})kxgaYS7>6xpeNwit_L0La+09h9(qKS4 zT0^n=d24=qDany7=7%pHSlTab6~k`FnwKv zsg2-rHx88KFDI&^B5+WnDMHFuhy-dZSgAn9n2YMr^b5yk!T@qX%8X3RV9p;53OeK|1h1Aa5+;1Gs49XA=-~N`p|l<_;Jbm;ZOx-aM?ybL|(sR$H~pIvlN0 zL56)~Rap^Hh6n@#(h4k<(d0=$rV0WY1jP_$>{8mQ4B@jHg%ARQLh`;zP$E-6{8|JQ z2@%b!Wr%)4N$^#$5Q9Z&dv4a*d!Mt<-q&^Zx%TNl6$A`lwb^#GW*(#&}az3^JbLs_O?&hS*-tkP&i%ltvZwKBhy-HPQ*HyA;?V`6y~*3s`= z|M+#TYg2@i#NpLC!*d^QBYraglShBqUyYe#ktw}UW6go0bu}sm;#(8tC`p}c!(QDz zipjoX$G6VnS2W1k$k2h)ew6D^2Vdtn7_rysRz2rNUz#5Jfe|1|G_^Q0*HOarOv2P! ze3I%6p;%=9c^*o%JBa;}T^UmDmu}(v2(MgiOY{5E&{w!zzH!F#knV2I&6sEr&SxIc zK++R9=CFG(QmK}kaVoVHgC_1?C7VZmhu*8@eVuq8y zgbSeJ^Ak(Kr|sngG04&(a}=4%Rm-DS#9Pp8+1#Sy@5fXuV$f1S_o#9{kI8LtVT7!g z5}P;W%56w5jKhWDh2Fe?u&~Dn5;#zN3Z?Bnwjvu$S;0n#+CHqjY5*aNy#{!g+30Nc z_r{1JF9Egj9r{3nldb-|T6QfFH$TFTgXfKGydUS@$hm!&i~%M(wTm!s<@1SC-dtts z)Gz#06ioj1p4FRGf<8no7#Xp{_Sj0aa~DXcniImn#uD))+ZezFAnOq&+=!BmGHfBq zr8B2_(uo+57fB|mn{)j4U7KHj2rPk+F!mK21vgnVVkc6$vXAN-&g+^qLtLd1mSbQd z9kx>2^fsA5A;n9<$H=^4_f0#s$^kqs1CU6J*XW7NvZoy26@WPKYB!f5wX)DL((Lm1Guth683LupV<>))>2;@cMI77fx9_L; zv7w)`r`}}qSUn(nnHl64Isfw=CouYRtk;JD8e+ik4~I?olCV96c^nu$#?>giPy`^@ z9Msc}Vw~E9kzD)=B?@cjSWsm`lcc8M6|gEf)bzvcyjn>=w`^`^uKM0IS?55c)k5e| z0l3fgi3D8P8<_Nm!{iJPR?7D#9ZR=*EDX^3f#mnLH3 zME{VmyGJl;ix#NY5bLCuk{kRyI0V-_8JnqXZ{qNAz`u4OESJ5?i=mft_kTHVI)VxIZ&tW%( zP8BQ0N~vwuv55Yh!Fn_>{lo^4b{&8feWFh44Rf?-%|OMuh2Nbz71!SW@JzUOerVv7 zLg%)-O~pxTeiP1%>=}_|f9_fHt2T`PBxT%V+I%*viK|WYi5NK6h25HooB~8(g3Z0x z!k!4BEdd1p978~8J~v1QHS80c_r2_ImZ`S3>LWsP?y$m$WMy>k2G1$=cc@Uj_$C&~ zs__PUN3xDM=uvg>W?Zp30#-(UFusPz(sN4ShHt>v%%GFk20@as7sk-NHt8^us4a;g zRbi#TuvJg4(o)!);LVW}XOmUl`oCh1=N5G9DDj3QFw)goy^N(rGk0?v9n_uPnVk67 zZS@{ceHdTDP+}!^>vzoFu5c?`M|^lCJOs9#T8=4R%05Pj=m0*Y#4=*p*m9M~UJ~)# z8P2UJ>}J?{mOkKE+M!z9LJ_AHHREQ=s#-qajZotKUO4?EAZ#!=)t+p!rNvqkS;JWO za9=CbTMtC`x~ZgvAD(;S7&|d4>g6ro z9Bof`MEMmh#k`2Y1lzZ>Ho-}Ob2s?7Mwz1?RFm9-0H)Rw81_SboirwgMVz?56}uzx zG|*Ogrze4YXX#N#C@W>fhT@)TnYvJr%13=xoe!LbjWiOcUgd$|69?pwzJ+$icuxMM zF&v~gXeXeyUoXt(r}U0+YY{EnJCvo5_RTO~T27UH2bt6bmHL=@vMH3eSfr+yZV%N~ z<67|`I_sgf0o^J0eS@RsjsI13VPipgrOEV#hEGeA+TrtW5HDX<$>I@dmiYRdRRh%K z2H7hWL44!QV>$0heHO=93hFjE@w*=K8Ieq8`Z7!t#fAH4GbZMtqv}QnSz&`fu3lBS z-KGIJ%Sa?@mK(gnhzy*y+_aflVdO_IiuqAqBG!XBK8f4K;^Q|vkEx(a?ZMuEtg8?~ z~1tpWO`IaGWp>kt$`^}%{-=Jo(Iwg>_oUg3tLuSKtsq?RtO&FhpRjqD$qAx z{K&q}nt4^_1lFjK0*`*zBLmhA_audF=Tuuw3wnXIL1Y{oj-2;0g7t`O_f334l?fuS zdP^F6+`vB;DTNVX8JZVnE3fsa(z{G9=_TbnB)&&vT$p|q5Y}|<6cO&tB6MJ5nlXDd z9j~Lt(+x?bRgeemv&-tO6~WxXi%J6vgw>n$5nyIX-1^keD#$6WPOIe6LA&{`Kc1?D zA4o*1TaE`@RTt133(9mms>4;N~~ZLfJqWR3A!;AB3r1e6_*V-xwk}L%l)P z;BJ*|Ka^EtT}Cm^w~qAAvn;IdEc7KJ7{t6+ z1Rxsd60lb8oz)sV%rW&yDTn9h!Pe>AYjA3tQ|ATL|L#g!)1#}1+h7pjPc0g!-%p?M zQt5*tw5Y-$^_LY=74TMs!`XAh4kP?HC1Dgjc?7>{7TgJ$`$GT~XmUmEpG_C%SP zU#aL9{c|qrS;JI$FGn}AQpZzPag9^+9|x5c0PSS6vt;FC&VFD?`gq`O@(E7C8+Q zI#y3SrVQQqj;(`{Fq2~f(KS$wZdv_2O%SI>=puhMu^ zb3?OGFSA)(9CF9XeG_r}%`a;YqgCEFZEzTBXd;qiMU*uqXcQ$Z@za4fj=F`e>*Rjt z%ie`egn?(M2YK?meWNl>2gkmv<A#=ArB1|jHAs*UbM-RLwZu;fD?l&#H+R0VC07_r}SNGHboaksy zWSKDqev+dw3hp=yrp1i``&sdh9s|@1>c>Pmq+y3#48aZj!+cki+p0*2rCmUWfQmMwvj{*J!EYl9N|-Ej ziupn7m@&U46uLerLLn64)a(a+g<{4W8A=+F=2FFf|}%eG(IjGVPtO0-VHS zMf>f;x$n}~Bw8wvmC+ftZcXu93*R+Z3s=7A>XGX>f~Wld0pFHi4k ziAp-aQ2l!m^}`m&e6G@g0xBuz8b(&7Ge*_#2kXJC?RB5g^K4mJJjm|6Ot z_RYjG^v$)<%(q)dgUKgxjMxf?as)fT7w9k8>tMR9k`sqhA+GVPtPqcyu_U>Fl)GyC z_4`48SdIjzQZ`j>*Wb$dcCbOw`XPk{?kUUqmRI0X$7hYF{lH@gq~>dMCX@qIWAH*5 zqXk6*YeO@#m*@q_>$T5hM$k=fPL(f~*;T6CL1}6YKmtj53-@`^K~daK$v<+5sOQIw z$jTfAh=8O(Rj9zpoY!!FYQ@CLTfa_=2{C7`3rtd?7S-?WU znoW;TqzrpmgFVI`;p;;a_Ut2HV|V#!lBN1b<&f?EJPr|sLf z(o*fEEizXC!>Z4X8p7V5$5!Pu{w+uC2GpSkQM%=aOmEKI$sMS=SqHBiPSSqGzEJ7bi+_OEB0@1s`9$!GBWIUsEWj zaqMbnk~-`-unMud%Un5;an0ZoDzU7Fi)TUw(c#X%rsS9M3av3A1^p zdWpETQKNt8D(ez{sV@?nJtwFC`M}9hw^8>a{bSKT`^zt?h?gUO1MaTZAi6o%e!hqB zH60m+M5EfntmU}Bz+0HwZ(}Dq=pGem$!-Uy4`2R6R(bj#8xjO=-1#5(&mMGecR76j zyxAprdG`f;)rw!_$!jA{b_O5&?N|9w-Y-A>Sn9a8@x_A)2aoBWo#Osp;C%FfJhH3E z(&NNoj}!3yfgaA@b%!77coSX1S=4_wEx~J{eiyAE{6e@(T>p<(Y#g#@4)qo}^%iXU z#VX4=zNhhpHZ9J%JC-mK~TFNetkp1|r+#=0;zkhUMch!2YGTtGN6A5|Zp%cISSzfUH zYfb53v0v2s6#tgC^H%-+A4}r8idIF<2U`WXAB^4VxW4$hYeG2hQls%fh4&UK z_cT}((ohRH+{B}>Yb0Xx2hbL;QvYicD zVbuMEZsF`fS_P%&$0Db@szdHPc{uOI{fa-1g+Jfw7!}UDl@QUmzIcAvS-y?lB`l!k zi3W>yIVd&;C*401k#;EW^4a@G`qFuEPvS4G-_ZBqthYnN$pm+HRO<*}9YXUI|{I1`GVd!)fIcx^f~;0qoX}cd0JG8R34ALeP7~z1rYO ziteEZh?iP0#r~WhnOMy@`0LXowJMcfC>P0lum{y(v;Lryd&A7Uh1F4UVKji@vrd(| zO*<&Di_(y$WsKPLJ ziMZEYgX~fL+{muTFq3UnCGaUtCi|L~CCX#0t-wwovq*HE2WEey?&&@`5xCx_PKyNj)CLh4f*S=j zSBcBKhw#_-;AO}oQn!p_=E%>%HV`O}nQ4`qswD3rP8`O3ViRE$i(i)(FA(3*Ktj>; z9#}uPFj9&MsdZ=5Y=D^J0ii3C1K(eN*qMF5uen}?v9R*y8)mQJ*Gka$tQdR)Z4B7P zML(QF;axAjq@)Aw*3Qj4E)}T-3DD+NPoPyxEB-e zX$GRqn17c}E$UPn1oW2ckmublgHYawgW!3#G~%g8ZOR8L6pcxqV3jbzvcxV@>x_Kn zZz6LGKy6r{6S+pqM0A{d!WCV_yX#fkq=TmQHl*VjuhLa|Vvy(3n`8)}Lw>7=6{PKw zk4+th%pp+aR7g9deIm88P_I@zwA2CC$rHJS)(Bh<(jeowf6NH$RYzH)Dr$hXuIfv=V!1wD{Np z`<7Qp7@RZS)X-@h(~j~Nu+IV^j$Pq`}w1qK~3t{@>U0EPige+9F! zVDb(>qN~cDTJN?P9u9c>DTPc5baC5W)8|BBsl5585XfWv; z6b!U!gb8~PpY;d^u>)?%`#7-RFy;1yNT&Ec5eU{W1QGA%DVAa7EyzB`@i2endefKr z^iPt@Ucadu!^8n>6i8J;Aq&+CR?i0U%#EJZrykgm?RS)(b6O7i7QF86%@0GNgUC*5 zLk3Lzyoi`$pjT4g%U*$@-&I6UO!MZ7WD~50OB85O&R{=&OytyQn8*WH&W|(x@`sdc z0&&I*y@ae=?!p3du^gF}K_myg&+bC|&SF1|<2RtPeE{sq0g{xN*<=?ANuoZ7lk!jtg|kvfTeMPRmfOE?UBpf`i*$Rc8Bw9mX?uh>ZN*(GsP7e>$L`HbdG^%l+)_zR z4Yi_3bkzc~U$`o^>u6FxKOD}2(D&BFzGWCBQhQ#-9W*9*cn9x2O>sSS#Qz(plVnI;sHi1QZNa$14X>d6rojoMm|#g0-+N(i+?-yInwJ?FfLbVtZ&r(7 z-ASl2QqRf8KpeqAIiQnF^0ofRi1paRYFx}gU}@fG)!Q+au-olW5EYI?_cS*S^gy85 z$p9-CtQ^RJ<^#2KM57&xQOlTcENc$%QGr4!)-5ysCuUYnX|VjgzJzE=%*VXndL=!pNnb@@E^~%x9G9>~4yLEm4-krxgAaDE%T8ViQ(I!+ zx|Ksh*2`YBg%#?FN3(vkuk%oen?%Mu(>!nr$4XwpoRe8H>UY|EF z0r;eR*3*^lGZJjSi@<#BE|#@gS>=?`o%gDi zpNKkU6u$(xCOJLM=JfVwwB0bK>?sXZ76i*x!zI_z1J#~fV0l=xUVyf)Kb>;4Mh&!F zn`*Gbd)XcuAnsM!5g|t$m3SaHuT-?8P?vwp3ph{%&!_LSL@7}4nZwJzcMVAE6zSXBR=zm5t}2yBz7q2%(&!uftZt2(D;MWZfhuYN^D z6651Rq0X{FmZ8KU)T8787budoY?x9&N<3!(;JP|KGdQQA*+^}LK|Je;7SZ{U)do1C z>V?rzK_dVl7d=1CObi}OjuO_uURa#65)iC)Vmxa$wF&Sb>b1f;F57G(wrYULc9+^pL``gnIhIr(?h^@y`w?$2Flm;^@4U@Cmz{C{7H92DT|fTZ)e zpP+gsmd5I9z{Uk<=ohUqnE(Z{T_?d-Dwe+{G@9)J`qBn`{Aj?yujYIr?;ZGW2{T>! z%(BsmPYj_fV9LgMXZ}3I*86cvq3-y4K79id?8OxNh>p2i29F-D>`R4D^HAe(Y1zU8 zX@^5HhTn$36kg((b9W}fM7LkIbwSfOA;kuAK#WS(iH)fzo^Tu_Jf3M~3hlA9^8Or!YW0G|@#nGpegCGYL>Dbf6M2HRrNd87k8bW$6P=kMx`9#Y!( z0y|NivQJ4%dl+p(XYuVkZ@%WJpA}-dVBdj>5o9Hmdw2-fSc+4f{OCF{i;K!IDCaE8>Y}vJKHaL#*;CY(0ltFE)n* z9(x^=^)f&zI}IqJkV#ntxqt)|>BETi2xAk8i;v#W07|Jqem*BeErWa?#})4%~oSMnA{hlani6~A<`|8?-i6SNO84=yiUQUsO(FQ8;5Wz_4Ia;FN&F7|ld zl!p>vnT26hi%ax-mn1NY4WVAo!$kUJH1?+;!H!|DsiaI34TkixZVop7`=adYng~ug zY#O8plpKmNB}9|8vj6oAKa#k#q%@lo6m#4 zKdCUQWq0`pl4vYx&PCQ22XcUm4+RFd2{e}BVCz~{K3=G2bMFYSqYxGsD;}`x21z?q z=`MhaQd4m!AA8sMfP5G6!XMElAl|2H1k=>z6~VAp+MUJ(rxnk5ZtIe|0xW9VrC}Y_ zFoq^4=jR(ldI%W1NxTc4vYLsG46~(SqK+9;hQS~uT1oEEy|!^_b+6VoUPO*UV9}s{ ziC@r%3dQGQarR4c#Iws~JZfRa+HdX4^S67-XCZ*i(;w!i=Y zXw3=xDfxQD$=T3I zQR{?oy%B7(p8B1r?qnTMbBKMQmGzBZ`lSLT^ zK#PRkk)woIVL~q|l*6d~WI>lP0Jw6Orc5d#gnKQ9;O#HpB*Ef~2VqTrgS@aGKte~u zs#uXuSejnP({pO7gQ+rq?9}TXtjq-^uTHx=ZBLqDBAo<|gOG)!Wa)HB+BXg+iuh)M z(!2Oexs(y&it>&TOi?pkO>e|0w7mV-Io#}FahiK=?=ap3jfK3Se5Ew zY*P&|e7eNiRJv>@u`Ko4n{^jJO|U25Iiq=*-#%%e#B^sM13-cVs#EW=dV3^=fsEMZeEvF-@peCloF zSzU;4F?LyWTguc{Dio*<u9 z1$N1WjZ+{!fCC^ny9AJORW#9>qu4~f2b8R8g82{3FgoG)msxs?HQQrc-Fy{D3ImHv z5G2SrOtUg3x&5Q#$Hf{b#_-_Y5&0bUJTu;)41R^LNhK)o7gp+-b zH$}_fVkYbPNp6rAc#kf{!R9wof5J>NqK@9nC@QHWaqkO$a5 zIL^5mu@9*yU`=Mi_r8aDG^izz6N&`$$ZLSg60xwiPGLY9df$NH7%7LTbrWaNU7`;A z2UZrE!1}4dC@sVe0o5TAd)o9rQAOoKS}WYA-toG*Ti9>`8XdAIL4`L+eB<~qI*1Kb z0b}dtq7@8;aiv4I9}AaT(}CYv^=Q!()i|*%P%RU7VCC1(^q{wW++zQi(~avdS^rX`y4gBSwV-~ zTa%|$-RwR3l#RIa*k)r++TtddS}ZMIlUSeteu$gr`MZ^@7iyU^y}-)sp3{k?lfxHn zu77vnR2<%nR6q{yGC{0HCX9UK6@i9o6{-Nj6bPT~sLR%aSA}498>EO`x0IPp{*M-? zxpy?*AKzT!S)!=-DY77u%l;K6$kkiY2~5xrT+skDMAIr zk2<&x?qZ$X1`yP?qrOJ`tpx|o%NeX$d@2A&W&l?xrvP!FF_$Y6ShdJrL~lSLq=~w` zxpq5z-fPCe1;!XmOIaoB36{LZXfabIYJlDo{rr5N2r71*Pl4+E;k4c2kx7fhDlH!B z)El%OFy;T(ire+XroJLtND#m%X8e+9z*nLowM`$sG5y%5;IkWMgF(1F^+pYlFMf}S z2lsOh1;M11Rf0^!J`_<*K1)o9rf@8ME?I9*YRN|Ax0(DcPL)A^raP(B2DFdHG;Qn$ z^6@&b@LUvv(VzfZSTNF}twn$1%6Z}$KmMwQLi%TJwC4aVG;Q!a)eBnD`X;PC2^0Ba z*ZO2_de$FXZl@5zcG$%gIp6X?8jihh64hNZ8dYc{8Qf}0L-j$XfDMa<=&`rU>!3%O zpKpVyoFpCvW2Opzcs0!S8$u6^W*@90Rj9au$`r{tp0hdT3u8)U87*@Cz^bj z{BOL1x4iMt?9M9A(}lH8t~{VUPhaNi3zQE3(16`ikH;#V8A@ea+9$slSfRY$p%+R8 zgT2G?OijI8MV{D-&x zU6=D+Jz`Y*Ly>eDt0xW=qi`DdEm373;g@q{nvY(6l}?E?CbmP7BOro;SkqKlVXU|R zNk=R$M}3V*iKKAvlo3mPywaBfw`&nz-RyWqiFFUng6}o|B!t0?tCtDGUy1_XT^R2- z4$fmHlep)>wl8@PJ?~-JSPN7>V}@=%6F{te!YKIlWDg$_;%*fA6+gTXW5FpQciy)R zs7W<0p^ovyVHlUPcMi(ciqM4c^#bU{zelt+|Jof)!Wxh|bkU}vZ&eHWBS((@fui8e zoYQygYl0fI4%|Zli8-d4*0URx*ie6beA?70?ysYR6OhuNRz^Muh|)$-Vr|`=h))t_ zPUH>j-q}DG=XJseZ(9hz;ow24iD-T_u-Ep5-Aw>GbD!+CpWm1CbE5>4b6&+-IA@5+ zT8FS}uBW&{$QLa+_U^1&b`bo2_ceckys`1VJJ%3}Mxl9#XXZKv@^H&8be&4xL>cyv zrN(Vc4XZ@F&5!9_TxY2 zA6)S%_SiU^6`xn??(tjOyi2@E^5X7$H_`Uorwg{jRhuis+H!}xFmZimJ@h2e7TRDE zC+W?Ts*GQ!j!li}|DrffRiWC%j8YN!%p_Xk8|KdAm;X65dz!IzTgdh3!NxnA84-T@ z)=l|4R;P>))c-ozoU@|()i$BTpK$L`ha2t7 z6~I-j*I%C+hV9)vH7$p%BsTHdoMO_|BHgMpo+SakM|EBh_wuRs(mF~C9C3+GgKY!P zy)%4Zqr*ZkAkv1~Gtz8a9Hh|v9>7%UdT%SREw-w$MSN6F{arfx!<7+%yv=*YOB5E&AopJwRnQ zVtRHw&^HeNQle^CwL?JjrDd3za{wDIR2DA`vG3+I*EK-B@e`I*y1I7a+eK3MA!Dk=I%vNSgHzg`_DcXhJMCH8jD-0nf^STsh~D)>#^~JCus*;UCOuf$ z#U65kInt7(Je#pLDoViwN0DKC2p|vJ@)v}ctS6aBM2IIgr?;Hxm zRQ-wsP9Qm4HrTQW6LN1J7vcM$KsD`AQK{E$;yZ+r+9u*8+-2NGuB_DQViMj4_Q5@i z5$@DcFqpAq#3E56cJc^T7iOxG06KzFA}VW5clCbkxG8?LT6QVz?h);7^46H!5o}y? z9i?PA^D)p_@csAa|c(c{Do+^@BL20g|;QJ}$(!0+l6i(69M5sN+K} z9CYylAsDOIxu69s@=>(9Q4yf(1)0BBH4E}Ih_}n}=!Wf(K~&9$M;vo1YhHPJ?*Keu zs|5{x`Nx)vRd=BMO5er*tl8WTf~%pxt4fD5UCW3qbO{BEaxHRas5Z6ivUb!9hzRry z&V2r+mExBPkpp0*+&)Y`Bci7^LBh!f25~cEs;InIt4YiooTwGii+j;Ub$fZj$42AS zNd7gj9HS28wodM_cPyZ;W~LE=lqE!)wvZ~4=xYlV_iCC(^7PorgY9)#-9UqrjvwI< zK@`4YQ1p6CpGUbU5*s;h(nsYcv8N%braHPEr80OA1Hx>O8FDGW(7&5?KY^3|A;TyO z&>@R3G}Zg_8>+okSU23(0hcRUpC5A?d!59zcx`4rpijZt*RBW8w3|G@nY&@pixG3O zA#rM?IU_PGG8!9JSh~+oQrixE$f!O?ZiO)DryeE!mu*~ZE2BStU0h?p19O9(?*f`7 zDo`(5BV?C^QP@=D8l8W!Is45T>^gHeG3{{rUoE{g-KaLBa3Dw2-q^)zt_|nP$ZG5l z&s~w%_-i6L?09Sjo7P``HPEqambz3+jmG3#VS7%U z%G|A-_5_90NHc6TV8S||CNk}< z3iTVwFBzel>NiaR%An+`@upbpH_HZBv`H%{k+H^{>&8!N6rwV0R3Pet||0-uvp7HJC!=@19Zo8?I^d|1cf2kI?@^< za1@m0-{=Lr@T!3X$}gFi>|Lt9o!0}CDIIYkAgp{{l)i1!v6>|7^raj>W+vES18$co zHq*AW!g_I;ozH3Cf@E1n;ko7z5iw9L#aCLGV;A~)A;IBOP76Kc!5L!np`a$&Jd4NR^E&N8@oESH@w z2ZH$7YV4UdeS@Wn*O`0Ul<|5@>Wpc^VU`%`R|z!j%{Ue|O&e~&<5U}et0+9(^V}&sNx9^$1aEW8<=Hnt5bD9SWZsab*rh=laW4J9XT(zPd!nNl~xKrW^ z8d7`np?%`g{(=oR;{5GkhnG$PCE$Ep4LIWO#!__8=(o(2L-S8SP+3mCZ}uu)fM75f zdBJUQc5wC#b!k=$dd4HYiDPIPnO^B1hhufZOy|Dk3cJoB?e|7(8bUqpVchyK%N-@h z?VWd=O3ol&A?Y@2S;j^GlXV$~EARWN?=w;#XZ3th9JAH`56tKCGoQF`*ox-(0KvW$ z%{Nnam2&09Z=7u8JvZihKr==%s8NO{?FnBX*2tVU$(I}LdE-@86F z(i9&5&<@SBi3@u)$xw87PwjvRn&pZqU&|HwTG|oB)@uK|DixpV634B#r?BSmxmnuZ8?JHdN+tj7jTR6~d?%?Z zulNq*H{Z4{&a!X}aAJLg^`d{@fy0VCg^i6JoS1AI+~T;sZK@t4o2RJ_iy7yjWzJDx zKNYp4>eekQtrCywSXMLFt;+#0Zp2n=0bmiqpbNBPfp$hXmIL61b2qjitbrH;vB?P5 z9W##4m#qC)Es*dRxW{x@bGskM|I{%&4ul|pssS?V(hHCG^h3Yhle@C8o5Knt_9mXB zH$C@4l%v|vi;K$2e%Pq8>(TuhUv#}(Π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

Wue>hS;;@jfqr)M##235K>9O}8xo|a*3ipCl| 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�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�u(Po=KDRt5x$Gb}MHjhG1GAODp$Ymna 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Ή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 0).toEqual(true); - }); - - it("vibrate should throw exception when not passed a valid start time", function () { - expect(function () { - Device.vibrate(); - }).toThrow(anInvalidParameterException); - }); - - it("vibrate should call successfully", function () { - expect(function () { - Device.vibrate(50); - }).not.toThrow(); - }); -}); diff --git a/test/unit/wac/DeviceInfo.js b/test/unit/wac/DeviceInfo.js deleted file mode 100644 index df00bbba..00000000 --- a/test/unit/wac/DeviceInfo.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_DeviceInfo", function () { - - var DeviceInfo = require('ripple/platform/wac/1.0/DeviceInfo'), - deviceSettings = require('ripple/deviceSettings'), - platform = require('ripple/platform'), - devices = require('ripple/devices'), - HVGA = require('ripple/devices/HVGA'); - - beforeEach(function () { - spyOn(platform, "current").andReturn({ - device: { - "DeviceInfo": { - "phoneColorDepthDefault": {control: {value: 32}}, - "totalMemory": {control: {value: 128}} - } - } - }); - }); - - it("phoneColorDepthDefault returns the current default color depth", function () { - var value = DeviceInfo.phoneColorDepthDefault; - expect(value).toEqual(32); - }); - - it("phoneColorDepthDefault returns the current 'persisted' device's default color depth", function () { - deviceSettings.register("DeviceInfo.phoneColorDepthDefault", 545454); - expect(DeviceInfo.phoneColorDepthDefault).toEqual(545454); - }); - - it("totalMemory returns the current device's memory", function () { - expect(DeviceInfo.totalMemory).toEqual(128); - }); - - it("totalMemory returns the current registered device total memory", function () { - deviceSettings.register("DeviceInfo.totalMemory", 6666); - expect(DeviceInfo.totalMemory).toEqual(6666); - }); - - it("phoneOS returns the current device's os", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneOS).toEqual(HVGA.osName + " " + HVGA.osVersion); - }); - - it("phoneManufacturer returns the current device's manufacturer", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneManufacturer).toEqual(HVGA.manufacturer); - }); - - it("phoneFirmware returns the current device's os firmware version", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneFirmware).toEqual(HVGA.firmware); - }); - - it("phoneModel returns the current device's model", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneModel).toEqual(HVGA.model); - }); - - it("phoneScreenHeightDefault returns the current pixel height of the device's primary screen", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneScreenHeightDefault).toEqual(HVGA.screen.height); - }); - - it("phoneScreenWidthDefault returns the current pixel width of the device's primary screen", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneScreenWidthDefault).toEqual(HVGA.screen.width); - }); - - it("phoneSoftware returns the current default software version", function () { - spyOn(devices, "getCurrentDevice").andReturn(HVGA); - expect(DeviceInfo.phoneSoftware).toEqual(HVGA.osVersion); - }); -}); diff --git a/test/unit/wac/DeviceStateInfo.js b/test/unit/wac/DeviceStateInfo.js deleted file mode 100644 index 62c46f3f..00000000 --- a/test/unit/wac/DeviceStateInfo.js +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_DeviceStateInfo", function () { - var DeviceStateInfo = require('ripple/platform/wac/1.0/DeviceStateInfo'), - sinon = require('sinon'), - event = require('ripple/event'), - deviceSettings = require('ripple/deviceSettings'), - platform = require('ripple/platform'), - _console = require('ripple/console'), - s; - - beforeEach(function () { - spyOn(_console, "log"); - s = sinon.sandbox.create(); - spyOn(platform, "current").andReturn({ - name: "default", - device: { - DeviceStateInfo: { - language: {control: {value: "en"}}, - availableMemory: {control: {value: 256}} - } - } - }); - - deviceSettings.initialize(); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - describe("language", function () { - it("should return the default control value", function () { - expect(DeviceStateInfo.language).toEqual("en"); - }); - - it("should return the current 'persisted' device's language", function () { - deviceSettings.register("DeviceStateInfo.availableMemory", 66666); - var value = DeviceStateInfo.availableMemory; - expect(value).toEqual(66666); - }); - }); - - describe("availableMemory", function () { - it("should return the current device's available memory", function () { - var value = DeviceStateInfo.availableMemory; - expect(value).toBeGreaterThan(0); - }); - - it("should return the current 'persisted' device's available memory", function () { - deviceSettings.register("DeviceStateInfo.availableMemory", 66666); - var value = DeviceStateInfo.availableMemory; - expect(value).toEqual(66666); - }); - }); - - describe("keypadLightOn", function () { - it("should return the current 'persisted' device's key pad on boolean", function () { - deviceSettings.register("DeviceStateInfo.keypadLightOn", true); - var value = DeviceStateInfo.keypadLightOn; - expect(value).toBeTruthy(); - }); - - it("should return the current 'persisted' device's back light on boolean", function () { - deviceSettings.register("DeviceStateInfo.backLightOn", true); - var value = DeviceStateInfo.backLightOn; - expect(value).toBeTruthy(); - }); - }); - - describe("requestPositionInfo", function () { - it("validates argument length", function () { - expect(function () { - DeviceStateInfo.requestPositionInfo(); - }).toThrow(); - }); - - it("validates argument", function () { - expect(function () { - DeviceStateInfo.requestPositionInfo("abcdef"); - }).toThrow(); - }); - - it("accepts expected argument", function () { - expect(function () { - DeviceStateInfo.requestPositionInfo(""); - DeviceStateInfo.requestPositionInfo("gps"); - }).toThrow(); - }); - - it("calls onPositionRetrieved with empty positionInfo when time out", function () { - runs(function () { - var geo = require('ripple/geo'), - utils = require('ripple/utils'), - origTimeout = geo.timeout; - - geo.timeout = true; - - DeviceStateInfo.onPositionRetrieved = function (pos) { - expect(pos).toBeDefined(); - - utils.forEach(pos, function (prop) { - expect(prop).not.toBeDefined(); - }); - }; - - DeviceStateInfo.requestPositionInfo("gps"); - geo.timeout = origTimeout; - }); - }); - }); - - describe("audioPath", function () { - it("should return the current 'persisted' device's audio path", function () { - deviceSettings.register("DeviceStateInfo.audioPath", "WHATUP"); - var value = DeviceStateInfo.audioPath; - expect(value).toEqual("WHATUP"); - }); - }); - - describe("processorUtilizationPercent", function () { - it("should return the current 'persisted' cpu percentage", function () { - deviceSettings.register("DeviceStateInfo.processorUtilizationPercent", "500%"); - var value = DeviceStateInfo.processorUtilizationPercent; - expect(value).toEqual("500%"); - }); - }); - - describe("onScreenChangeDimensions", function () { - it("should fire when the screen changes dimensions", function () { - DeviceStateInfo.onScreenChangeDimensions = s.mock().once().withExactArgs(480, 800); - event.trigger("ScreenChangeDimensions", [480, 800]); - waits(1); - runs(function () { - DeviceStateInfo.onScreenChangeDimensions = null; - }); - }); - }); -}); diff --git a/test/unit/wac/Message.js b/test/unit/wac/Message.js deleted file mode 100644 index bbb7f38c..00000000 --- a/test/unit/wac/Message.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_Message", function () { - - var s, - sinon = require('sinon'), - Message = require('ripple/platform/wac/1.0/Message'); - - beforeEach(function () { - s = sinon.sandbox.create(); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("it is an instance of message", function () { - expect(new Message() instanceof Message).toEqual(true); - }); - -}); diff --git a/test/unit/wac/Messaging.js b/test/unit/wac/Messaging.js deleted file mode 100644 index c70abe41..00000000 --- a/test/unit/wac/Messaging.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_Messaging", function () { - var messaging = require('ripple/platform/wac/1.0/Messaging'), - Message = require('ripple/platform/wac/1.0/Message'), - platform = require('ripple/platform'), - notifications = require('ripple/notifications'), - constants = require('ripple/constants'), - _console = require('ripple/console'), - MessageTypes = require('ripple/platform/wac/1.0/MessageTypes'), - sinon = require('sinon'), - s; - - beforeEach(function () { - s = sinon.sandbox.create(); - spyOn(_console, "log"); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("is a message returned on create", function () { - var msg = messaging.createMessage(MessageTypes.SMSMessage); - expect(msg.messageType).toEqual(MessageTypes.SMSMessage, "The message isn't the right type"); - }); - - it("is a message sent on send", function () { - var text, - msg = new Message(); - - msg.messageType = MessageTypes.SMSMessage; - msg.messageId = 1; - msg.destinationAddress = "1234567890"; - text = "Sent " + msg.messageType + " " + msg.messageId + " to " + msg.destinationAddress; - - spyOn(platform, "current").andReturn({name: "whatup"}); - s.mock(notifications).expects("openNotification") - .withExactArgs(constants.NOTIFICATIONS.TYPES.NORMAL, text).once(); - - messaging.sendMessage(msg); - }); - - it("send throws invalid parameter when not passed a message object", function () { - expect(function () { - messaging.sendMessage({}); - }).toThrow(); - }); - - it("it can't add an address for something weird", function () { - var msg = new Message(); - msg.addAddress("FOOOBAR", "5199541707"); - expect(msg.FOOOBAR).not.toBeDefined(); - }); - - it("it can add the destination address", function () { - var msg = new Message(); - msg.addAddress("destination", "5199541707"); - expect(msg.destinationAddress[0]).toEqual("5199541707"); - }); - - it("it can add a couple destination addresses", function () { - var msg = new Message(); - msg.addAddress("destination", "5199541707;2269297927"); - expect(msg.destinationAddress[0]).toEqual("5199541707"); - expect(msg.destinationAddress[1]).toEqual("2269297927"); - }); - - it("it can add the cc address", function () { - var msg = new Message(); - msg.addAddress("cc", "5199541707"); - expect(msg.ccAddress[0]).toEqual("5199541707"); - }); - - it("it can add a couple cc addresses", function () { - var msg = new Message(); - msg.addAddress("cc", "5199541707;2269297927"); - expect(msg.ccAddress[0]).toEqual("5199541707"); - expect(msg.ccAddress[1]).toEqual("2269297927"); - }); - - it("it can add the bcc address", function () { - var msg = new Message(); - msg.addAddress("bcc", "5199541707"); - expect(msg.bccAddress[0]).toEqual("5199541707"); - }); - - it("it can add a couple bcc addresses", function () { - var msg = new Message(); - msg.addAddress("bcc", "5199541707;2269297927"); - expect(msg.bccAddress[0]).toEqual("5199541707"); - expect(msg.bccAddress[1]).toEqual("2269297927"); - }); - - it("it can delete a bcc address", function () { - var msg = new Message(); - msg.addAddress("bcc", "5199541707;2269297927"); - msg.deleteAddress("bcc", "2269297927"); - - expect(msg.bccAddress.length).toEqual(1); - expect(msg.bccAddress[0]).toEqual("5199541707"); - }); -}); diff --git a/test/unit/wac/Multimedia.js b/test/unit/wac/Multimedia.js deleted file mode 100644 index 9b36c5bd..00000000 --- a/test/unit/wac/Multimedia.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_Multimedia", function () { - - var Multimedia = require('ripple/platform/wac/1.0/Multimedia'), - AudioPlayer = require('ripple/platform/wac/1.0/AudioPlayer'), - VideoPlayer = require('ripple/platform/wac/1.0/VideoPlayer'), - event = require('ripple/event'); - - // -------- getVolume - - it("getVolume should return a number between zero and ten", function () { - event.trigger("MultimediaVolumeChanged", [7]); - waits(1); - runs(function () { - expect(Multimedia.getVolume()).toEqual(7); - }); - }); - - // -------- stopAll - - it("stopAll stops both audio and video modules", function () { - spyOn(VideoPlayer, "stop"); - spyOn(AudioPlayer, "stop"); - Multimedia.stopAll(); - expect(VideoPlayer.stop).toHaveBeenCalled(); - expect(AudioPlayer.stop).toHaveBeenCalled(); - }); - - // -------- isAudioPlaying - - it("isAudioPlaying returns false when not playing", function () { - event.trigger("MultimediaAudioStateChanged", ["playing"]); - waits(1); - runs(function () { - expect(Multimedia.isAudioPlaying).toEqual(true); - }); - }); - - // -------- isVideoPlaying - - it("isVideoPlaying returns false when not playing", function () { - event.trigger("MultimediaVideoStateChanged", ["playing"]); - waits(1); - runs(function () { - expect(Multimedia.isVideoPlaying).toEqual(true); - }); - }); - -}); diff --git a/test/unit/wac/PIM.js b/test/unit/wac/PIM.js deleted file mode 100644 index 1b66d69f..00000000 --- a/test/unit/wac/PIM.js +++ /dev/null @@ -1,867 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_PIM", function () { - - var pim = require('ripple/platform/wac/1.0/PIM'), - sinon = require('sinon'), - CalendarItem = require('ripple/platform/wac/1.0/CalendarItem'), - AddressBookItem = require('ripple/platform/wac/1.0/AddressBookItem'), - constants = require('ripple/constants'), - db = require('ripple/db'), - s; - - beforeEach(function () { - s = sinon.sandbox.create(); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("createAddressBookItem returns an empty AddressBookItem", function () { - expect(pim.createAddressBookItem() instanceof AddressBookItem).toEqual(true); - }); - - it("getAddressBookItem returns the item for the given ID", function () { - var items = [ - {addressBookItemId: "1"}, - {addressBookItemId: "2"}, - {addressBookItemId: "3"} - ]; - - s.stub(db, "retrieveObject").returns(items); - expect(pim.getAddressBookItem("2").addressBookItemId).toEqual(items[1].addressBookItemId); - }); - - it("getAddressBookItem returns null when no items match the given ID", function () { - s.stub(db, "retrieveObject").returns([]); - expect(pim.getAddressBookItem("2")).toBeNull(); - }); - - it("getAddressBookItem returns null when nothing returned from persistence", function () { - s.stub(db, "retrieveObject").returns(undefined); - expect(pim.getAddressBookItem("2")).toBeNull(); - }); - - it("getAddressBookItemsCount returns the count of items", function () { - var items = [ - {addressBookItemId: "a"}, - {addressBookItemId: "b"}, - {addressBookItemId: "c"} - ]; - - s.stub(db, "retrieveObject").returns(items); - expect(pim.getAddressBookItemsCount()).toEqual(items.length); - }); - - it("getAddressBookItemsCount returns 5 when persitence returns undefined", function () { - //this is because of the default contacts ;) - s.stub(db, "retrieveObject").returns(undefined); - s.mock(db).expects("saveObject").once(); - - expect(pim.getAddressBookItemsCount()).toEqual(5); - }); - - it("addAddressBookItem should add an item to the persisted list", function () { - var items = [], - added = new AddressBookItem(); - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.ADDRESS_LIST_KEY, [added]); - - pim.addAddressBookItem(added); - }); - - it("addAddressBookItem should set id if none provided", function () { - var items = [], - added = new AddressBookItem(); - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.ADDRESS_LIST_KEY, [added]); - - pim.addAddressBookItem(added); - expect(added.addressBookItemId).toBeTruthy(); - }); - - it("addAddressBookItem should not set id if one is provided", function () { - var items = [], - added = new AddressBookItem(), - id = "AF7492"; - - added.addressBookItemId = id; - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.ADDRESS_LIST_KEY, [added]); - - pim.addAddressBookItem(added); - expect(added.addressBookItemId).toEqual(id); - }); - - it("addAddressBookItem throws an exception when passed in a null item", function () { - expect(function () { - var foo = null; - pim.addAddressBookItem(foo); - }).toThrow(); - }); - - it("addAddressBookItem throws an exception when passed in an invalid address book item", function () { - expect(function () { - pim.addAddressBookItem({ - title: "", - address: "" - }); - }).toThrow(); - }); - - it("deleteAddressBookItem should remove an item from the persisted list", function () { - var items = [ - {addressBookItemId: "a"}, - {addressBookItemId: "b"}, - {addressBookItemId: "c"} - ]; - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.ADDRESS_LIST_KEY, [items[0], items[2]]); - - pim.deleteAddressBookItem("b"); - }); - - it("deleteAddressBookItem shouldn't delete if not match found", function () { - var items = [ - {addressBookItemId: "a"}, - {addressBookItemId: "b"}, - {addressBookItemId: "c"} - ]; - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.ADDRESS_LIST_KEY, items); - - pim.deleteAddressBookItem("d"); - }); - - it("should raise the onAddressBookItemsFound event when searching", function () { - s.stub(db, "retrieveObject").returns([]); - s.stub(db, "saveObject"); - - pim.onAddressBookItemsFound = s.mock().withExactArgs([]).once(); - pim.findAddressBookItems({title: "Dr"}, 0, 1); - }); - - it("should be able to search for addressBookItemId", function () { - var items = [ - {addressBookItemId: "a"}, - {addressBookItemId: "b"}, - {addressBookItemId: "c"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({addressBookItemId: "b"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - - expect(result.length).toEqual(1); - expect(result[0].addressBookItemId).toEqual("b"); - }); - - it("should be able to search for fullName", function () { - var items = [ - {fullName: "Gord"}, - {fullName: "Steph"}, - {fullName: "Gwen"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gwen"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - - expect(result.length).toEqual(1); - expect(result[0].fullName).toEqual("Gwen"); - }); - - it("should be able to search for a blank fullName", function () { - var items = [ - {fullName: "Gord"}, - {fullName: "Steph"}, - {fullName: "", mobilePhone: "555-1234"}, - {fullName: "Gwen"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].mobilePhone).toEqual("555-1234"); - expect(result[0].fullName).toEqual(""); - }); - - it("should be able to search for mobilePhone", function () { - var items = [ - {mobilePhone: "555-1234"}, - {mobilePhone: "555-2222"}, - {mobilePhone: "555-2222"}, - {mobilePhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({mobilePhone: "555-1234"}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].mobilePhone).toEqual("555-1234"); - expect(result[1].mobilePhone).toEqual("555-1234"); - }); - - it("should be able to search for a blank mobilePhone", function () { - var items = [ - {mobilePhone: "555-1234"}, - {mobilePhone: "555-2222"}, - {mobilePhone: ""}, - {mobilePhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({mobilePhone: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].mobilePhone).toEqual(""); - }); - - it("should be able to search for homePhone", function () { - var items = [ - {homePhone: "555-1234"}, - {homePhone: "555-2222"}, - {homePhone: "555-2222"}, - {homePhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({homePhone: "555-2222"}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].homePhone).toEqual("555-2222"); - expect(result[1].homePhone).toEqual("555-2222"); - }); - - it("should be able to search for a blank homePhone", function () { - var items = [ - {homePhone: "555-1234"}, - {homePhone: ""}, - {homePhone: "555-2222"}, - {homePhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({homePhone: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].homePhone).toEqual(""); - }); - - it("should be able to search for workPhone", function () { - var items = [ - {workPhone: "555-1234"}, - {workPhone: "555-2222"}, - {workPhone: "555-2222"}, - {workPhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({workPhone: "555-2222"}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].workPhone).toEqual("555-2222"); - expect(result[1].workPhone).toEqual("555-2222"); - }); - - it("should be able to search for a blank workPhone", function () { - var items = [ - {workPhone: ""}, - {workPhone: "555-2222"}, - {workPhone: ""}, - {workPhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({workPhone: ""}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].workPhone).toEqual(""); - expect(result[1].workPhone).toEqual(""); - }); - - it("should be able to search for eMail", function () { - var items = [ - {eMail: "gord@tinyhippos.com"}, - {eMail: "gtanner@gmail.com"}, - {eMail: "gord.tanner@tinyhippos.com"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({eMail: "gord@tinyhippos.com"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].eMail).toEqual("gord@tinyhippos.com"); - }); - - it("should be able to search for blank eMail", function () { - var items = [ - {eMail: "gord@tinyhippos.com"}, - {eMail: ""}, - {eMail: "gtanner@gmail.com"}, - {eMail: ""}, - {eMail: "gord.tanner@tinyhippos.com"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({eMail: ""}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].eMail).toEqual(""); - expect(result[1].eMail).toEqual(""); - }); - - it("should be able to search for company", function () { - var items = [ - {company: "tinyhippos.com"}, - {company: "tinyhippos.com"}, - {company: "tinyhippos.com"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({company: "tinyhippos.com"}, 0, 3); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(3); - }); - - it("should be able to search for a blank company", function () { - var items = [ - {company: "tinyhippos.com"}, - {company: ""}, - {company: "tinyhippos.com"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({company: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].company).toEqual(""); - }); - - it("should be able to search for title", function () { - var items = [ - {title: "Dr"}, - {title: "Dr"}, - {title: "Overlord"}, - {title: "Dr"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({title: "Overlord"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].title).toEqual("Overlord"); - }); - - it("should be able to search for a blank title", function () { - var items = [ - {title: "Dr"}, - {title: ""}, - {title: "Overlord"}, - {title: "Dr"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({title: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].title).toEqual(""); - }); - - it("should be able to search for address", function () { - var items = [ - {address: "123 Anystreet"}, - {address: "53 Patricia Ave"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({address: "123 Anystreet"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].address).toEqual("123 Anystreet"); - }); - - it("should be able to search for a blank address", function () { - var items = [ - {address: "123 Anystreet"}, - {address: ""}, - {address: "53 Patricia Ave"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({address: ""}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].address).toEqual(""); - }); - - it("can search by multiple values", function () { - var items = [ - {fullName: "Gord", workPhone: "555-1234"}, - {fullName: "Gord", workPhone: "555-2222"}, - {fullName: "Gord", workPhone: "555-2222"}, - {fullName: "Gord", workPhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gord", workPhone: "555-2222"}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - }); - - it("can search when a search param is null but the entity has a value", function () { - var items = [ - {fullName: "Gord", workPhone: "555-1234"}, - {fullName: "Gord", workPhone: null}, - {fullName: "Gord", workPhone: null}, - {fullName: "Gord", workPhone: "555-1234"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gord", workPhone: null}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - }); - - it("searching is case insensitive", function () { - var items = [ - {fullName: "Gord", workPhone: "5551111"}, - {fullName: "GORD", workPhone: "5552222"}, - {fullName: "GoRd", workPhone: "5552222"}, - {fullName: "gOrD", workPhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gord"}, 0, 4); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(4); - }); - - it("searching can use wildcards", function () { - var items = [ - {fullName: "Gord", workPhone: "5551111"}, - {fullName: "Gwen", workPhone: "5552222"}, - {fullName: "Griffin", workPhone: "5552222"}, - {fullName: "Steph", workPhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "G*"}, 0, 3); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(3); - expect(result[0].fullName).toEqual("Gord"); - }); - - it("can escape * when searching", function () { - var calls = [ - {fullName: "Steph", workPhone: "5551111"}, - {fullName: "Gwen", workPhone: "5552222"}, - {fullName: "Griffin", workPhone: "5552222"}, - {fullName: "Gord", workPhone: "*69"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({workPhone: "\\*69"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].workPhone).toEqual("*69"); - }); - - it("can search with multiple wildcards", function () { - var calls = [ - {fullName: "Steph", workPhone: "5551111"}, - {fullName: "Gwen", workPhone: "5551234"}, - {fullName: "Griffin", workPhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({workPhone: "*12*"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].workPhone).toEqual("5551234"); - }); - - it("can search for strings containing escaped single quotes", function () { - var calls = [ - {fullName: "George O'Conner"}, - {fullName: "Larry"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "*O\'Conner"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].fullName).toEqual("George O'Conner"); - }); - - it("can search for strings containing escaped double quotes", function () { - var calls = [ - {fullName: 'George O"Conner'}, - {fullName: "Larry"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "*O\"Conner"}, 0, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].fullName).toEqual('George O"Conner'); - }); - - it("can search for only the first 2 records", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "g*"}, 0, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].fullName).toEqual("Gwen"); - expect(result[1].fullName).toEqual("Griffin"); - }); - - it("can serach for the third and forth records", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "g*"}, 2, 4); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].fullName).toEqual("Gwen"); - expect(result[1].fullName).toEqual("Gwen"); - }); - - it("if startInx equals, only one item whose sequence number is startInx is returned", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "g*"}, 2, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].fullName).toEqual("Gwen"); - expect(result[0].homePhone).toEqual("5551234"); - }); - - it("if startInx is greater than endInx the returned callRecordsFound will be an empty array.", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "g*"}, 4, 2); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(0); - }); - - it("if startInx is greater than the number of found item the returned callRecordsFound will be an empty array.", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gord", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gord"}, 3, 6); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(0); - }); - - it("if endInx is greater than the number of found items the returned callRecordsFound will contain items between startInx and the last returned item", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gord", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gwen"}, 0, 6); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(2); - expect(result[0].fullName).toEqual("Gwen"); - expect(result[1].fullName).toEqual("Gwen"); - }); - - it("if endInx is positive and startInx is negative, startInx will be treated as 0", function () { - var calls = [ - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Gord", homePhone: "5551234"}, - {fullName: "Gwen", homePhone: "5551234"}, - {fullName: "Griffin", homePhone: "5552222"}, - {fullName: "Griffin", homePhone: "5552222"} - ], result; - - s.stub(db, "retrieveObject").returns(calls); - pim.onAddressBookItemsFound = s.mock().once(); - pim.findAddressBookItems({fullName: "Gwen"}, -1, 1); - - result = pim.onAddressBookItemsFound.args[0][0]; - expect(result.length).toEqual(1); - expect(result[0].fullName).toEqual("Gwen"); - }); - - it("if endInx is negative throws INVALID_PARAMETER exception", function () { - expect(function () { - pim.findAddressBookItems({fullName: "Gwen"}, 0, -1); - }).toThrow(); - }); - - it("if comparisonContact is invalid throws INVALID_PARAMETER exception", function () { - expect(function () { - pim.findAddressBookItems("Gwen", 0, 1); - }).toThrow(); - }); - - it("if startInx is not a number throws INVALID_PARAMETER exception", function () { - expect(function () { - pim.findAddressBookItems({fullName: "Gwen"}, "test", 1); - }).toThrow(); - }); - - it("if endInx is not a number throws INVALID_PARAMETER exception", function () { - expect(function () { - pim.findAddressBookItems({fullName: "Gwen"}, 0, "test"); - }).toThrow(); - }); - - it("addCalendarItem should add an item to the persisted list", function () { - var items = [], - added = new CalendarItem(); - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.CALENDAR_LIST_KEY, [added]); - - pim.addCalendarItem(added); - }); - - it("deleteCalendarItem should remove an item from the persisted list", function () { - var items = [ - {calendarItemId: "a"}, - {calendarItemId: "b"}, - {calendarItemId: "c"} - ]; - - s.stub(db, "retrieveObject").returns(items); - s.mock(db).expects("saveObject").once().withExactArgs(constants.PIM.CALENDAR_LIST_KEY, [items[0], items[2]]); - - pim.deleteCalendarItem("b"); - }); - - it("getCalendarItem returns the item for the given ID", function () { - var items = [ - {calendarItemId: "1"}, - {calendarItemId: "2"}, - {calendarItemId: "3"} - ]; - - s.stub(db, "retrieveObject").returns(items); - expect(items[1].calendarItemId).toEqual(pim.getCalendarItem("2").calendarItemId); - }); - - it("should raise the onCalendarItemsFound event when searching", function () { - s.stub(db, "retrieveObject").returns([]); - - pim.onCalendarItemsFound = s.mock().withExactArgs([]).once(); - pim.findCalendarItems({eventName: "w00t"}); - }); - - it("should be able to search for calendarItemId", function () { - var items = [ - {calendarItemId: "a"}, - {calendarItemId: "b"}, - {calendarItemId: "c"} - ]; - - s.stub(db, "retrieveObject").returns(items); - pim.onCalendarItemsFound = s.mock().once(); - pim.findCalendarItems({calendarItemId: "b"}); - }); - - it("should be able to search for alarmDate", function () { - var items = [ - {alarmDate: new Date(new Date().setMonth(1))}, - {alarmDate: new Date(new Date().setMonth(2))}, - {alarmDate: new Date(new Date().setMonth(3))} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onCalendarItemsFound = s.mock().once(); - pim.findCalendarItems({alarmDate: items[1].alarmDate}); - - result = pim.onCalendarItemsFound.args[0][0]; - - expect(result.length).toEqual(1); - expect(result[0].alarmDate).toEqual(items[1].alarmDate); - }); - - it("should be able to search for eventStartTime", function () { - var items = [ - {eventStartTime: new Date(new Date().setMonth(1))}, - {eventStartTime: new Date(new Date().setMonth(2))}, - {eventStartTime: new Date(new Date().setMonth(3))} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onCalendarItemsFound = s.mock().once(); - pim.findCalendarItems({eventStartTime: items[1].eventStartTime}); - - result = pim.onCalendarItemsFound.args[0][0]; - - expect(result.length).toEqual(1); - expect(result[0].eventStartTime).toEqual(items[1].eventStartTime); - }); - - it("should be able to search for events in a timebox", function () { - var items = [ - {eventStartTime: new Date(new Date().setMonth(1)), eventEndTime: new Date(new Date().setMonth(3))}, - {eventStartTime: new Date(new Date().setMonth(2)), eventEndTime: new Date(new Date().setMonth(3))}, - {eventStartTime: new Date(new Date().setMonth(4)), eventEndTime: new Date(new Date().setMonth(5))} - ], result; - - s.stub(db, "retrieveObject").returns(items); - pim.onCalendarItemsFound = s.mock().never(); - - result = pim.getCalendarItems(items[0].eventStartTime, items[1].eventEndTime); - - expect(result.length).toEqual(2); - }); - - it("I can call a method on a returned addressbook item", function () { - var items = [ - {addressBookItemId: "1"}, - {addressBookItemId: "2"}, - {addressBookItemId: "3"} - ], - contact; - - s.stub(db, "retrieveObject").returns(items); - contact = pim.getAddressBookItem("1"); - - expect(contact.getAvailableAttributes()); - }); - - it("the returned calendar item has the update method", function () { - var items = [ - {calendarItemId: "a"}, - {calendarItemId: "b"}, - {calendarItemId: "c"} - ], - event; - - s.stub(db, "retrieveObject").returns(items); - event = pim.getCalendarItem("b"); - - expect(event.update); - }); -}); diff --git a/test/unit/wac/PositionInfo.js b/test/unit/wac/PositionInfo.js deleted file mode 100644 index fd733ff7..00000000 --- a/test/unit/wac/PositionInfo.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_PositionInfo", function () { - var PositionInfo = require('ripple/platform/wac/1.0/PositionInfo'), - db = require('ripple/db'), - geo = require('ripple/geo'), - stub = { - "latitude": 43.465187, - "longitude": -80.522372, - "altitude": 100, - "accuracy": 150, - "altitudeAccuracy": 80, - "cellID": 321654, - "timeStamp": new Date() - }, - sinon = require('sinon'), - s; - - beforeEach(function () { - s = sinon.sandbox.create(); - s.stub(db, "retrieveObject").returns(stub); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("gets its default values from the db", function () { - spyOn(geo, "getPositionInfo").andReturn(stub); - expect(PositionInfo.latitude).toEqual(stub.latitude); - expect(PositionInfo.longitude).toEqual(stub.longitude); - expect(PositionInfo.altitude).toEqual(stub.altitude); - expect(PositionInfo.accuracy).toEqual(stub.accuracy); - expect(PositionInfo.altitudeAccuracy).toEqual(stub.altitudeAccuracy); - expect(PositionInfo.cellID).toEqual(stub.cellID); - }); -}); diff --git a/test/unit/wac/PowerInfo.js b/test/unit/wac/PowerInfo.js deleted file mode 100644 index 46b60643..00000000 --- a/test/unit/wac/PowerInfo.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_PowerInfo", function () { - var PowerInfo = require('ripple/platform/wac/1.0/PowerInfo'), - deviceSettings = require('ripple/deviceSettings'), - event = require('ripple/event'), - _console = require('ripple/console'), - platform = require('ripple/platform'); - - beforeEach(function () { - spyOn(_console, "error"); - spyOn(_console, "log"); - spyOn(platform, "current").andReturn({ - name: "whatup", - device: { - "PowerInfo": { - "isCharging": {control: {value: false}}, - "percentRemaining": {control: {value: 98}} - } - } - }); - }); - - it("isCharging should return default control value", function () { - expect(PowerInfo.isCharging).toEqual(false); - }); - - it("percentRemaining returns default control value", function () { - expect(PowerInfo.percentRemaining).toEqual(98); - }); - - it("isCharging state change invokes onChargeStateChange", function () { - spyOn(deviceSettings, "retrieve").andReturn(50); - PowerInfo.onChargeStateChange = jasmine.createSpy(); - - event.trigger("DeviceBatteryStateChanged", [], true); - - expect(PowerInfo.onChargeStateChange).toHaveBeenCalled(); - delete PowerInfo.onChargeStateChange; - }); - - it("isCharging state change invokes onChargeStateChange with discharging", function () { - spyOn(deviceSettings, "retrieve").andReturn(30); - PowerInfo.onChargeStateChange = jasmine.createSpy(); - - event.trigger("DeviceBatteryStateChanged", [true], true); - - expect(PowerInfo.onChargeStateChange).toHaveBeenCalledWith("charging"); - delete PowerInfo.onChargeStateChange; - }); - - it("onChargeStateChange invokes properly when changing to 100 percent battery level", function () { - spyOn(deviceSettings, "retrieve").andReturn(100); - PowerInfo.onChargeStateChange = jasmine.createSpy(); - - event.trigger("DeviceBatteryStateChanged", [true], true); - - expect(PowerInfo.onChargeStateChange).toHaveBeenCalledWith("full"); - delete PowerInfo.onChargeStateChange; - }); - - it("onChargeStateChange invokes properly when changing from 100 percent battery level", function () { - spyOn(deviceSettings, "retrieve").andReturn(99); - PowerInfo.onChargeStateChange = jasmine.createSpy(); - - event.trigger("DeviceBatteryStateChanged", [false], true); - - expect(PowerInfo.onChargeStateChange).toHaveBeenCalledWith("discharging"); - delete PowerInfo.onChargeStateChange; - }); - - it("percentRemaining update invokes onChargeLevelChange with proper args", function () { - spyOn(deviceSettings, "retrieve").andReturn(99); - PowerInfo.onChargeLevelChange = jasmine.createSpy(); - - event.trigger("DeviceBatteryLevelChanged", [5], true); - - expect(PowerInfo.onChargeLevelChange).toHaveBeenCalledWith(5); - delete PowerInfo.onChargeLevelChange; - }); - - it("percentRemaining should invoke onLowBattery when below ten percent", function () { - spyOn(deviceSettings, "retrieve").andReturn(99); - PowerInfo.onLowBattery = jasmine.createSpy(); - - event.trigger("DeviceBatteryLevelChanged", [7], true); - - expect(PowerInfo.onLowBattery).toHaveBeenCalledWith(7); - delete PowerInfo.onLowBattery; - }); -}); diff --git a/test/unit/wac/RadioInfo.js b/test/unit/wac/RadioInfo.js deleted file mode 100644 index 21c05bc5..00000000 --- a/test/unit/wac/RadioInfo.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_RadioInfo", function () { - - var RadioInfo = require('ripple/platform/wac/1.0/RadioInfo'), - RadioSignalSourceTypes = require('ripple/platform/wac/1.0/RadioSignalSourceTypes'), - utils = require('ripple/utils'), - event = require('ripple/event'), - _console = require('ripple/console'), - platform = require('ripple/platform'); - - function _isValidSignalSource(sourceToCheck) { - var validValues = RadioSignalSourceTypes, - flag = false; - - utils.forEach(validValues, function (sourceKey, sourceValue) { - if (sourceToCheck === sourceValue) { - flag = true; - return true; - } - }); - - return flag; - } - - beforeEach(function () { - spyOn(platform, "current").andReturn({ - name: "whatup", - device: { - "RadioInfo": { - "isRoaming": {control: {value: true}}, - "isRadioEnabled": {control: {value: false}}, - "radioSignalStrengthPercent": {control: {value: 60}}, - "radioSignalSource": {control: {value: "LTE"}} - } - } - }); - }); - - // --------- Tests -------- \\ - - it("isRoaming returns default control", function () { - expect(RadioInfo.isRoaming).toEqual(true); - }); - - it("isRadioEnabled returns a default control", function () { - expect(RadioInfo.isRadioEnabled).toEqual(false); - }); - - it("radioSignalStrengthPercent returns a default value", function () { - expect(RadioInfo.radioSignalStrengthPercent).toEqual(60); - }); - - it("radioSignalSource is returns a default value", function () { - expect(_isValidSignalSource(RadioInfo.radioSignalSource)).toEqual(true); - }); - - it("radioSignalSource change invokes onSignalSourceChange when changed", function () { - spyOn(_console, "log"); - RadioInfo.onSignalSourceChange = jasmine.createSpy(); - event.trigger("RadioSignalSourceChanged", [], true); - - expect(RadioInfo.onSignalSourceChange).toHaveBeenCalledWith("LTE", true); - delete RadioInfo.onSignalSourceChange; - }); - -}); diff --git a/test/unit/wac/Telephony.js b/test/unit/wac/Telephony.js deleted file mode 100644 index 046a6943..00000000 --- a/test/unit/wac/Telephony.js +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_Telephony", function () { - - var telephony = require('ripple/platform/wac/1.0/Telephony'), - CallRecord = require('ripple/platform/wac/1.0/CallRecord'), - callType = require('ripple/platform/wac/1.0/CallRecordTypes'), - device = require('ripple/platform/wac/1.0/Device'), - db = require('ripple/db'), - sinon = require('sinon'), - s; - - beforeEach(function () { - s = sinon.sandbox.create(); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("should initiate a voice call", function () { - s.mock(device) - .expects("launchApplication") - .withExactArgs("PHONECALL", "5199541707") - .once(); - - telephony.initiateVoiceCall("5199541707"); - }); - - it("call record is an instance of call record", function () { - expect(new CallRecord() instanceof CallRecord).toBeTruthy(); - }); - - it("should fire the onCallEvent when initiating a voice call", function () { - s.stub(device, "launchApplication"); - - telephony.onCallEvent = s.mock().withExactArgs(callType.OUTGOING, "5199541707").once(); - telephony.initiateVoiceCall("5199541707"); - }); - - it("should get the count of call records", function () { - s.stub(db, "retrieveObject") - .returns([{callRecordType: callType.MISSED}, - {callRecordType: callType.MISSED}]); - - expect(2).toEqual(telephony.getCallRecordCnt(callType.MISSED)); - }); - - it("should only count the call records of the requested type", function () { - s.mock(db) - .expects("retrieveObject") - .once() - .returns([{callRecordType: callType.MISSED}, - {callRecordType: callType.OUTGOING}]); - - expect(1).toEqual(telephony.getCallRecordCnt(callType.MISSED)); - }); - - it("should return a count of 0 call records if the type is unknown", function () { - s.mock(db) - .expects("retrieveObject") - .once() - .returns([{callRecordType: callType.MISSED}, - {callRecordType: callType.MISSED}]); - - expect(0).toEqual(telephony.getCallRecordCnt("foo")); - }); - - it("should return the callRecord with the given id", function () { - s.stub(db, "retrieveObject") - .returns([{callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"}]); - - var call = telephony.getCallRecord(callType.MISSED, "1"); - - expect(call).not.toBeNull(); - }); - - it("should return null when attempt to get callRecord by not in found", function () { - s.stub(db, "retrieveObject").returns([]); - var call = telephony.getCallRecord(callType.MISSED, "1"); - expect(call).toBeNull(); - }); - - it("should delete a call record by id", function () { - var calls = [ - {callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - s.mock(db).expects("saveObject").once(); - - telephony.deleteCallRecord(callType.MISSED, "1"); - - expect(1).toEqual(calls.length); - }); - - it("shouldn't delete a record if no matches", function () { - var calls = [ - {callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - s.mock(db).expects("saveObject").never(); - - telephony.deleteCallRecord(callType.OUTGOING, "1"); - - expect(2).toEqual(calls.length); - }); - - it("should delete all calls of the given type", function () { - var calls = [ - {callRecordType: callType.OUTGOING, callRecordId: "1"}, - {callRecordType: callType.OUTGOING, callRecordId: "2"}, - {callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - s.mock(db).expects("saveObject").once(); - - telephony.deleteAllCallRecords(callType.OUTGOING); - - expect(2).toEqual(calls.length); - }); - - it("should raise the onCallRecordsFound when searching", function () { - - s.stub(db, "retrieveObject").returns([]); - - telephony.onCallRecordsFound = s.mock().withExactArgs([]).once(); - telephony.findCallRecords({callRecordType: callType.MISSED}); - }); - - it("can search for records by type", function () { - - var calls = [ - {callRecordType: callType.OUTGOING, callRecordId: "1"}, - {callRecordType: callType.OUTGOING, callRecordId: "2"}, - {callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2], calls[3]]).once(); - telephony.findCallRecords({callRecordType: callType.MISSED}); - }); - - it("can search for records by id", function () { - - var calls = [ - {callRecordType: callType.OUTGOING, callRecordId: "1"}, - {callRecordType: callType.OUTGOING, callRecordId: "2"}, - {callRecordType: callType.MISSED, callRecordId: "1"}, - {callRecordType: callType.MISSED, callRecordId: "2"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0], calls[2]]).once(); - telephony.findCallRecords({callRecordId: "1"}); - }); - - it("can search for records by name", function () { - var calls = [ - {callRecordName: "Gwen"}, - {callRecordName: "Steph"}, - {callRecordName: "Griffin"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0]]).once(); - telephony.findCallRecords({callRecordName: "Gwen"}); - }); - - it("can search for records with a blank name", function () { - var calls = [ - {callRecordName: "Gwen"}, - {callRecordName: "Steph"}, - {callRecordName: "", callRecordAddress: "5551234"}, - {callRecordName: "Griffin"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2]]).once(); - telephony.findCallRecords({callRecordName: ""}); - }); - - it("can search for records by address", function () { - var calls = [ - {callRecordAddress: "5552222"}, - {callRecordAddress: "5551111"}, - {callRecordAddress: "5551234"}, - {callRecordAddress: "5551111"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1], calls[3]]).once(); - telephony.findCallRecords({callRecordAddress: "5551111"}); - }); - - it("can search for records with a blank address", function () { - var calls = [ - {callRecordAddress: "5552222"}, - {callRecordAddress: "5551111"}, - {callRecordAddress: ""}, - {callRecordAddress: "5551111"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2]]).once(); - telephony.findCallRecords({callRecordAddress: ""}); - }); - - it("can search for records by duration", function () { - var calls = [ - {durationSeconds: 60}, - {durationSeconds: 120}, - {durationSeconds: 60} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1]]).once(); - telephony.findCallRecords({durationSeconds: 120}); - }); - - it("can search for records by start time", function () { - var calls = [ - {startTime: new Date(new Date() - 100)}, - {startTime: new Date(new Date() - 200)}, - {startTime: new Date(new Date() - 300)} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2]]).once(); - telephony.findCallRecords({startTime: calls[2].startTime}); - }); - - it("can search by multiple values", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551111"}, - {callRecordName: "Gwen", callRecordAddress: "5552222"}, - {callRecordName: "Gwen", callRecordAddress: "5552222"}, - {callRecordName: "Steph", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1], calls[2]]).once(); - telephony.findCallRecords({callRecordName: "Gwen", callRecordAddress: "5552222"}); - }); - - it("searching is case insensitive", function () { - var calls = [ - {callRecordName: "Gord", callRecordAddress: "5551111"}, - {callRecordName: "GORD", callRecordAddress: "5552222"}, - {callRecordName: "GoRd", callRecordAddress: "5552222"}, - {callRecordName: "gOrD", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs(calls).once(); - telephony.findCallRecords({callRecordName: "gord"}); - }); - - it("can use wildcards when searching name", function () { - var calls = [ - {callRecordName: "Steph", callRecordAddress: "5551111"}, - {callRecordName: "Gwen", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gord", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1], calls[2], calls[3]]).once(); - telephony.findCallRecords({callRecordName: "G*"}); - - }); - - it("can use wildcards when searching for address", function () { - var calls = [ - {callRecordName: "Steph", callRecordAddress: "5551111"}, - {callRecordName: "Gwen", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gord", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1], calls[2], calls[3]]).once(); - telephony.findCallRecords({callRecordAddress: "*22*"}); - }); - - it("can escape * when searching", function () { - var calls = [ - {callRecordName: "Steph", callRecordAddress: "5551111"}, - {callRecordName: "Gwen", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gord", callRecordAddress: "*69"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[3]]).once(); - telephony.findCallRecords({callRecordAddress: "\\*69"}); - }); - - - it("can search with multiple wildcards", function () { - var calls = [ - {callRecordName: "Steph", callRecordAddress: "5551111"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[1]]).once(); - telephony.findCallRecords({callRecordAddress: "*12*"}); - }); - - it("can search for strings containing escaped single quotes", function () { - var calls = [ - {callRecordName: "George O'Conner"}, - {callRecordName: "Larry"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0]]).once(); - telephony.findCallRecords({callRecordName: "*O\'Conner"}); - }); - - it("can search for strings containing escaped double quotes", function () { - var calls = [ - {callRecordName: 'George O"Conner'}, - {callRecordName: "Larry"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0]]).once(); - telephony.findCallRecords({callRecordName: "*O\"Conner"}); - }); - - it("can search for only the first 2 records", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0], calls[1]]).once(); - telephony.findCallRecords({callRecordName: "g*"}, 0, 2); - }); - - it("can serach for the third and forth records", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2], calls[3]]).once(); - telephony.findCallRecords({callRecordName: "g*"}, 2, 4); - }); - - it("if startInx equals, only one item whose sequence number is startInx is returned", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[2]]).once(); - telephony.findCallRecords({callRecordName: "g*"}, 2, 2); - }); - - it("if startInx is greater than endInx the returned callRecordsFound will be an empty array.", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([]).once(); - telephony.findCallRecords({callRecordName: "g*"}, 4, 2); - }); - - - it("if startInx is greater than the number of found item the returned callRecordsFound will be an empty array.", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gord", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([]).once(); - telephony.findCallRecords({callRecordName: "Gord"}, 3, 6); - }); - - it("if endInx is greater than the number of found items the returned callRecordsFound will contain items between startInx and the last returned item", function () { - var calls = [ - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Gord", callRecordAddress: "5551234"}, - {callRecordName: "Gwen", callRecordAddress: "5551234"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"}, - {callRecordName: "Griffin", callRecordAddress: "5552222"} - ]; - - s.stub(db, "retrieveObject").returns(calls); - telephony.onCallRecordsFound = s.mock().withExactArgs([calls[0], calls[3]]).once(); - telephony.findCallRecords({callRecordName: "Gwen"}, 0, 6); - }); -}); diff --git a/test/unit/wac/VideoPlayer.js b/test/unit/wac/VideoPlayer.js deleted file mode 100644 index bc6dc9e8..00000000 --- a/test/unit/wac/VideoPlayer.js +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_VideoPlayer", function () { - - var video = require('ripple/platform/wac/1.0/VideoPlayer'), - sinon = require('sinon'), - platform = require('ripple/platform'), - fileSystem = require('ripple/fileSystem'), - _console = require('ripple/console'), - event = require('ripple/event'), - videoNode, domNode, s, - A_VIDEO = "../../short_video.ogv"; - - beforeEach(function () { - s = sinon.sandbox.create(); - domNode = document.createElement("div"); - videoNode = document.createElement("video"); - videoNode.canPlayType = function () { - return "probably"; - }; - // think jsdom does not have special methods like play on videotag - videoNode.play = function () {}; - videoNode.pause = function () {}; - videoNode.stop = function () {}; - - spyOn(platform, "current").andReturn({name: "generic"}); - }); - - afterEach(function () { - domNode = null; - videoNode = null; - s.verifyAndRestore(); - //HACK: this is to clear the state of video player between tests - video.onStateChange = null; - event.trigger("MultimediaVideoStateChanged", [null], true); - }); - - - // -------- setWindow - - it("setWindow sets a video inside a dom object", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - expect(domNode.childNodes.length).toBe(1); - expect(videoNode.tagName.toLowerCase()).toBe("video"); - }); - - it("setWindow only sets one video in the dom object", function () { - video.setWindow(domNode); - video.setWindow(domNode); - expect(domNode.childNodes.length).toBe(1); - }); - - it("setWindow dissociates video from a set dom object", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.setWindow(null); - expect(domNode.childNodes.length).toBe(0); - }); - - // -------- open - - it("open throws invalid param when given invalid fileUrl", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - expect(function () { - video.setWindow(domNode); - video.open(false); - }).toThrow(); - }); - - it("open throws invalid param when given invalid number of arguments", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - expect(function () { - video.setWindow(domNode); - video.open(); - }).toThrow(); - }); - - it("open sets video tag src attribute", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open(A_VIDEO); - expect(videoNode.getAttribute("src")).toBe(A_VIDEO); - }); - - it("open washes file url for virtual direcories", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - s.mock(fileSystem).expects("getURI").once().withExactArgs(A_VIDEO).returns(A_VIDEO); - video.open(A_VIDEO); - }); - - // ------- invalid state checks - // TODO: this could be a lot more tight (test every state case) - - it("open warns to console when called from invalid state", function () { - s.mock(_console).expects("warn").once(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - s.mock(videoNode).expects("setAttribute").never(); - video.open(A_VIDEO); - }); - - it("play warns to console when called from invalid state", function () { - s.mock(_console).expects("warn").once(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - s.mock(videoNode).expects("play").never(); - video.play(1); - }); - - it("pause warns to console when called from invalid state", function () { - s.mock(_console).expects("warn").once(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open(A_VIDEO); - s.mock(videoNode).expects("pause").never(); - video.pause(); - }); - - it("resume warns to console when called from invalid state", function () { - s.mock(_console).expects("warn").once(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - s.mock(videoNode).expects("play").never(); - video.resume(); - }); - - it("stop warns to console when called from invalid state", function () { - s.mock(_console).expects("warn").once(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open(A_VIDEO); - s.mock(videoNode).expects("pause").never(); - video.stop(); - }); - - // -------- play - - it("play throws invalid param when given invalid number of plays (negative integer)", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - expect(function () { - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(-7); - }).toThrow(); - }); - - it("play throws invalid param when given invalid number of plays (boolean)", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - expect(function () { - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(false); - }).toThrow(); - }); - - it("play throws invalid param when given invalid number of plays (string)", function () { - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - expect(function () { - video.setWindow(domNode); - video.open(A_VIDEO); - video.play("what up dawg"); - }).toThrow(); - }); - - it("play throws invalid param when given invalid number of arguments", function () { - s.mock(document).expects("createElement").twice().withExactArgs("video").returns(videoNode); - - expect(function () { - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1, 2); - }).toThrow(); - - expect(function () { - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(); - }).toThrow(); - }); - - // -------- integration - - it("play initiates play on video tag", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - s.mock(videoNode).expects("play").once(); - video.play(1); - }); - - it("pause initiates pause on video tag", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - s.mock(videoNode).expects("pause").once(); - video.pause(); - }); - - it("resume initiates pause on video tag", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - s.mock(videoNode).expects("play").once(); - video.resume(); - }); - - it("stop initiates pause on video tag", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - s.mock(videoNode).expects("pause").once(); - video.stop(); - }); - - it("stop resets video tag src", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - s.mock(videoNode).expects("setAttribute").once().withExactArgs("src", A_VIDEO); - video.stop(); - }); - - it("open triggers state change event", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.onStateChange = s.mock().once().withExactArgs("opened"); - video.setWindow(domNode); - video.open(A_VIDEO); - }); - - it("play triggers state change event", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.onStateChange = s.mock().once().withExactArgs("playing"); - video.play(1); - }); - - it("play does not trigger state change event when give 0 number of play times", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.onStateChange = s.mock().never(); - video.play(0); - }); - - it("pause triggers state change event", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.onStateChange = s.mock().once().withExactArgs("paused"); - video.pause(); - }); - - it("resume triggers state change event", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - - video.onStateChange = s.mock().once().withExactArgs("playing"); - video.resume(); - }); - - it("stop triggers state change event", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - video.resume(); - - video.onStateChange = s.mock().once().withExactArgs("stopped"); - video.stop(); - }); - - // TODO: mock fire ended event and mock onStateChange - //it("triggers completed state change event when video ends", function () {}, - - it("object flow executes without any invalid state warnings", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - video.resume(); - video.stop(); - }); - - it("object flow is reusable", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").twice().withExactArgs("video").returns(videoNode); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - video.resume(); - video.stop(); - - video.setWindow(domNode); - video.open(A_VIDEO); - video.play(1); - video.pause(); - video.resume(); - video.stop(); - }); - - // -------- codec/container handling - - it("open should raise notification when given unsupported codecs/containers", function () { - s.mock(_console).expects("warn").atLeast(1); - videoNode.canPlayType = function () { - return ""; - }; - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.dude"); - }); - - it("open should not raise notification when given supported codecs/containers (mp4)", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.mp4"); - }); - - it("open should not raise notification when given supported codecs/containers (ogg)", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.ogg"); - }); - - it("open should not raise notification when given supported codecs/containers (ogv)", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.ogv"); - }); - - it("open should not raise notification when given supported codecs/containers (webm)", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.webm"); - }); - - it("open should not raise notification when given supported codecs/containers (flv)", function () { - s.mock(_console).expects("warn").never(); - s.mock(document).expects("createElement").once().withExactArgs("video").returns(videoNode); - video.setWindow(domNode); - video.open("video.flv"); - }); -}); diff --git a/test/unit/wac/Widget.js b/test/unit/wac/Widget.js deleted file mode 100644 index b4d4f83d..00000000 --- a/test/unit/wac/Widget.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -describe("wac_Widget", function () { - var Widget = require('ripple/platform/wac/1.0/Widget'), - Exception = require('ripple/platform/wac/1.0/Exception'), - event = require('ripple/event'), - platform = require('ripple/platform'), - db = require('ripple/db'), - sinon = require('sinon'), - s; - - beforeEach(function () { - s = sinon.sandbox.create(); - spyOn(platform, "current").andReturn({name: "generic"}); - s.stub(platform, "getPersistencePrefix").returns("default"); - spyOn(console, "log"); - }); - - afterEach(function () { - s.verifyAndRestore(); - }); - - it("Exception_can_be_thrown_properly", function () { - // TODO: look into more, so does this mean you can have race conditions where this Static Exception object is used around the same time? - var exception = Exception; - exception.message = "message"; - exception.type = "testype"; - - try { - throw exception; - } - catch (e) { - expect(e.message).toBe("message"); - expect(e.type).toBe("testype"); - } - }); - - it("setPreferenceForKey_throws_INVALID_PARAMETER_exception_when_invalid_argument_types", function () { - expect(function () { - Widget.setPreferenceForKey(new Date(), 5); - - }).toThrow(); - }); - - it("setPreferenceForKey_throws_INVALID_PARAMETER_exception_when_invalid_argument_lengths", function () { - expect(function () { - Widget.setPreferenceForKey({}, false, ""); - }).toThrow(); - - expect(function () { - Widget.setPreferenceForKey(); - }).toThrow(); - }); - - it("setPreferenceForKey calls into the db to save", function () { - s.mock(db).expects("save").once(); - Widget.setPreferenceForKey("p value", "pstring"); - }); - - it("setPreferenceForKey raises the StorageUpdatedEvent", function () { - s.stub(db, "save"); - s.mock(event).expects("trigger").withExactArgs("StorageUpdatedEvent").once(); - Widget.setPreferenceForKey("a", "b"); - }); - - it("setPreferenceForKey_adds_and_removes_key_properly", function () { - s.mock(db).expects("remove").once(); - Widget.setPreferenceForKey(null, "removes_key"); - }); - - it("setPreferenceForKey_returns_undefined_with_nonexistent_key", function () { - expect(Widget.preferenceForKey("nonexistentkey")).not.toBeDefined(); - }); - - it("preferenceForKey_throws_INVALID_PARAMETER_exception_when_invalid_argument_types", function () { - expect(function () { - Widget.preferenceForKey(5); - }).toThrow(); - }); - - it("preferenceForKey_throws_INVALID_PARAMETER_exception_when_invalid_argument_lengths", function () { - expect(function () { - Widget.preferenceForKey(false, new Date()); - }).toThrow(); - - expect(function () { - Widget.preferenceForKey(); - }).toThrow(); - }); -}); diff --git a/test/unit/widgetConfig.js b/test/unit/widgetConfig.js index d780dabb..4d0da390 100644 --- a/test/unit/widgetConfig.js +++ b/test/unit/widgetConfig.js @@ -28,154 +28,136 @@ describeBrowser("widgetConfig", function () { var widgetConfig = require('ripple/widgetConfig'), platform = require('ripple/platform'); - it("validateNumberOfArguments_Throws_Exception_If_No_Arguments", function () { - expect(function () { - widgetConfig.validate(); - }).toThrow(function (e) { - return e.type === "ArgumentLength"; + describe("phoengap config", function () { + beforeEach(function () { + spyOn(platform, "current").andReturn(require('ripple/platform/phonegap/1.0/spec')); }); - }); - - it("load_config_file", function () { - var configXML = _getConfig("config.xml"); - expect(typeof configXML === "object"); - }); - - it("config_no_namespaces_file_loads_and_we_can_parse_the_first_node", function () { - var evaluator, - configXML, - resolver, - results, - configNodes; - configXML = _getConfig("config_no_namespaces.xml"); + it("validateNumberOfArguments_Throws_Exception_If_No_Arguments", function () { + expect(function () { + widgetConfig.validate(); + }).toThrow(function (e) { + return e.type === "ArgumentLength"; + }); + }); - evaluator = new XPathEvaluator(); - resolver = evaluator.createNSResolver(configXML); - configNodes = evaluator.evaluate("//*[name()='widget']", configXML, - null, XPathResult.ANY_TYPE, null); + it("load_config_file", function () { + var configXML = _getConfig("config.xml"); + expect(typeof configXML === "object"); + }); - results = configNodes.iterateNext(); + it("config_no_namespaces_file_loads_and_we_can_parse_the_first_node", function () { + var evaluator, + configXML, + resolver, + results, + configNodes; - expect(typeof configNodes === "object"); - }); + configXML = _getConfig("config_no_namespaces.xml"); - it("config_file_loads_and_we_can_parse_a_namespaced_node", function () { - var configXML, - evaluator, - resolver, - configNodes; + evaluator = new XPathEvaluator(); + resolver = evaluator.createNSResolver(configXML); + configNodes = evaluator.evaluate("//*[name()='widget']", configXML, + null, XPathResult.ANY_TYPE, null); - configXML = _getConfig("config.xml"); + results = configNodes.iterateNext(); - evaluator = new XPathEvaluator(); - resolver = evaluator.createNSResolver(configXML); - configNodes = configXML.evaluate("//*[name()='JIL:billing']", configXML, - resolver, XPathResult.ANY_TYPE, null); + expect(typeof configNodes === "object"); + }); - expect(typeof configNodes).toEqual("object"); - }); + it("config_file_loads_and_we_can_parse_a_namespaced_node", function () { + var configXML, + evaluator, + resolver, + configNodes; - it("config_file_validation_returns_true_for_a_valid_config_file", function () { - var configXML; + configXML = _getConfig("config.xml"); - configXML = _getConfig("config.xml"); - expect(widgetConfig.validate(configXML).widget.validationResult[0].valid).toEqual(true); - }); + evaluator = new XPathEvaluator(); + resolver = evaluator.createNSResolver(configXML); + configNodes = configXML.evaluate("//*[name()='JIL:billing']", configXML, + resolver, XPathResult.ANY_TYPE, null); - it("config_file_validation_returns_returns_proper_nodes_as_being_validated", function () { - var configXML, - result; - - configXML = _getConfig("config.xml"); - - result = widgetConfig.validate(configXML).widget; - - expect(result.validationResult[0].valid).toEqual(true); - expect(result.children["preference"].validationResult[0].valid).toEqual(true); - expect(result.children["name"].validationResult[0].valid).toEqual(true); - expect(result.children["description"].validationResult[0].valid).toEqual(true); - expect(result.children["icon"].validationResult[0].valid).toEqual(true); - expect(result.children["author"].validationResult[0].valid).toEqual(true); - expect(result.children["content"].validationResult[0].valid).toEqual(true); - expect(result.children["feature"].validationResult[0].valid).toEqual(true); - expect(result.children["JIL:maximum_display_mode"].validationResult[0].valid).toEqual(true); - expect(result.children["JIL:update"].validationResult[0].valid).toEqual(true); - expect(result.children["JIL:access"].validationResult[0].valid).toEqual(true); - expect(result.children["JIL:billing"].validationResult[0].valid).toEqual(true); - }); + expect(typeof configNodes).toEqual("object"); + }); - it("config_file_validation_validates_for_required_widget_and_icon_nodes", function () { - var configXML, - result; + it("config_file_validation_returns_true_for_a_valid_config_file", function () { + var configXML = _getConfig("config.xml"); + expect(widgetConfig.validate(configXML).widget.validationResult[0].valid).toEqual(true); + }); - configXML = _getConfig("config_no_widet_node.xml"); + it("config_file_validation_returns_returns_proper_nodes_as_being_validated", function () { + var configXML, + result; - result = widgetConfig.validate(configXML).widget; + configXML = _getConfig("config.xml"); - expect(result).toBeTruthy(); - expect(result.validationResult[0].message).toEqual("widget node expected, but not found"); - }); + result = widgetConfig.validate(configXML).widget; - it("config_file_validation_validates_that_only_one_name_node_can_exist", function () { - var configXML, - result; + expect(result.validationResult[0].valid).toEqual(true); + expect(result.children["name"].validationResult[0].valid).toEqual(true); + expect(result.children["description"].validationResult[0].valid).toEqual(true); + expect(result.children["icon"].validationResult[0].valid).toEqual(true); + expect(result.children["author"].validationResult[0].valid).toEqual(true); + expect(result.children["feature"].validationResult[0].valid).toEqual(true); + }); - configXML = _getConfig("config_multiple_name_nodes.xml"); + it("config_file_validation_validates_for_required_widget_and_icon_nodes", function () { + var configXML, + result; - result = widgetConfig.validate(configXML).widget; + configXML = _getConfig("config_no_widet_node.xml"); - expect(result.children.name.validationResult[1].attributes["xml:lang"].message) - .toEqual("name.xml:lang node is allowed to appear multiple times, however it must be unique based on " + - "this attribute and in this case another node with an identical attribute vale was found"); - }); + result = widgetConfig.validate(configXML).widget; - it("config_file_validation_validates_that_multiple_unique_name_node_can_exist", function () { - var configXML, - result; + expect(result).toBeTruthy(); + expect(result.validationResult[0].message).toEqual("widget node expected, but not found"); + }); - configXML = _getConfig("config_multiple_name_nodes_unique.xml"); - result = widgetConfig.validate(configXML).widget; - expect(result.children.name.validationResult[0].valid).toEqual(true); - }); + it("config_file_validation_validates_that_only_one_name_node_can_exist", function () { + var configXML = _getConfig("config_multiple_name_nodes.xml"), + result = widgetConfig.validate(configXML).widget; - it("config_file_validation_fails_for_bad_attributes", function () { - var configXML, - result; + expect(result.children.name.validationResult[1].attributes["xml:lang"].message) + .toEqual("name.xml:lang node is allowed to appear multiple times, however it must be unique based on " + + "this attribute and in this case another node with an identical attribute vale was found"); + }); - configXML = _getConfig("config_with_missing_attributes.xml"); + it("config_file_validation_validates_that_multiple_unique_name_node_can_exist", function () { + var configXML = _getConfig("config_multiple_name_nodes_unique.xml"), + result = widgetConfig.validate(configXML).widget; - result = widgetConfig.validate(configXML).widget; + expect(result.children.name.validationResult[0].valid).toEqual(true); + }); - expect(result.validationResult[0].attributes.id.message).toEqual("widget.id attribute was expected but not found"); - expect(result.validationResult[0].attributes.version.message).toEqual("widget.version attribute was expected but not found"); - expect(result.validationResult[0].attributes.height.message).toEqual("widget.height attribute was expected but not found"); - expect(result.validationResult[0].attributes.width.message).toEqual("widget.width attribute was expected but not found"); - expect(result.children.icon.validationResult[0].attributes.src.message).toEqual("icon.src attribute was expected but not found"); - }); + it("config_file_validation_fails_for_bad_attributes", function () { + var configXML = _getConfig("config_with_missing_attributes.xml"), + result = widgetConfig.validate(configXML).widget; - it("config_file_validation_catches_bad_urls_and_emails_in_attributes", function () { - var configXML, - result; + expect(result.children.icon.validationResult[0].attributes.src.message).toEqual("icon.src attribute was expected but not found"); + }); - configXML = _getConfig("config_with_bad_url_email_attributes.xml"); - result = widgetConfig.validate(configXML).widget; + it("config_file_validation_catches_bad_urls_and_emails_in_attributes", function () { + var configXML = _getConfig("config_with_bad_url_email_attributes.xml"), + result = widgetConfig.validate(configXML).widget; - expect("author.email value does not match expected format. Value should pass this regular expression validation: " + (/^([^@\s]+)@((?:[\-a-z0-9]+\.)+[a-z]{2,})$/)) - .toEqual(result.children.author.validationResult[0].attributes.email.message); - expect("JIL:update.href value does not match expected format. Value should pass this regular expression validation: " + - (/^((https?|ftp|gopher|telnet|file|notes|ms-help):((\/\/)|(\\\\))+[\w\d:#@%\/;$()~_?\+-=\\\.&]*)$/)) - .toEqual(result.children["JIL:update"].validationResult[0].attributes.href.message); + expect(result.children.author.validationResult[0].attributes.email.message) + .toEqual("author.email value does not match expected format. Value should pass this regular expression validation: " + + (/^([^@\s]+)@((?:[\-a-z0-9]+\.)+[a-z]{2,})$/)); + }); }); - it("can handle duplicate nodes at different levels", function () { - var configXML, - widget; + describe("webworks config", function () { + beforeEach(function () { + spyOn(platform, "current").andReturn(require('ripple/platform/webworks.handset/2.0.0/spec')); + }); + + it("can handle duplicate nodes at different levels", function () { + var configXML = _getConfig("config_multiple_nested_features.xml"), + widget = widgetConfig.validate(configXML).widget; - spyOn(platform, "current").andReturn(require('ripple/platform/webworks.handset/2.0.0/spec')); - configXML = _getConfig("config_multiple_nested_features.xml"); - widget = widgetConfig.validate(configXML).widget; - expect(widget.children.feature.validationResult.length).toBe(1); - expect(widget.children.access.children.feature.validationResult.length).toBe(2); + expect(widget.children.feature.validationResult.length).toBe(1); + expect(widget.children.access.children.feature.validationResult.length).toBe(2); + }); }); }); diff --git a/test/unit/xhr.js b/test/unit/xhr.js index e625cef0..42761207 100644 --- a/test/unit/xhr.js +++ b/test/unit/xhr.js @@ -105,7 +105,6 @@ describe("xhr", function () { }); // TODO: add tests (cors) - // open (ex fileSystem.getURI) // test defaulting to base on local request describe("xhr/cors", function () { it("exports a mappable xhr object", function () { From 2b1f03ca2d08cdadf71872f838d6676d15dfa0da Mon Sep 17 00:00:00 2001 From: brent lintner Date: Thu, 25 Aug 2011 14:15:10 -0400 Subject: [PATCH 002/182] Progress on filesystem api. touch, mkdir and ls commands all work. --- .jshintrc | 1 + ext/chromium/manifest.json | 2 +- lib/ripple.js | 2 + lib/ripple/fileSystem.js | 95 ++++++++++++++++++++++ test/unit/fileSystem.js | 161 +++++++++++++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 lib/ripple/fileSystem.js create mode 100644 test/unit/fileSystem.js diff --git a/.jshintrc b/.jshintrc index b7ed2501..3a0affdc 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,6 +1,7 @@ { "predef": [ "webkitNotifications", + "FileError", "DOMDocument", "$", "it", "describe", "xit", "xdescribe", diff --git a/ext/chromium/manifest.json b/ext/chromium/manifest.json index 5ad04f54..b3c94d96 100644 --- a/ext/chromium/manifest.json +++ b/ext/chromium/manifest.json @@ -17,7 +17,7 @@ "js": ["controllers/Insertion.js"], "matches": ["http://*/*","https://*/*","file:///*"] }], - "permissions": ["tabs", "unlimited_storage", "notifications", "contextMenus", "http://*/*", "https://*/*"], + "permissions": ["tabs", "unlimitedStorage", "notifications", "contextMenus", "http://*/*", "https://*/*"], "description": "A browser based html5 mobile application development and testing tool", "file_name": "manifest.json", "update_page": "update.html", diff --git a/lib/ripple.js b/lib/ripple.js index 147f8a2b..cbcd0df5 100644 --- a/lib/ripple.js +++ b/lib/ripple.js @@ -18,6 +18,7 @@ var omgwtf = require('ripple/omgwtf'), xhr = require('ripple/xhr'), accelerometer = require('ripple/accelerometer'), geo = require('ripple/geo'), + fs = require('ripple/fileSystem'), platform = require('ripple/platform'), builder = require('ripple/platform/builder'), devices = require('ripple/devices'), @@ -31,6 +32,7 @@ var omgwtf = require('ripple/omgwtf'), .andThen(xhr.initialize, xhr) .andThen(accelerometer.initialize, accelerometer) .andThen(geo.initialize, geo) + .andThen(fs.initialize, fs) .andThen(devices.initialize, devices) .andThen(platform.initialize, platform) .andThen(widgetConfig.initialize, widgetConfig) diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js new file mode 100644 index 00000000..c5e7190c --- /dev/null +++ b/lib/ripple/fileSystem.js @@ -0,0 +1,95 @@ +var _self, _fs; + +// stupid arrays that are not arrays... +function _map(array, callback) { + var map = [], + i; + + for (i = 0; i < array.length; i++) { + map[i] = callback(array[i], i); + } + + return map; +} + +function _errorHandler(e) { + var msg = ''; + + switch (e.code) { + case FileError.QUOTA_EXCEEDED_ERR: + msg = 'QUOTA_EXCEEDED_ERR'; + break; + case FileError.NOT_FOUND_ERR: + msg = 'NOT_FOUND_ERR'; + break; + case FileError.SECURITY_ERR: + msg = 'SECURITY_ERR'; + break; + case FileError.INVALID_MODIFICATION_ERR: + msg = 'INVALID_MODIFICATION_ERR'; + break; + case FileError.INVALID_STATE_ERR: + msg = 'INVALID_STATE_ERR'; + break; + default: + msg = 'Unknown Error'; + break; + } + + console.log('FileSystem initialization error: ' + msg); +} + +_self = { + initialize: function () { + var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; + + requestFileSystem(window.TEMPORARY, 10 * 1024 * 1024, function (fs) { + _fs = fs; + }, _errorHandler); + }, + + ls: function (path, success, error) { + path = path || "/"; + + _fs.root.getDirectory(path, {}, function (dirEntry) { + var dirReader = dirEntry.createReader(); + dirReader.readEntries(function (entries) { + success(_map(entries, function (entry, index) { + return { + name: entry.name, + isDirectory: entry.isDirectory + }; + })); + }, error); + }, error); + }, + + rm: function (path, success, error) { + }, + + rmdir: function (path, success, error) { + }, + + mkdir: function (path, success, error) { + _fs.root.getDirectory(path, {create: true}, function (dirEntry) { + success(dirEntry); + }, error); + }, + + mv: function (from, to, success, error) { + }, + + touch: function (path, success, error) { + _fs.root.getFile(path, {create: true}, function (fileEntry) { + success(fileEntry); + }, error); + }, + + cp: function (from, to, success, error) { + }, + + stat: function (path, success, error) { + } +}; + +module.exports = _self; diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js new file mode 100644 index 00000000..3f56e177 --- /dev/null +++ b/test/unit/fileSystem.js @@ -0,0 +1,161 @@ +var fileSystem = require('ripple/fileSystem'); + +describe("fileSystem", function () { + var _resultEntries, + _dirEntry, + _fs; + + beforeEach(function () { + _dirEntry = { + createReader: function () { + return { + readEntries: function (success, error) { + success(_resultEntries); + } + }; + } + }; + + _fs = { + root: { + getDirectory: function (path, options, callback) { + callback(_dirEntry); + } + } + }; + + window.TEMPORARY = 0; + window.PERSISTENT = 1; + window.webkitRequestFileSystem = window.requestFileSystem = function (persistenceMethod, fsSize, success, failure) { + success(_fs); + }; + + fileSystem.initialize(); + }); + + afterEach(function () { + delete window.TEMPORARY; + delete window.PERSISTENT; + delete window.requestFileSystem; + delete window.webkitRequestFileSystem; + }); + + describe("initialize", function () { + it("uses requestFileSystem", function () { + spyOn(window, "requestFileSystem"); + fileSystem.initialize(); + + expect(window.requestFileSystem.argsForCall[0][0]).toEqual(window.TEMPORARY); + expect(window.requestFileSystem.argsForCall[0][1]).toEqual(10 * 1024 * 1024); + }); + + it("uses webkitRequestFileSystem when requestFileSystem is not present", function () { + delete window.requestFileSystem; + spyOn(window, "webkitRequestFileSystem"); + fileSystem.initialize(); + + expect(window.webkitRequestFileSystem.argsForCall[0][0]).toEqual(window.TEMPORARY); + expect(window.webkitRequestFileSystem.argsForCall[0][1]).toEqual(10 * 1024 * 1024); + }); + }); + + describe("mkdir", function () { + it("creates a directory off of root", function () { + var error = jasmine.createSpy(), + success = jasmine.createSpy(); + + _fs.root.getDirectory = function (path, options, callback) { + callback(_resultEntries[0]); + }; + + spyOn(_fs.root, "getDirectory").andCallThrough(); + + _resultEntries = [ + {name: "whatev", isDirectory: true} + ]; + + fileSystem.mkdir("whatev", success, error); + + expect(_fs.root.getDirectory.argsForCall[0][0]).toEqual("whatev"); + expect(_fs.root.getDirectory.argsForCall[0][1]).toEqual({create: true}); + expect(typeof _fs.root.getDirectory.argsForCall[0][2]).toEqual("function"); + expect(_fs.root.getDirectory.argsForCall[0][3]).toEqual(error); + expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(error).not.toHaveBeenCalled(); + }); + }); + + describe("touch", function () { + it("creates a file off of root", function () { + var error = jasmine.createSpy(), + success = jasmine.createSpy(); + + _fs.root.getFile = function (path, options, callback) { + callback(_resultEntries[0]); + }; + + spyOn(_fs.root, "getFile").andCallThrough(); + + _resultEntries = [ + {name: "er", isDirectory: false} + ]; + + fileSystem.touch("er", success, error); + + expect(_fs.root.getFile.argsForCall[0][0]).toEqual("er"); + expect(_fs.root.getFile.argsForCall[0][1]).toEqual({create: true}); + expect(typeof _fs.root.getFile.argsForCall[0][2]).toEqual("function"); + expect(_fs.root.getFile.argsForCall[0][3]).toEqual(error); + expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(error).not.toHaveBeenCalled(); + }); + }); + + describe("ls", function () { + it("defaults to '/' for a null path", function () { + _fs.root.getDirectory = jasmine.createSpy(); + fileSystem.ls(null); + expect(_fs.root.getDirectory.argsForCall[0][0]).toEqual("/"); + }); + + it("returns a list of items in the root", function () { + var error = jasmine.createSpy(); + + _resultEntries = [ + {name: "dude", isDirectory: true}, + {name: "sweet.js", isDirectory: false} + ]; + + fileSystem.ls("/", function (entries) { + expect(entries[0]).toEqual(_resultEntries[0]); + expect(entries[1]).toEqual(_resultEntries[1]); + }, error); + + expect(error).not.toHaveBeenCalled(); + }); + + it("calls error callback when path does not exist", function () { + var success = jasmine.createSpy(), + FileError = { + code: 5, + ENCODING_ERR: 5 + }; + + _dirEntry.createReader = function () { + return { + readEntries: function (success, error) { + error(FileError); + } + }; + }; + + fileSystem.ls("/foo", success, function (error) { + expect(error).toEqual(FileError); + }); + + expect(success).not.toHaveBeenCalled(); + }); + + // it does not return empty array when found values + }); +}); From 160bb37fc7713cfc652561886109625d460da68f Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Fri, 26 Aug 2011 16:53:05 -0400 Subject: [PATCH 003/182] Added more functions to filesystem api. rm, rmdir, stat, mv (wip) --- lib/ripple/fileSystem.js | 43 +++++++++++-- test/unit/fileSystem.js | 128 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 11 deletions(-) diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js index c5e7190c..82792f67 100644 --- a/lib/ripple/fileSystem.js +++ b/lib/ripple/fileSystem.js @@ -1,4 +1,5 @@ -var _self, _fs; +var utils = require('ripple/utils'), + _self, _fs; // stupid arrays that are not arrays... function _map(array, callback) { @@ -12,6 +13,10 @@ function _map(array, callback) { return map; } +function _resolveLocalFileSystemURL(path, success, error) { + return (window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL)(path, success, error); +} + function _errorHandler(e) { var msg = ''; @@ -42,7 +47,7 @@ function _errorHandler(e) { _self = { initialize: function () { var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; - + requestFileSystem(window.TEMPORARY, 10 * 1024 * 1024, function (fs) { _fs = fs; }, _errorHandler); @@ -64,10 +69,18 @@ _self = { }, error); }, - rm: function (path, success, error) { + rm: function (path, success, error, options) { + options = options || {}; + + _fs.root[options.recursive ? "getDirectory" : "getFile"](path, {create: false}, function (entry) { + entry[options.recursive ? "removeRecursively" : "remove"](function () { + success(entry); + }, error); + }, error); }, rmdir: function (path, success, error) { + _self.rm(path, success, error, {recursive: false}); }, mkdir: function (path, success, error) { @@ -77,11 +90,23 @@ _self = { }, mv: function (from, to, success, error) { + var path = to.split("/"), + fileName = path[path.length - 1]; + + path.splice(path.length, 1); + + _self.stat(from, function (entry) { + _self.stat(path, {}, function (dest) { + entry.moveTo(dest, fileName, function (finalDestination) { + success(finalDestination); + }, error); + }, error); + }, error); }, touch: function (path, success, error) { _fs.root.getFile(path, {create: true}, function (fileEntry) { - success(fileEntry); + success(fileEntry); }, error); }, @@ -89,6 +114,16 @@ _self = { }, stat: function (path, success, error) { + var url = "filesystem:" + utils.location().origin + "/temporary/" + path; + _resolveLocalFileSystemURL(url, function (entry) { + success(entry); + }, error); + }, + + write: function (path, contents, success, error, options) { + }, + + read: function (path, success, error) { } }; diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js index 3f56e177..1988d057 100644 --- a/test/unit/fileSystem.js +++ b/test/unit/fileSystem.js @@ -1,4 +1,5 @@ -var fileSystem = require('ripple/fileSystem'); +var fileSystem = require('ripple/fileSystem'), + utils = require('ripple/utils'); describe("fileSystem", function () { var _resultEntries, @@ -18,8 +19,8 @@ describe("fileSystem", function () { _fs = { root: { - getDirectory: function (path, options, callback) { - callback(_dirEntry); + getDirectory: function (path, options, success, error) { + success(_dirEntry); } } }; @@ -30,6 +31,9 @@ describe("fileSystem", function () { success(_fs); }; + window.webkitResolveLocalFileSystemURL = window.resolveLocalFileSystemURL = function (url, success, failure) { + }; + fileSystem.initialize(); }); @@ -64,8 +68,8 @@ describe("fileSystem", function () { var error = jasmine.createSpy(), success = jasmine.createSpy(); - _fs.root.getDirectory = function (path, options, callback) { - callback(_resultEntries[0]); + _fs.root.getDirectory = function (path, options, success, error) { + success(_resultEntries[0]); }; spyOn(_fs.root, "getDirectory").andCallThrough(); @@ -90,8 +94,8 @@ describe("fileSystem", function () { var error = jasmine.createSpy(), success = jasmine.createSpy(); - _fs.root.getFile = function (path, options, callback) { - callback(_resultEntries[0]); + _fs.root.getFile = function (path, options, success, error) { + success(_resultEntries[0]); }; spyOn(_fs.root, "getFile").andCallThrough(); @@ -158,4 +162,114 @@ describe("fileSystem", function () { // it does not return empty array when found values }); + + describe("rm", function () { + it("removes la file from the root", function () { + var error = jasmine.createSpy(), + remove = jasmine.createSpy().andCallFake(function (callback) { + callback(); + }), + success = jasmine.createSpy(); + + _fs.root.getFile = function (path, options, success, error) { + success(_resultEntries[0]); + }; + + spyOn(_fs.root, "getFile").andCallThrough(); + + _resultEntries = [ + {name: "/foo", isDirectory: false, remove: remove} + ]; + + fileSystem.rm("/foo", success, error); + + expect(_fs.root.getFile.argsForCall[0][0]).toEqual("/foo"); + expect(_fs.root.getFile.argsForCall[0][1]).toEqual({create: false}); + expect(typeof _fs.root.getFile.argsForCall[0][2]).toEqual("function"); + expect(_fs.root.getFile.argsForCall[0][3]).toEqual(error); + expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(typeof remove.argsForCall[0][0]).toEqual("function"); + expect(remove.argsForCall[0][1]).toEqual(error); + expect(error).not.toHaveBeenCalled(); + }); + + it("removes a directory recursively", function () { + var error = jasmine.createSpy(), + removeRecursively = jasmine.createSpy().andCallFake(function (callback) { + callback(); + }), + success = jasmine.createSpy(); + + _fs.root.getDirectory = function (path, options, success, error) { + success(_resultEntries[0]); + }; + + spyOn(_fs.root, "getDirectory").andCallThrough(); + + _resultEntries = [ + {name: "/foo", isDirectory: true, removeRecursively: removeRecursively} + ]; + + fileSystem.rm("/foo", success, error, {recursive: true}); + + expect(_fs.root.getDirectory.argsForCall[0][0]).toEqual("/foo"); + expect(_fs.root.getDirectory.argsForCall[0][1]).toEqual({create: false}); + expect(typeof _fs.root.getDirectory.argsForCall[0][2]).toEqual("function"); + expect(_fs.root.getDirectory.argsForCall[0][3]).toEqual(error); + expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(typeof removeRecursively.argsForCall[0][0]).toEqual("function"); + expect(removeRecursively.argsForCall[0][1]).toEqual(error); + expect(error).not.toHaveBeenCalled(); + }); + }); + + describe("rmdir", function () { + it("removes a directory", function () { + var error = jasmine.createSpy(), + success = jasmine.createSpy(); + + spyOn(fileSystem, "rm"); + fileSystem.rmdir("/foo", success, error); + expect(fileSystem.rm).toHaveBeenCalledWith("/foo", success, error, {recursive: false}); + }); + }); + + describe("stat", function () { + it("retrieves the status of a file", function () { + var entry = { + name: "/bob", + isDirectory: false + }, + domain = "http://dude.com", + error = jasmine.createSpy(), + success = jasmine.createSpy(); + + spyOn(window, "resolveLocalFileSystemURL").andCallFake(function (url, success, error) { + success(entry); + }); + + spyOn(utils, "location").andReturn({origin: domain}); + + fileSystem.stat("/bob", success, error); + + expect(window.resolveLocalFileSystemURL.argsForCall[0][0]) + .toEqual("filesystem:" + domain + "/temporary//bob"); + expect(typeof window.resolveLocalFileSystemURL.argsForCall[0][1]).toEqual("function"); + expect(window.resolveLocalFileSystemURL.argsForCall[0][2]).toEqual(error); + expect(success).toHaveBeenCalledWith(entry); + }); + }); + + xdescribe("mv", function () { + it("can move a file from one location to another", function () { + var entry = { + name: "sherman", + isDirectory: true + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + success(entry); + }); + }); + }); }); From e9e25c2517b6ac604ed900decb136c9be12c9ac6 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Mon, 29 Aug 2011 18:54:16 -0400 Subject: [PATCH 004/182] hastily finished write apis --- lib/ripple/fileSystem.js | 46 ++++++++-- test/unit/fileSystem.js | 178 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 205 insertions(+), 19 deletions(-) diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js index 82792f67..6179f14d 100644 --- a/lib/ripple/fileSystem.js +++ b/lib/ripple/fileSystem.js @@ -17,7 +17,12 @@ function _resolveLocalFileSystemURL(path, success, error) { return (window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL)(path, success, error); } -function _errorHandler(e) { +function _blobBuilder() { + var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; + return new BlobBuilder(); +} + +function _error(e) { var msg = ''; switch (e.code) { @@ -41,7 +46,7 @@ function _errorHandler(e) { break; } - console.log('FileSystem initialization error: ' + msg); + console.log('FileSystem error: ' + msg); } _self = { @@ -50,7 +55,7 @@ _self = { requestFileSystem(window.TEMPORARY, 10 * 1024 * 1024, function (fs) { _fs = fs; - }, _errorHandler); + }, _error); }, ls: function (path, success, error) { @@ -90,13 +95,11 @@ _self = { }, mv: function (from, to, success, error) { - var path = to.split("/"), - fileName = path[path.length - 1]; - - path.splice(path.length, 1); + var path = to.replace(/^\//, "").split("/"), + fileName = path.splice(path.length - 1, 1).toString(); _self.stat(from, function (entry) { - _self.stat(path, {}, function (dest) { + _self.stat(path.length > 0 ? path.join("/") : "/", function (dest) { entry.moveTo(dest, fileName, function (finalDestination) { success(finalDestination); }, error); @@ -111,6 +114,16 @@ _self = { }, cp: function (from, to, success, error) { + var path = to.replace(/^\//, "").split("/"), + fileName = path.splice(path.length - 1, 1).toString(); + + _self.stat(from, function (entry) { + _self.stat(path.length > 0 ? path.join("/") : "/", function (dest) { + entry.copyTo(dest, fileName, function (finalDestination) { + success(finalDestination); + }, error); + }, error); + }, error); }, stat: function (path, success, error) { @@ -121,6 +134,23 @@ _self = { }, write: function (path, contents, success, error, options) { + options = options || {}; + + _self.stat(path, function (entry) { + entry.createWriter(function (fileWriter) { + var bb = _blobBuilder(); + + fileWriter.onwriteend = success; + fileWriter.onerror = error; + + if (options.mode === "append") { + fileWriter.seek(fileWriter.length); + } + + bb.append(contents); + fileWriter.write(bb.getBlob('text/plain')); + }, error); + }, error); }, read: function (path, success, error) { diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js index 1988d057..05c2ab73 100644 --- a/test/unit/fileSystem.js +++ b/test/unit/fileSystem.js @@ -34,6 +34,8 @@ describe("fileSystem", function () { window.webkitResolveLocalFileSystemURL = window.resolveLocalFileSystemURL = function (url, success, failure) { }; + window.WebKitBlobBuilder = window.BlobBuilder = function () {}; + fileSystem.initialize(); }); @@ -42,6 +44,10 @@ describe("fileSystem", function () { delete window.PERSISTENT; delete window.requestFileSystem; delete window.webkitRequestFileSystem; + delete window.resolveLocalFileSystemURL; + delete window.webkitResolveLocalFileSystemURL; + delete window.WebKitBlobBuilder; + delete window.BlobBuilder; }); describe("initialize", function () { @@ -75,7 +81,7 @@ describe("fileSystem", function () { spyOn(_fs.root, "getDirectory").andCallThrough(); _resultEntries = [ - {name: "whatev", isDirectory: true} + {fullPath: "whatev", isDirectory: true} ]; fileSystem.mkdir("whatev", success, error); @@ -101,7 +107,7 @@ describe("fileSystem", function () { spyOn(_fs.root, "getFile").andCallThrough(); _resultEntries = [ - {name: "er", isDirectory: false} + {fullPath: "er", isDirectory: false} ]; fileSystem.touch("er", success, error); @@ -178,7 +184,7 @@ describe("fileSystem", function () { spyOn(_fs.root, "getFile").andCallThrough(); _resultEntries = [ - {name: "/foo", isDirectory: false, remove: remove} + {fullPath: "/foo", isDirectory: false, remove: remove} ]; fileSystem.rm("/foo", success, error); @@ -207,7 +213,7 @@ describe("fileSystem", function () { spyOn(_fs.root, "getDirectory").andCallThrough(); _resultEntries = [ - {name: "/foo", isDirectory: true, removeRecursively: removeRecursively} + {fullPath: "/foo", isDirectory: true, removeRecursively: removeRecursively} ]; fileSystem.rm("/foo", success, error, {recursive: true}); @@ -237,7 +243,7 @@ describe("fileSystem", function () { describe("stat", function () { it("retrieves the status of a file", function () { var entry = { - name: "/bob", + fullPath: "/bob", isDirectory: false }, domain = "http://dude.com", @@ -260,16 +266,166 @@ describe("fileSystem", function () { }); }); - xdescribe("mv", function () { + describe("mv", function () { it("can move a file from one location to another", function () { - var entry = { - name: "sherman", - isDirectory: true - }; + var movedEntry = { + fullPath: "/bar", + isDirectory: false + }, + fromEntry = { + fullPath: "/foo", + isDirectory: false, + moveTo: jasmine.createSpy().andCallFake(function (dest, fileName, callback) { + callback(movedEntry); + }) + }, + rootEntry = { + fullPath: "/", + isDirectory: true + }, + error = jasmine.createSpy(), + success = jasmine.createSpy(), + from = "/foo", + to = "/bar"; spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { - success(entry); + success(path.match(/^\/$/) ? rootEntry : fromEntry); }); + + fileSystem.mv(from, to, success, error); + + expect(fromEntry.moveTo.argsForCall[0][0]).toEqual(rootEntry); + expect(fromEntry.moveTo.argsForCall[0][1]).toEqual("bar"); + expect(fromEntry.moveTo.argsForCall[0][3]).toEqual(error); + expect(fileSystem.stat.argsForCall[0][2]).toEqual(error); + expect(fileSystem.stat.argsForCall[1][2]).toEqual(error); + expect(success).toHaveBeenCalledWith(movedEntry); }); }); + + describe("cp", function () { + it("can copy a file from one location to another", function () { + var copiedEntry = { + fullPath: "/bar", + isDirectory: false + }, + fromEntry = { + fullPath: "/foo", + isDirectory: false, + copyTo: jasmine.createSpy().andCallFake(function (dest, fileName, callback) { + callback(copiedEntry); + }) + }, + rootEntry = { + fullPath: "/", + isDirectory: true + }, + error = jasmine.createSpy(), + success = jasmine.createSpy(), + from = "/foo", + to = "/bar"; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + success(path.match(/^\/$/) ? rootEntry : fromEntry); + }); + + fileSystem.cp(from, to, success, error); + + expect(fromEntry.copyTo.argsForCall[0][0]).toEqual(rootEntry); + expect(fromEntry.copyTo.argsForCall[0][1]).toEqual("bar"); + expect(fromEntry.copyTo.argsForCall[0][3]).toEqual(error); + expect(fileSystem.stat.argsForCall[0][2]).toEqual(error); + expect(fileSystem.stat.argsForCall[1][2]).toEqual(error); + expect(success).toHaveBeenCalledWith(copiedEntry); + }); + }); + + describe("write", function () { + it("overwrites an existing file by default", function () { + var path = "some/path", + contents = "file data", + error = jasmine.createSpy(), + success = jasmine.createSpy(), + fileWriterInstance = { + onwriteend: null, + onerror: null, + write: jasmine.createSpy() + }, + fileEntry = { + fullPath: "some/path", + isDirectory: false, + createWriter: jasmine.createSpy().andCallFake(function (callback) { + callback(fileWriterInstance); + }) + }, + txt = "plain text blob", + blobInstance = { + append: jasmine.createSpy(), + getBlob: jasmine.createSpy().andReturn(txt) + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + success(fileEntry); + }); + + spyOn(window, "BlobBuilder").andReturn(blobInstance); + + fileSystem.write(path, contents, success, error); + + expect(fileWriterInstance.onwriteend).toBe(success); + expect(fileWriterInstance.onerror).toBe(error); + expect(fileEntry.createWriter.callCount).toBe(1); + expect(fileEntry.createWriter.argsForCall[0][1]).toBe(error); + expect(blobInstance.append).toHaveBeenCalledWith(contents); + expect(fileWriterInstance.write).toHaveBeenCalledWith(txt); + expect(fileSystem.stat.argsForCall[0][2]).toBe(error); + }); + + describe("when options.append", function () { + it("appends to an existing file", function () { + var path = "some/path", + contents = "file data", + error = jasmine.createSpy(), + success = jasmine.createSpy(), + options = { + mode: "append" + }, + fileWriterInstance = { + onwriteend: null, + onerror: null, + length: 5, + write: jasmine.createSpy(), + seek: jasmine.createSpy() + }, + fileEntry = { + fullPath: "some/path", + isDirectory: false, + createWriter: jasmine.createSpy().andCallFake(function (callback) { + callback(fileWriterInstance); + }) + }, + txt = "plain text blob", + blobInstance = { + append: jasmine.createSpy(), + getBlob: jasmine.createSpy().andReturn(txt) + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + success(fileEntry); + }); + + spyOn(window, "BlobBuilder").andReturn(blobInstance); + + fileSystem.write(path, contents, success, error, options); + + expect(fileWriterInstance.seek).toHaveBeenCalledWith(fileWriterInstance.length); + }); + }); + + // TODO: it creates the file if it does not exist + // TODO: it appends onto a file with options.mode === "append" + }); + + // TODO: fileWriter.onwriteend may get called even if there is an error? (see FileWriter spec) + // TODO: make consistent the objects that get returned (i.e. {name, isDirectory} instead of full Directory/FileEntry objects) }); From 947c27a186c1bd5c9e646f4eb428b9cfd4e6c0e8 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 30 Aug 2011 15:10:12 -0400 Subject: [PATCH 005/182] added read/write to fileSystem, removed FileReader, FileWriter and file from PhoneGap spec --- .jshintrc | 1 + lib/ripple/fileSystem.js | 71 ++++++-- .../platform/phonegap/1.0/FileReader.js | 34 ---- .../platform/phonegap/1.0/FileWriter.js | 34 ---- lib/ripple/platform/phonegap/1.0/file.js | 23 --- lib/ripple/platform/phonegap/1.0/spec.js | 9 - test/unit/fileSystem.js | 161 ++++++++++++++++-- 7 files changed, 200 insertions(+), 133 deletions(-) delete mode 100644 lib/ripple/platform/phonegap/1.0/FileReader.js delete mode 100644 lib/ripple/platform/phonegap/1.0/FileWriter.js delete mode 100644 lib/ripple/platform/phonegap/1.0/file.js diff --git a/.jshintrc b/.jshintrc index 3a0affdc..961ed4d0 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,5 +1,6 @@ { "predef": [ + "FileReader", "FileWriter", "webkitNotifications", "FileError", "DOMDocument", diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js index 6179f14d..020ec6a8 100644 --- a/lib/ripple/fileSystem.js +++ b/lib/ripple/fileSystem.js @@ -1,15 +1,27 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ var utils = require('ripple/utils'), + _console = require('ripple/console'), _self, _fs; -// stupid arrays that are not arrays... function _map(array, callback) { - var map = [], - i; - + var map = [], i; for (i = 0; i < array.length; i++) { map[i] = callback(array[i], i); } - return map; } @@ -46,13 +58,13 @@ function _error(e) { break; } - console.log('FileSystem error: ' + msg); + _console.log('FileSystem error: ' + msg); } _self = { initialize: function () { var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; - + requestFileSystem(window.TEMPORARY, 10 * 1024 * 1024, function (fs) { _fs = fs; }, _error); @@ -65,10 +77,7 @@ _self = { var dirReader = dirEntry.createReader(); dirReader.readEntries(function (entries) { success(_map(entries, function (entry, index) { - return { - name: entry.name, - isDirectory: entry.isDirectory - }; + return entry; })); }, error); }, error); @@ -79,7 +88,7 @@ _self = { _fs.root[options.recursive ? "getDirectory" : "getFile"](path, {create: false}, function (entry) { entry[options.recursive ? "removeRecursively" : "remove"](function () { - success(entry); + success(); }, error); }, error); }, @@ -130,17 +139,19 @@ _self = { var url = "filesystem:" + utils.location().origin + "/temporary/" + path; _resolveLocalFileSystemURL(url, function (entry) { success(entry); - }, error); + }, error); }, write: function (path, contents, success, error, options) { options = options || {}; - _self.stat(path, function (entry) { + function write(entry) { entry.createWriter(function (fileWriter) { var bb = _blobBuilder(); - fileWriter.onwriteend = success; + fileWriter.onwriteend = function (progressEvent) { + success(progressEvent.target); + }; fileWriter.onerror = error; if (options.mode === "append") { @@ -150,10 +161,38 @@ _self = { bb.append(contents); fileWriter.write(bb.getBlob('text/plain')); }, error); - }, error); + } + + _self.stat(path, function (entry) { + if (options.mode === "append") { + write(entry); + } else { + _self.rm(path, function () { + _self.touch(path, write, error); + }, error); + } + }, function (e) { + if (e.code === FileError.NOT_FOUND_ERR) { + _self.touch(path, write, error); + } else { + error(e); + } + }); }, read: function (path, success, error) { + _self.stat(path, function (entry) { + entry.file(function (file) { + var reader = new FileReader(); + + reader.onloadend = function (progressEvent) { + success(progressEvent.target.result); + }; + reader.onerror = error; + + reader.readAsText(file); + }, error); + }, error); } }; diff --git a/lib/ripple/platform/phonegap/1.0/FileReader.js b/lib/ripple/platform/phonegap/1.0/FileReader.js deleted file mode 100644 index 8c3dfd8b..00000000 --- a/lib/ripple/platform/phonegap/1.0/FileReader.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = function () { - return { - readAsBinaryString: function () { - throw "not implemented"; - }, - readAsDataURL: function () { - throw "not implemented"; - }, - readAsText: function () { - throw "not implemented"; - }, - readAsArrayBuffer: function () { - throw "not implemented"; - }, - abort: function () { - throw "not implemented"; - } - }; -}; diff --git a/lib/ripple/platform/phonegap/1.0/FileWriter.js b/lib/ripple/platform/phonegap/1.0/FileWriter.js deleted file mode 100644 index 5ffe01d6..00000000 --- a/lib/ripple/platform/phonegap/1.0/FileWriter.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = function () { - return { - write: function () { - throw "not implemented"; - }, - readAsDataURL: function () { - throw "not implemented"; - }, - seek: function () { - throw "not implemented"; - }, - truncate: function () { - throw "not implemented"; - }, - abort: function () { - throw "not implemented"; - } - }; -}; diff --git a/lib/ripple/platform/phonegap/1.0/file.js b/lib/ripple/platform/phonegap/1.0/file.js deleted file mode 100644 index 2022da14..00000000 --- a/lib/ripple/platform/phonegap/1.0/file.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - read: function () { - throw "not implemented"; - }, - write: function () { - throw "not implemented"; - } -}; diff --git a/lib/ripple/platform/phonegap/1.0/spec.js b/lib/ripple/platform/phonegap/1.0/spec.js index 1c04f690..bdd951fa 100644 --- a/lib/ripple/platform/phonegap/1.0/spec.js +++ b/lib/ripple/platform/phonegap/1.0/spec.js @@ -47,9 +47,6 @@ module.exports = { camera: { path: "phonegap/1.0/camera" }, - file: { - path: "phonegap/1.0/file" - }, sms: { path: "phonegap/1.0/sms" }, @@ -165,12 +162,6 @@ module.exports = { }, MicrophoneAttributes: { path: "phonegap/1.0/MicrophoneAttributes" - }, - FileReader: { - path: "phonegap/1.0/FileReader" - }, - FileWriter: { - path: "phonegap/1.0/FileWriter" } } diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js index 05c2ab73..03271b72 100644 --- a/test/unit/fileSystem.js +++ b/test/unit/fileSystem.js @@ -1,3 +1,18 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ var fileSystem = require('ripple/fileSystem'), utils = require('ripple/utils'); @@ -35,6 +50,8 @@ describe("fileSystem", function () { }; window.WebKitBlobBuilder = window.BlobBuilder = function () {}; + window.FileReader = global.FileReader = function () {}; + window.FileError = global.FileError = {NOT_FOUND_ERR: 1}; fileSystem.initialize(); }); @@ -48,6 +65,8 @@ describe("fileSystem", function () { delete window.webkitResolveLocalFileSystemURL; delete window.WebKitBlobBuilder; delete window.BlobBuilder; + delete window.FileReader; + delete global.FileReader; }); describe("initialize", function () { @@ -165,12 +184,10 @@ describe("fileSystem", function () { expect(success).not.toHaveBeenCalled(); }); - - // it does not return empty array when found values }); describe("rm", function () { - it("removes la file from the root", function () { + it("removes a file from the root", function () { var error = jasmine.createSpy(), remove = jasmine.createSpy().andCallFake(function (callback) { callback(); @@ -193,7 +210,7 @@ describe("fileSystem", function () { expect(_fs.root.getFile.argsForCall[0][1]).toEqual({create: false}); expect(typeof _fs.root.getFile.argsForCall[0][2]).toEqual("function"); expect(_fs.root.getFile.argsForCall[0][3]).toEqual(error); - expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(success).toHaveBeenCalled(); expect(typeof remove.argsForCall[0][0]).toEqual("function"); expect(remove.argsForCall[0][1]).toEqual(error); expect(error).not.toHaveBeenCalled(); @@ -222,7 +239,7 @@ describe("fileSystem", function () { expect(_fs.root.getDirectory.argsForCall[0][1]).toEqual({create: false}); expect(typeof _fs.root.getDirectory.argsForCall[0][2]).toEqual("function"); expect(_fs.root.getDirectory.argsForCall[0][3]).toEqual(error); - expect(success).toHaveBeenCalledWith(_resultEntries[0]); + expect(success).toHaveBeenCalled(); expect(typeof removeRecursively.argsForCall[0][0]).toEqual("function"); expect(removeRecursively.argsForCall[0][1]).toEqual(error); expect(error).not.toHaveBeenCalled(); @@ -233,7 +250,7 @@ describe("fileSystem", function () { it("removes a directory", function () { var error = jasmine.createSpy(), success = jasmine.createSpy(); - + spyOn(fileSystem, "rm"); fileSystem.rmdir("/foo", success, error); expect(fileSystem.rm).toHaveBeenCalledWith("/foo", success, error, {recursive: false}); @@ -254,7 +271,7 @@ describe("fileSystem", function () { success(entry); }); - spyOn(utils, "location").andReturn({origin: domain}); + spyOn(utils, "location").andReturn({origin: domain}); fileSystem.stat("/bob", success, error); @@ -302,7 +319,7 @@ describe("fileSystem", function () { expect(success).toHaveBeenCalledWith(movedEntry); }); }); - + describe("cp", function () { it("can copy a file from one location to another", function () { var copiedEntry = { @@ -351,6 +368,9 @@ describe("fileSystem", function () { onerror: null, write: jasmine.createSpy() }, + progressEvent = { + target: fileWriterInstance + }, fileEntry = { fullPath: "some/path", isDirectory: false, @@ -358,7 +378,7 @@ describe("fileSystem", function () { callback(fileWriterInstance); }) }, - txt = "plain text blob", + txt = "plain text blob", blobInstance = { append: jasmine.createSpy(), getBlob: jasmine.createSpy().andReturn(txt) @@ -368,17 +388,82 @@ describe("fileSystem", function () { success(fileEntry); }); + spyOn(fileSystem, "touch").andCallFake(function (path, success, error) { + success(fileEntry); + }); + + spyOn(fileSystem, "rm").andCallFake(function (path, success, error) { + success(); + }); + spyOn(window, "BlobBuilder").andReturn(blobInstance); fileSystem.write(path, contents, success, error); - expect(fileWriterInstance.onwriteend).toBe(success); + fileWriterInstance.onwriteend(progressEvent); + + expect(fileSystem.rm.callCount).toBe(1); + expect(fileSystem.rm.argsForCall[0][2]).toEqual(error); + expect(fileSystem.touch.callCount).toBe(1); + expect(fileSystem.touch.argsForCall[0][0]).toEqual(path); + expect(fileSystem.touch.argsForCall[0][2]).toEqual(error); + + expect(success).toHaveBeenCalledWith(progressEvent.target); expect(fileWriterInstance.onerror).toBe(error); expect(fileEntry.createWriter.callCount).toBe(1); expect(fileEntry.createWriter.argsForCall[0][1]).toBe(error); expect(blobInstance.append).toHaveBeenCalledWith(contents); expect(fileWriterInstance.write).toHaveBeenCalledWith(txt); - expect(fileSystem.stat.argsForCall[0][2]).toBe(error); + }); + + it("creates the file if it does not exist", function () { + var path = "some/path", + contents = "file data", + error = jasmine.createSpy(), + success = jasmine.createSpy(), + txt = "plain text blob", + blobInstance = { + append: jasmine.createSpy(), + getBlob: jasmine.createSpy().andReturn(txt) + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + error({code: 1}); + }); + + spyOn(fileSystem, "touch"); + spyOn(fileSystem, "rm"); + spyOn(window, "BlobBuilder").andReturn(blobInstance); + + fileSystem.write(path, contents, success, error); + + expect(fileSystem.touch.callCount).toBe(1); + expect(fileSystem.touch.argsForCall[0][0]).toEqual(path); + expect(fileSystem.touch.argsForCall[0][2]).toEqual(error); + }); + + it("invokes error when file does exit", function () { + var path = "some/path", + contents = "file data", + error = jasmine.createSpy(), + success = jasmine.createSpy(), + txt = "plain text blob", + blobInstance = { + append: jasmine.createSpy(), + getBlob: jasmine.createSpy().andReturn(txt) + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + error({code: 2}); + }); + + spyOn(fileSystem, "touch"); + spyOn(fileSystem, "rm"); + spyOn(window, "BlobBuilder").andReturn(blobInstance); + + fileSystem.write(path, contents, success, error); + + expect(fileSystem.touch).not.toHaveBeenCalled(); }); describe("when options.append", function () { @@ -404,7 +489,7 @@ describe("fileSystem", function () { callback(fileWriterInstance); }) }, - txt = "plain text blob", + txt = "plain text blob", blobInstance = { append: jasmine.createSpy(), getBlob: jasmine.createSpy().andReturn(txt) @@ -414,6 +499,14 @@ describe("fileSystem", function () { success(fileEntry); }); + spyOn(fileSystem, "touch").andCallFake(function (path, success, error) { + success(fileEntry); + }); + + spyOn(fileSystem, "rm").andCallFake(function (path, success, error) { + success(); + }); + spyOn(window, "BlobBuilder").andReturn(blobInstance); fileSystem.write(path, contents, success, error, options); @@ -421,11 +514,45 @@ describe("fileSystem", function () { expect(fileWriterInstance.seek).toHaveBeenCalledWith(fileWriterInstance.length); }); }); - - // TODO: it creates the file if it does not exist - // TODO: it appends onto a file with options.mode === "append" }); - // TODO: fileWriter.onwriteend may get called even if there is an error? (see FileWriter spec) - // TODO: make consistent the objects that get returned (i.e. {name, isDirectory} instead of full Directory/FileEntry objects) + describe("read", function () { + it("returns contents of a file", function () { + var path = "a/file", + error = jasmine.createSpy(), + success = jasmine.createSpy(), + fileInstance = jasmine.createSpy(), + fileReaderInstance = { + onloadend: null, + result: "file data", + readAsText: jasmine.createSpy() + }, + progressEvent = { + target: fileReaderInstance + }, + fileEntry = { + fullPath: "a/file", + isDirectory: false, + file: jasmine.createSpy().andCallFake(function (callback) { + callback(fileInstance); + }) + }; + + spyOn(fileSystem, "stat").andCallFake(function (path, success, error) { + success(fileEntry); + }); + + spyOn(global, "FileReader").andReturn(fileReaderInstance); + + fileSystem.read(path, success, error); + + fileReaderInstance.onloadend(progressEvent); + + expect(fileReaderInstance.readAsText).toHaveBeenCalledWith(fileInstance); + expect(success).toHaveBeenCalledWith(fileReaderInstance.result); + expect(fileReaderInstance.onerror).toBe(error); + expect(fileEntry.file.argsForCall[0][1]).toBe(error); + expect(fileSystem.stat.argsForCall[0][2]).toBe(error); + }); + }); }); From 11fad806cd8e913f49b50f9a673a470c56f4a631 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 30 Aug 2011 22:24:27 -0400 Subject: [PATCH 006/182] created test shell for webworks.core io.dir --- .../webworks.core/2.0.0/client/io/dir.js | 10 +++ .../webworks.core/2.0.0/server/io/dir.js | 1 + .../platform/webworks.handset/2.0.0/server.js | 5 +- .../platform/webworks.handset/2.0.0/spec.js | 8 ++ .../platform/webworks.tablet/2.0.0/server.js | 3 + .../platform/webworks.tablet/2.0.0/spec.js | 8 ++ test/unit/webworks.tablet/systemEvent.js | 20 ++--- test/unit/webworks/io/dir.js | 80 +++++++++++++++++++ 8 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js create mode 100644 lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js create mode 100644 test/unit/webworks/io/dir.js diff --git a/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js b/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js new file mode 100644 index 00000000..26f6a57c --- /dev/null +++ b/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js @@ -0,0 +1,10 @@ +var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'), + _uri = "blackberry/io/dir/"; + +module.exports = { + createNewDir: function (path) { + return transport.call(_uri + "createNewDir", { + post: {path: path} + }); + } +}; diff --git a/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js b/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js new file mode 100644 index 00000000..f053ebf7 --- /dev/null +++ b/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/lib/ripple/platform/webworks.handset/2.0.0/server.js b/lib/ripple/platform/webworks.handset/2.0.0/server.js index e0033d1c..ec2b5fe7 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/server.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/server.js @@ -48,6 +48,9 @@ module.exports = { menu: require(platform + "menu"), dialog: require(platform + "dialog") }, - phone: require(platform + "phone") + phone: require(platform + "phone"), + io: { + dir: require(core + "io/dir") + } } }; diff --git a/lib/ripple/platform/webworks.handset/2.0.0/spec.js b/lib/ripple/platform/webworks.handset/2.0.0/spec.js index ea70580e..d4bb52d9 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/spec.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/spec.js @@ -267,6 +267,14 @@ module.exports = { feature: "blackberry.audio.Player" } } + }, + io: { + children: { + dir: { + path: "webworks.core/2.0.0/client/io/dir", + feature: "blackberry.io.dir" + } + } } } } diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/server.js b/lib/ripple/platform/webworks.tablet/2.0.0/server.js index 7b580f75..a5a18e03 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/server.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/server.js @@ -31,6 +31,9 @@ module.exports = { system: system, ui: { dialog: require(platform + "dialog") + }, + io: { + dir: require(core + "io/dir") } } }; diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/spec.js b/lib/ripple/platform/webworks.tablet/2.0.0/spec.js index 797fac8a..616e3803 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/spec.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/spec.js @@ -102,6 +102,14 @@ module.exports = { utils: { path: "webworks.core/2.0.0/client/utils", feature: "blackberry.utils" + }, + io: { + children: { + dir: { + path: "webworks.core/2.0.0/client/io/dir", + feature: "blackberry.io.dir" + } + } } } } diff --git a/test/unit/webworks.tablet/systemEvent.js b/test/unit/webworks.tablet/systemEvent.js index 537d4de5..214b8a17 100644 --- a/test/unit/webworks.tablet/systemEvent.js +++ b/test/unit/webworks.tablet/systemEvent.js @@ -16,7 +16,7 @@ describe("webworks.tablet system event", function () { var server = require('ripple/platform/webworks.tablet/2.0.0/server/systemEvent'), client = require('ripple/platform/webworks.tablet/2.0.0/client/systemEvent'), - spec = require('ripple/platform/webworks.tablet/2.0.0/spec/device'), + deviceSpec = require('ripple/platform/webworks.tablet/2.0.0/spec/device'), transport = require('ripple/platform/webworks.core/2.0.0/client/transport'), event = require('ripple/event'), MockBaton = function () { @@ -42,23 +42,23 @@ describe("webworks.tablet system event", function () { describe("in the device spec", function () { it("includes setting to togger handset charging on and off", function () { - expect(typeof spec.battery.state.name).toEqual("string"); - expect(spec.battery.state.control.type).toEqual("checkbox"); + expect(typeof deviceSpec.battery.state.name).toEqual("string"); + expect(deviceSpec.battery.state.control.type).toEqual("checkbox"); - expect(typeof spec.battery.level.callback).toEqual("function"); + expect(typeof deviceSpec.battery.level.callback).toEqual("function"); spyOn(event, "trigger"); - spec.battery.state.callback(false); + deviceSpec.battery.state.callback(false); expect(event.trigger).toHaveBeenCalledWith("DeviceBatteryStateChanged", [false]); }); it("includes setting to set charge level of the handset", function () { - expect(typeof spec.battery.level.name).toEqual("string"); - expect(spec.battery.level.control.type).toEqual("select"); - expect(typeof spec.battery.level.options === "object").toEqual(true); + expect(typeof deviceSpec.battery.level.name).toEqual("string"); + expect(deviceSpec.battery.level.control.type).toEqual("select"); + expect(typeof deviceSpec.battery.level.options === "object").toEqual(true); - expect(typeof spec.battery.level.callback).toEqual("function"); + expect(typeof deviceSpec.battery.level.callback).toEqual("function"); spyOn(event, "trigger"); - spec.battery.level.callback(87); + deviceSpec.battery.level.callback(87); expect(event.trigger).toHaveBeenCalledWith("DeviceBatteryLevelChanged", [87]); }); }); diff --git a/test/unit/webworks/io/dir.js b/test/unit/webworks/io/dir.js new file mode 100644 index 00000000..9f1c3dc1 --- /dev/null +++ b/test/unit/webworks/io/dir.js @@ -0,0 +1,80 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +describe("webworks.core io.dir", function () { + var server = require('ripple/platform/webworks.core/2.0.0/server/io/dir'), + client = require('ripple/platform/webworks.core/2.0.0/client/io/dir'), + transport = require('ripple/platform/webworks.core/2.0.0/client/transport'); + + describe("handset", function () { + describe("platform spec index", function () { + it("includes module according to proper object structure", function () { + var spec = require('ripple/platform/webworks.handset/2.0.0/spec'); + expect(spec.objects.blackberry.children.io.children.dir).toEqual({ + path: "webworks.core/2.0.0/client/io/dir", + feature: "blackberry.io.dir" + }); + }); + }); + + describe("server index", function () { + it("exposes the server module", function () { + var webworks = require('ripple/platform/webworks.handset/2.0.0/server'); + expect(webworks.blackberry.io.dir).toEqual(server); + }); + }); + }); + + describe("tablet", function () { + describe("platform spec index", function () { + it("includes module according to proper object structure", function () { + var spec = require('ripple/platform/webworks.tablet/2.0.0/spec'); + expect(spec.objects.blackberry.children.io.children.dir).toEqual({ + path: "webworks.core/2.0.0/client/io/dir", + feature: "blackberry.io.dir" + }); + }); + }); + + describe("server index", function () { + it("exposes the server module", function () { + var webworks = require('ripple/platform/webworks.tablet/2.0.0/server'); + expect(webworks.blackberry.io.dir).toEqual(server); + }); + }); + }); + + describe("core", function () { + describe("client", function () { + describe("createNewDir", function () { + it("calls transport with appropriate args", function () { + var args, + path = "new/new/new/dir"; + + spyOn(transport, "call"); + expect(client.createNewDir(path)).not.toBeDefined(); + + args = transport.call.argsForCall[0]; + expect(args[0]).toEqual("blackberry/io/dir/createNewDir"); + expect(args[1]).toEqual({post: {path: path}}); + }); + }); + }); + + // TODO: server should also support any changed URI methods and what they return + describe("server", function () { + }); + }); +}); From 63d75eae7a4290689667f655b8f93e62c219063e Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 30 Aug 2011 23:30:32 -0300 Subject: [PATCH 007/182] last minute tweaks.. --- .../webworks.core/2.0.0/client/io/dir.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js b/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js index 26f6a57c..8bc8e7b5 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js +++ b/lib/ripple/platform/webworks.core/2.0.0/client/io/dir.js @@ -1,9 +1,24 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'), _uri = "blackberry/io/dir/"; module.exports = { createNewDir: function (path) { - return transport.call(_uri + "createNewDir", { + transport.call(_uri + "createNewDir", { post: {path: path} }); } From b36d51f1cbdf5554b54868bfe13b9685b2ca3991 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 31 Aug 2011 17:42:55 -0400 Subject: [PATCH 008/182] created a fileSystem cache (for webworks), almost finished webworks io.dir module --- lib/ripple/fileSystem.js | 10 +- .../webworks.core/2.0.0/fileSystemCache.js | 138 ++++++++++++++++++ .../webworks.core/2.0.0/server/io/dir.js | 19 +++ test/unit/fileSystem.js | 24 ++- test/unit/webworks/fileSystemCache.js | 111 ++++++++++++++ 5 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js create mode 100644 test/unit/webworks/fileSystemCache.js diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js index 020ec6a8..77acb1ab 100644 --- a/lib/ripple/fileSystem.js +++ b/lib/ripple/fileSystem.js @@ -93,8 +93,14 @@ _self = { }, error); }, - rmdir: function (path, success, error) { - _self.rm(path, success, error, {recursive: false}); + rmdir: function (path, success, error, options) { + options = options || {}; + + _fs.root.getDirectory(path, {create: false}, function (entry) { + entry.remove(function () { + success(); + }, error); + }, error); }, mkdir: function (path, success, error) { diff --git a/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js new file mode 100644 index 00000000..fe35c0a2 --- /dev/null +++ b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js @@ -0,0 +1,138 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var fs = require('ripple/fileSystem'), + utils = require('ripple/utils'), + _console = require('ripple/console'), + _cache = {}; + +function _walk(path, parent) { + fs.ls(path, function (entries) { + parent.children = parent.children || {}; + + entries.forEach(function (entry) { + parent.children[entry.name] = entry; + + if (entry.isDirectory) { + _walk(entry.fullPath, entry); + } + }); + }, _fsError); +} + +function _walkFS() { + _cache = {}; + _walk("/", _cache); +} + +function _fsError(e) { + _walkFS(); + _console.error("FileSystem error (code " + e.code + ")"); +} + +function _get(path) { + return path.replace(/^\//, '').split("/").reduce(function (obj, token) { + return token === "" ? obj : (obj.children ? obj.children[token] || null : null); + }, _cache); +} + +function _set(path, obj) { + var parent = _cache, + tokens = path.replace(/^\//, '').split("/"), + child = tokens.splice(tokens.length - 1, 1).join(""); + + tokens.forEach(function (token) { + parent = parent.children[token]; + }); + + parent.children = parent.children || {}; + parent.children[child] = obj; +} + +function _delete(path) { + var parent = _cache, + tokens = path.replace(/^\//, '').split("/"), + child = tokens.splice(tokens.length - 1, 1).join(""); + + tokens.forEach(function (token) { + parent = parent.children[token]; + }); + + delete parent.children[child]; +} + +module.exports = { + initialize: _walkFS, + dir: { + createNewDir: function (path) { + + var entry = _get(path); + + if (!entry) { + _set(path, { + fullPath: path + }); + } + + fs.mkdir(path, function (entry) { + _set(path, entry); + }, _fsError); + }, + + deleteDirectory: function (path, recursive) { + _delete(path); + if (recursive) { + fs.rm(path, function () {}, _fsError, {recursive: recursive}); + } else { + fs.rmdir(path, function () {}, _fsError); + } + }, + + exists: function (path) { + var entry = _get(path); + fs.stat(path, function () {}, _fsError); + return entry && entry.isDirectory; + }, + + getParentDirectory: function (path) { + path = "/" + path.replace(/^\//, '').replace(/\/$/, ''); + + var entry = _get(path), + parent = null, + array = path.split("/"); + + fs.stat(path, function (entry) { + entry.getParent(function (p) {}, _fsError); + }, _fsError); + + return entry ? array.splice(0, array.length - 1).join("/") || "/" : null; + }, + + listDirectories: function (path) { + var dir = _get(path), + directories = []; + + utils.forEach(dir.children, function (item) { + if (item.isDirectory) { + directories.push(item.name); + } + }); + + fs.ls(path, function () {}, _fsError); + + return directories; + } + } +}; diff --git a/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js b/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js index f053ebf7..c6fe3cfd 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js +++ b/lib/ripple/platform/webworks.core/2.0.0/server/io/dir.js @@ -1 +1,20 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var fileSystemCache = require('ripple/platform/webworks.core/2.0.0/fileSystemCache'); + +//fileSystemCache.initialize(); + module.exports = {}; diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js index 03271b72..0dcaea48 100644 --- a/test/unit/fileSystem.js +++ b/test/unit/fileSystem.js @@ -249,11 +249,31 @@ describe("fileSystem", function () { describe("rmdir", function () { it("removes a directory", function () { var error = jasmine.createSpy(), + remove = jasmine.createSpy().andCallFake(function (callback) { + callback(); + }), success = jasmine.createSpy(); - spyOn(fileSystem, "rm"); + _fs.root.getDirectory = function (path, options, success, error) { + success(_resultEntries[0]); + }; + + spyOn(_fs.root, "getDirectory").andCallThrough(); + + _resultEntries = [ + {fullPath: "/foo", isDirectory: true, remove: remove} + ]; + fileSystem.rmdir("/foo", success, error); - expect(fileSystem.rm).toHaveBeenCalledWith("/foo", success, error, {recursive: false}); + + expect(_fs.root.getDirectory.argsForCall[0][0]).toEqual("/foo"); + expect(_fs.root.getDirectory.argsForCall[0][1]).toEqual({create: false}); + expect(typeof _fs.root.getDirectory.argsForCall[0][2]).toEqual("function"); + expect(_fs.root.getDirectory.argsForCall[0][3]).toEqual(error); + expect(success).toHaveBeenCalled(); + expect(typeof remove.argsForCall[0][0]).toEqual("function"); + expect(remove.argsForCall[0][1]).toEqual(error); + expect(error).not.toHaveBeenCalled(); }); }); diff --git a/test/unit/webworks/fileSystemCache.js b/test/unit/webworks/fileSystemCache.js new file mode 100644 index 00000000..6f54905d --- /dev/null +++ b/test/unit/webworks/fileSystemCache.js @@ -0,0 +1,111 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var fs = require('ripple/fileSystem'), + cache = require('ripple/platform/webworks.core/2.0.0/fileSystemCache'); + +describe("fileSystemCache", function () { + var _root = [{ + fullPath: "/dude", + name: "dude", + isDirectory: false + }, { + fullPath: "/dudeDir", + name: "dudeDir", + isDirectory: true + }, { + fullPath: "/hippo", + name: "hippo", + isDirectory: true + }]; + + beforeEach(function () { + spyOn(fs, "ls").andCallFake(function (path, success, error) { + success(path === "/" ? _root : []); + }); + + cache.initialize(); + }); + + describe("io.dir", function () { + describe("createNewDir", function () { + it("creates a directory", function () { + spyOn(fs, "mkdir"); + cache.dir.createNewDir("/test"); + expect(fs.mkdir.argsForCall[0][0]).toBe("/test"); + expect(typeof fs.mkdir.argsForCall[0][1]).toBe("function"); + expect(typeof fs.mkdir.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("deleteDirectory", function () { + it("removes a directory", function () { + spyOn(fs, "rmdir"); + cache.dir.deleteDirectory("/dudeDir"); + expect(fs.rmdir.argsForCall[0][0]).toBe("/dudeDir"); + expect(typeof fs.rmdir.argsForCall[0][1]).toBe("function"); + expect(typeof fs.rmdir.argsForCall[0][2]).toBe("function"); + }); + + it("removes a directory recursively", function () { + spyOn(fs, "rm"); + cache.dir.deleteDirectory("/dudeDir", true); + expect(fs.rm.argsForCall[0][0]).toBe("/dudeDir"); + expect(typeof fs.rm.argsForCall[0][1]).toBe("function"); + expect(typeof fs.rm.argsForCall[0][2]).toBe("function"); + expect(fs.rm.argsForCall[0][3]).toEqual({recursive: true}); + }); + }); + + describe("exists", function () { + it("returns true when the file exists", function () { + spyOn(fs, "stat"); + expect(cache.dir.exists("/dudeDir")).toBe(true); + expect(fs.stat.argsForCall[0][0]).toBe("/dudeDir"); + expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); + expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("getParentDirectory", function () { + it("returns the path to the parent directory", function () { + var entry = { + getParent: jasmine.createSpy() + }; + + spyOn(fs, "stat").andCallFake(function (path, success, error) { + success(entry); + }); + + expect(cache.dir.getParentDirectory("/dudeDir")).toBe("/"); + expect(fs.stat.argsForCall[0][0]).toBe("/dudeDir"); + expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); + expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); + expect(typeof entry.getParent.argsForCall[0][0]).toBe("function"); + expect(typeof entry.getParent.argsForCall[0][1]).toBe("function"); + }); + }); + + describe("listDirectories", function () { + it("returns an array of all directories in a path", function () { + expect(cache.dir.listDirectories("/")).toEqual(["dudeDir", "hippo"]); + expect(fs.ls.argsForCall[0][0]).toBe("/"); + expect(typeof fs.ls.argsForCall[0][1]).toBe("function"); + expect(typeof fs.ls.argsForCall[0][2]).toBe("function"); + }); + }); + + }); +}); From c39b169e2b21eb0271c7ad1ac1fdc1718908d062 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 1 Sep 2011 09:58:49 -0400 Subject: [PATCH 009/182] Adding listFiles and rename to webworks file system api --- .../webworks.core/2.0.0/fileSystemCache.js | 34 +++++++++++++++++++ test/unit/webworks/fileSystemCache.js | 23 +++++++++++++ 2 files changed, 57 insertions(+) diff --git a/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js index fe35c0a2..a9adef72 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js +++ b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js @@ -133,6 +133,40 @@ module.exports = { fs.ls(path, function () {}, _fsError); return directories; + }, + + listFiles: function (path) { + var dir = _get(path), + files = []; + + utils.forEach(dir.children, function (item) { + if (!item.isDirectory) { + files.push(item.name); + } + }); + + fs.ls(path, function () {}, _fsError); + + return files; + }, + + rename: function (path, newName) { + var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"), + oldName = parent.splice(parent.length - 1, 1).join(""), + from, to; + + parent = parent.join("/"); + from = parent + "/" + oldName; + to = parent + "/" + newName; + + _delete(from); + _set(to, { + fullPath: to + }); + + fs.mv(parent + "/" + oldName, parent + "/" + newName, function (entry) { + _set(to, entry); + }, _fsError); } } }; diff --git a/test/unit/webworks/fileSystemCache.js b/test/unit/webworks/fileSystemCache.js index 6f54905d..2a20c741 100644 --- a/test/unit/webworks/fileSystemCache.js +++ b/test/unit/webworks/fileSystemCache.js @@ -25,6 +25,10 @@ describe("fileSystemCache", function () { fullPath: "/dudeDir", name: "dudeDir", isDirectory: true + }, { + fullPath: "/hungry", + name: "hungry", + isDirectory: false }, { fullPath: "/hippo", name: "hippo", @@ -107,5 +111,24 @@ describe("fileSystemCache", function () { }); }); + describe("listFiles", function () { + it("returns an array of all files in a path", function () { + expect(cache.dir.listFiles("/")).toEqual(["dude", "hungry"]); + expect(fs.ls.argsForCall[0][0]).toBe("/"); + expect(typeof fs.ls.argsForCall[0][1]).toBe("function"); + expect(typeof fs.ls.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("rename", function () { + it("renames a directory at the specified path", function () { + spyOn(fs, "mv"); + cache.dir.rename("/dudeDir", "theDudeDir"); + expect(fs.mv.argsForCall[0][0]).toBe("/dudeDir"); + expect(fs.mv.argsForCall[0][1]).toBe("/theDudeDir"); + expect(typeof fs.mv.argsForCall[0][2]).toBe("function"); + expect(typeof fs.mv.argsForCall[0][3]).toBe("function"); + }); + }); }); }); From 77c8e532e538ae20eaf6ad37d64d9a0383e60286 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Thu, 1 Sep 2011 16:51:58 -0400 Subject: [PATCH 010/182] completed webworks fileSystem cache, webworks utils stringtoBlob/blobToString methods --- .jshintrc | 1 + lib/ripple/fileSystem.js | 2 +- .../2.0.0/client/FileProperties.js | 35 ++++ .../webworks.core/2.0.0/client/utils.js | 166 +++++++++------- .../webworks.core/2.0.0/fileSystemCache.js | 148 +++++++++++--- test/unit/fileSystem.js | 2 +- test/unit/webworks/fileSystemCache.js | 180 +++++++++++++++++- test/unit/webworks/utils.js | 84 ++++++++ 8 files changed, 517 insertions(+), 101 deletions(-) create mode 100644 lib/ripple/platform/webworks.core/2.0.0/client/FileProperties.js create mode 100644 test/unit/webworks/utils.js diff --git a/.jshintrc b/.jshintrc index 961ed4d0..fa4f46c7 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,6 +1,7 @@ { "predef": [ "FileReader", "FileWriter", + "WebKitBlobBuilder", "BlobBuilder", "webkitNotifications", "FileError", "DOMDocument", diff --git a/lib/ripple/fileSystem.js b/lib/ripple/fileSystem.js index 77acb1ab..97b766bf 100644 --- a/lib/ripple/fileSystem.js +++ b/lib/ripple/fileSystem.js @@ -156,7 +156,7 @@ _self = { var bb = _blobBuilder(); fileWriter.onwriteend = function (progressEvent) { - success(progressEvent.target); + success(entry); }; fileWriter.onerror = error; diff --git a/lib/ripple/platform/webworks.core/2.0.0/client/FileProperties.js b/lib/ripple/platform/webworks.core/2.0.0/client/FileProperties.js new file mode 100644 index 00000000..4ae4697f --- /dev/null +++ b/lib/ripple/platform/webworks.core/2.0.0/client/FileProperties.js @@ -0,0 +1,35 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +function FileProperties(props) { + props = props || {}; + + function _get(val) { + return function () { + return props[val]; + }; + } + + this.__defineGetter__("dateCreated", _get("dateCreated")); //tablet only + this.__defineGetter__("dateModified", _get("dateModified")); + this.__defineGetter__("directory", _get("directory")); + this.__defineGetter__("fileExtension", _get("fileExtension")); + this.__defineGetter__("isHidden", _get("isHidden")); + this.__defineGetter__("isReadonly", _get("isReadonly")); //handset only + this.__defineGetter__("mimeType", _get("mimeType")); //handset only + this.__defineGetter__("size", _get("size")); +} + +module.exports = FileProperties; diff --git a/lib/ripple/platform/webworks.core/2.0.0/client/utils.js b/lib/ripple/platform/webworks.core/2.0.0/client/utils.js index 577ffe42..296368c6 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/client/utils.js +++ b/lib/ripple/platform/webworks.core/2.0.0/client/utils.js @@ -13,91 +13,119 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -function Utils(disp) { +var _hate = {}; + +function _blobBuilder() { + var BlobBuilder = BlobBuilder || WebKitBlobBuilder; + return new BlobBuilder(); } -Utils.prototype.parseURL = function (theUrl) { - /********START IDEA BORROWING*******/ - // parseUri 1.2.2 - // (c) Steven Levithan - // MIT License +module.exports = { + parseURL: function (theUrl) { + /********START IDEA BORROWING*******/ + // parseUri 1.2.2 + // (c) Steven Levithan + // MIT License + + function parseUri(str) { + var o = parseUri.options, + m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), + uri = {}, + i = 14; + + while (i--) { + uri[o.key[i]] = m[i] || ""; + } - function parseUri(str) { - var o = parseUri.options, - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), - uri = {}, - i = 14; + uri[o.q.name] = {}; + uri[o.q.arrayName] = []; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) { + uri[o.q.name][$1] = $2; + uri[o.q.arrayName].push($2); + } + }); - while (i--) { - uri[o.key[i]] = m[i] || ""; + return uri; } - uri[o.q.name] = {}; - uri[o.q.arrayName] = []; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) { - uri[o.q.name][$1] = $2; - uri[o.q.arrayName].push($2); + parseUri.options = { + strictMode: false, + key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"], + q: { + name: "queryKey", + arrayName: "queryArray", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } + }; + /********END IDEA BORROWING*******/ + + parseUri.strictMode = "strict"; + var uri = parseUri(theUrl), + retVal = { + getURLParameter : function (key) { + return uri.queryKey[key]; + }, + + getURLParameterByIndex : function (index) { + return uri.queryArray[index]; + } + }; + + //Add default values for the http/https port if they weren't specified in the URL. The above parser returns undefined. We need the values + //to be compatible with the BB version of API. + if (uri["port"] === "") { + if (uri["protocol"] === "http") { + uri["port"] = "80"; + } + else if (uri["protocol"] === "https") { + uri["port"] = "443"; + } + else { + uri["port"] = "0"; } + } + + retVal.__defineGetter__("host", function () { + return uri["host"]; + }); + retVal.__defineGetter__("port", function () { + return parseInt(uri["port"], 10); }); - return uri; - } + return retVal; + }, - parseUri.options = { - strictMode: false, - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"], - q: { - name: "queryKey", - arrayName: "queryArray", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } - }; - /********END IDEA BORROWING*******/ + generateUniqueId: function () { + return Math.floor(Math.random() * Number.MAX_VALUE); + }, - parseUri.strictMode = "strict"; - var uri = parseUri(theUrl), - retVal = { - getURLParameter : function (key) { - return uri.queryKey[key]; - }, + blobToString: function (blob, encoding) { + var file = new FileReader(); - getURLParameterByIndex : function (index) { - return uri.queryArray[index]; - } + file.onloadend = function () { + _hate[blob.uuid] = file.result; }; + file.readAsText(blob); + return _hate[blob.uuid]; + }, - //Add default values for the http/https port if they weren't specified in the URL. The above parser returns undefined. We need the values - //to be compatible with the BB version of API. - if (uri["port"] === "") { - if (uri["protocol"] === "http") { - uri["port"] = "80"; - } - else if (uri["protocol"] === "https") { - uri["port"] = "443"; - } - else { - uri["port"] = "0"; - } - } + stringToBlob: function (string, encoding) { + var uuid = Math.uuid(undefined, 16), + blob = _blobBuilder(), + finalBlob; - retVal.__defineGetter__("host", function () { - return uri["host"]; - }); - retVal.__defineGetter__("port", function () { - return parseInt(uri["port"], 10); - }); + _hate[uuid] = string; + blob.append(string); - return retVal; -}; + finalBlob = blob.getBlob(); + finalBlob.uuid = uuid; -Utils.prototype.generateUniqueId = function () { - return Math.floor(Math.random() * Number.MAX_VALUE); + return finalBlob; + } }; - -module.exports = new Utils(); diff --git a/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js index a9adef72..6b958dd5 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js +++ b/lib/ripple/platform/webworks.core/2.0.0/fileSystemCache.js @@ -16,7 +16,15 @@ var fs = require('ripple/fileSystem'), utils = require('ripple/utils'), _console = require('ripple/console'), - _cache = {}; + bbUtils = require('ripple/platform/webworks.core/2.0.0/client/utils'), + FileProperties = require('ripple/platform/webworks.core/2.0.0/client/FileProperties'), + _cache = {}, + _self; + +function _fsError(e) { + _self.initialize(); + _console.error("FileSystem error (code " + e.code + ")"); +} function _walk(path, parent) { fs.ls(path, function (entries) { @@ -24,30 +32,41 @@ function _walk(path, parent) { entries.forEach(function (entry) { parent.children[entry.name] = entry; + parent.children[entry.name].properties = {}; if (entry.isDirectory) { _walk(entry.fullPath, entry); + } else { + entry.file(function (file) { + utils.mixin(file, parent.children[entry.name].properties); + }); + fs.read(entry.fullPath, function (data) { + parent.children[entry.name].data = data; + }, _fsError); } }); }, _fsError); } -function _walkFS() { - _cache = {}; - _walk("/", _cache); -} - -function _fsError(e) { - _walkFS(); - _console.error("FileSystem error (code " + e.code + ")"); -} - function _get(path) { return path.replace(/^\//, '').split("/").reduce(function (obj, token) { return token === "" ? obj : (obj.children ? obj.children[token] || null : null); }, _cache); } +function _getInfo(path) { + var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"), + name = parent.splice(parent.length - 1, 1).join(""), + ext = name.split("."); + + return { + name: name, + extension: ext.length > 1 ? ext[ext.length - 1] : "", + hidden: (name.length > 0 && name[0] === ".") || false, + parent: parent.join("/") || "/" + }; +} + function _set(path, obj) { var parent = _cache, tokens = path.replace(/^\//, '').split("/"), @@ -58,6 +77,7 @@ function _set(path, obj) { }); parent.children = parent.children || {}; + obj.properties = obj.properties || {}; parent.children[child] = obj; } @@ -73,11 +93,88 @@ function _delete(path) { delete parent.children[child]; } -module.exports = { - initialize: _walkFS, +// TODO: handle exceptions so that any respective fs command can error out +// TODO: dateCreated is always dateModified + +_self = { + initialize: function () { + _cache = {}; + _walk("/", _cache); + }, + file: { + exists: function (path) { + var entry = _get(path); + fs.stat(path, function () {}, _fsError); + return !!(entry && !entry.isDirectory); + }, + + deleteFile: function (path) { + _delete(path); + fs.rm(path, function () {}, _fsError); + }, + + copy: function (from, to) { + _delete(from); + _set(to, { + fullPath: to + }); + + fs.cp(from, to, function (entry) { + _set(to, entry); + }, _fsError); + }, + + getFileProperties: function (path) { + var entry = _get(path), + info = _getInfo(path); + + fs.stat(path, function () {}, _fsError); + + return new FileProperties({ + dateCreated: entry.properties.lastModifiedDate, + dateModified: entry.properties.lastModifiedDate, + directory: info.parent, + fileExtension: info.extension, + isHidden: info.hidden, + isReadonly: false, + mimeType: entry.properties.type, + size: entry.properties.size + }); + }, + + rename: function (path, newName) { + _self.dir.rename(path, newName); + }, + + readFile: function (path, success, async) { + var entry = _get(path); + + async = async === false ? async : true; + + if (!async) { + success(bbUtils.stringToBlob(entry.data)); + } + + fs.read(path, function (data) { + if (async) { + success(bbUtils.stringToBlob(data)); + } + entry.data = data; + _set(path, entry); + }, _fsError); + }, + + saveFile: function (path, blob) { + var data = bbUtils.blobToString(blob); + + fs.write(path, data, function (entry) { + entry.data = data; + _set(path, entry); + }, _fsError); + } + }, dir: { createNewDir: function (path) { - var entry = _get(path); if (!entry) { @@ -103,14 +200,13 @@ module.exports = { exists: function (path) { var entry = _get(path); fs.stat(path, function () {}, _fsError); - return entry && entry.isDirectory; + return !!(entry && entry.isDirectory); }, getParentDirectory: function (path) { path = "/" + path.replace(/^\//, '').replace(/\/$/, ''); var entry = _get(path), - parent = null, array = path.split("/"); fs.stat(path, function (entry) { @@ -151,22 +247,26 @@ module.exports = { }, rename: function (path, newName) { - var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"), - oldName = parent.splice(parent.length - 1, 1).join(""), - from, to; - - parent = parent.join("/"); - from = parent + "/" + oldName; - to = parent + "/" + newName; + var info = _getInfo(path), + parent = info.parent, + oldName = info.name, + from = (parent === "/" ? "" : parent) + "/" + oldName, + to = (parent === "/" ? "" : parent) + "/" + newName; _delete(from); _set(to, { fullPath: to }); - fs.mv(parent + "/" + oldName, parent + "/" + newName, function (entry) { + fs.mv(from, to, function (entry) { _set(to, entry); }, _fsError); + }, + + getRootDirs: function () { + return _self.dir.listDirectories("/"); } } }; + +module.exports = _self; diff --git a/test/unit/fileSystem.js b/test/unit/fileSystem.js index 0dcaea48..49f3ebe3 100644 --- a/test/unit/fileSystem.js +++ b/test/unit/fileSystem.js @@ -428,7 +428,7 @@ describe("fileSystem", function () { expect(fileSystem.touch.argsForCall[0][0]).toEqual(path); expect(fileSystem.touch.argsForCall[0][2]).toEqual(error); - expect(success).toHaveBeenCalledWith(progressEvent.target); + expect(success).toHaveBeenCalledWith(fileEntry); expect(fileWriterInstance.onerror).toBe(error); expect(fileEntry.createWriter.callCount).toBe(1); expect(fileEntry.createWriter.argsForCall[0][1]).toBe(error); diff --git a/test/unit/webworks/fileSystemCache.js b/test/unit/webworks/fileSystemCache.js index 2a20c741..20f8ef66 100644 --- a/test/unit/webworks/fileSystemCache.js +++ b/test/unit/webworks/fileSystemCache.js @@ -14,21 +14,37 @@ * limitations under the License. */ var fs = require('ripple/fileSystem'), + FileProperties = require('ripple/platform/webworks.core/2.0.0/client/FileProperties'), + bbUtils = require('ripple/platform/webworks.core/2.0.0/client/utils'), cache = require('ripple/platform/webworks.core/2.0.0/fileSystemCache'); describe("fileSystemCache", function () { var _root = [{ fullPath: "/dude", name: "dude", - isDirectory: false + isDirectory: false, + file: function (success, error) { + success({ + lastModifiedDate: new Date(456), + size: 20, + type: "text/plain" + }); + } }, { fullPath: "/dudeDir", name: "dudeDir", isDirectory: true }, { - fullPath: "/hungry", - name: "hungry", - isDirectory: false + fullPath: "/hungry.js", + name: "hungry.js", + isDirectory: false, + file: function (success, error) { + success({ + lastModifiedDate: new Date(123), + size: 50, + type: "application/x-javascript" + }); + } }, { fullPath: "/hippo", name: "hippo", @@ -36,6 +52,7 @@ describe("fileSystemCache", function () { }]; beforeEach(function () { + spyOn(fs, "read"); spyOn(fs, "ls").andCallFake(function (path, success, error) { success(path === "/" ? _root : []); }); @@ -43,6 +60,80 @@ describe("fileSystemCache", function () { cache.initialize(); }); + // TODO: cache (get,set,delete) layer is not under test + + describe("io.file", function () { + describe("exists", function () { + it("returns true when the file exists", function () { + spyOn(fs, "stat"); + expect(cache.file.exists("/hungry.js")).toBe(true); + expect(fs.stat.argsForCall[0][0]).toBe("/hungry.js"); + expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); + expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); + }); + + it("returns false when when given a directory", function () { + spyOn(fs, "stat"); + expect(cache.file.exists("/dudeDir")).toBe(false); + expect(fs.stat.argsForCall[0][0]).toBe("/dudeDir"); + expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); + expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("deleteFile", function () { + it("removes a file", function () { + spyOn(fs, "rm"); + cache.file.deleteFile("/hungry.js"); + expect(fs.rm.argsForCall[0][0]).toBe("/hungry.js"); + expect(typeof fs.rm.argsForCall[0][1]).toBe("function"); + expect(typeof fs.rm.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("copy", function () { + it("copies the file at the specified path", function () { + spyOn(fs, "cp"); + cache.file.copy("/hungry.js", "/hungrier"); + expect(fs.cp.argsForCall[0][0]).toBe("/hungry.js"); + expect(fs.cp.argsForCall[0][1]).toBe("/hungrier"); + expect(typeof fs.cp.argsForCall[0][2]).toBe("function"); + expect(typeof fs.cp.argsForCall[0][3]).toBe("function"); + }); + }); + + describe("getFileProperties", function () { + it("returns an object of file properties", function () { + spyOn(fs, "stat"); + + var properties = new FileProperties({ + dateModified: new Date(123), + size: 50, + mimeType: "application/x-javascript" + }), + result = cache.file.getFileProperties("/hungry.js"); + + expect(result.dateModified).toEqual(new Date(123)); + expect(result.dateCreated).toEqual(new Date(123)); + expect(result.directory).toEqual("/"); + expect(result.fileExtension).toEqual("js"); + expect(result.isHidden).toEqual(false); + expect(result.isReadonly).toEqual(false); + expect(result.mimeType).toEqual(properties.mimeType); + expect(result.size).toEqual(50); + expect(result instanceof FileProperties).toBe(true); + }); + }); + + describe("rename", function () { + it("renames a file", function () { + spyOn(cache.dir, "rename"); + cache.file.rename("/hungry.js", "hungryhungry.js"); + expect(cache.dir.rename).toHaveBeenCalledWith("/hungry.js", "hungryhungry.js"); + }); + }); + }); + describe("io.dir", function () { describe("createNewDir", function () { it("creates a directory", function () { @@ -74,13 +165,21 @@ describe("fileSystemCache", function () { }); describe("exists", function () { - it("returns true when the file exists", function () { + it("returns true when the directory exists", function () { spyOn(fs, "stat"); expect(cache.dir.exists("/dudeDir")).toBe(true); expect(fs.stat.argsForCall[0][0]).toBe("/dudeDir"); expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); }); + + it("returns false when given a file", function () { + spyOn(fs, "stat"); + expect(cache.dir.exists("/hungry.js")).toBe(false); + expect(fs.stat.argsForCall[0][0]).toBe("/hungry.js"); + expect(typeof fs.stat.argsForCall[0][1]).toBe("function"); + expect(typeof fs.stat.argsForCall[0][2]).toBe("function"); + }); }); describe("getParentDirectory", function () { @@ -113,7 +212,7 @@ describe("fileSystemCache", function () { describe("listFiles", function () { it("returns an array of all files in a path", function () { - expect(cache.dir.listFiles("/")).toEqual(["dude", "hungry"]); + expect(cache.dir.listFiles("/")).toEqual(["dude", "hungry.js"]); expect(fs.ls.argsForCall[0][0]).toBe("/"); expect(typeof fs.ls.argsForCall[0][1]).toBe("function"); expect(typeof fs.ls.argsForCall[0][2]).toBe("function"); @@ -130,5 +229,74 @@ describe("fileSystemCache", function () { expect(typeof fs.mv.argsForCall[0][3]).toBe("function"); }); }); + + describe("getRootDirs", function () { + it("returns an array of top level directories", function () { + spyOn(cache.dir, "listDirectories").andReturn(["foo"]); + expect(cache.dir.getRootDirs()).toEqual(["foo"]); + expect(cache.dir.listDirectories).toHaveBeenCalledWith("/"); + }); + }); + }); + + describe("readFile", function () { + it("asynchronously reads data from a file", function () { + var blob = {size: 5}, + path = "/hungry.js", + success = jasmine.createSpy(); + + fs.read.reset(); + fs.read.andCallFake(function (path, success, error) { + setTimeout(function () { + success(blob); + }, 1); + }); + + spyOn(bbUtils, "stringToBlob").andReturn(blob); + + cache.file.readFile(path, success, true); + + waits(1); + runs(function () { + expect(success).toHaveBeenCalledWith(blob); + expect(fs.read.argsForCall[0][0]).toBe(path); + expect(typeof fs.read.argsForCall[0][1]).toBe("function"); + expect(typeof fs.read.argsForCall[0][2]).toBe("function"); + }); + }); + + it("synchronously reads data from a file", function () { + var blob = {size: 5}, + path = "/hungry.js", + success = jasmine.createSpy(); + + fs.read.reset(); + + spyOn(bbUtils, "stringToBlob").andReturn(blob); + + cache.file.readFile(path, success, false); + + expect(success).toHaveBeenCalledWith(blob); + expect(fs.read.argsForCall[0][0]).toBe(path); + expect(typeof fs.read.argsForCall[0][1]).toBe("function"); + expect(typeof fs.read.argsForCall[0][2]).toBe("function"); + }); + }); + + describe("saveFile", function () { + it("asynchronously writes data to a file", function () { + var blob = {size: 5}, + path = "/hungry.js"; + + spyOn(fs, "write"); + spyOn(bbUtils, "blobToString").andReturn("contents"); + + cache.file.saveFile(path, blob); + + expect(fs.write.argsForCall[0][0]).toBe(path); + expect(fs.write.argsForCall[0][1]).toBe("contents"); + expect(typeof fs.write.argsForCall[0][2]).toBe("function"); + expect(typeof fs.write.argsForCall[0][3]).toBe("function"); + }); }); }); diff --git a/test/unit/webworks/utils.js b/test/unit/webworks/utils.js new file mode 100644 index 00000000..f7d77d27 --- /dev/null +++ b/test/unit/webworks/utils.js @@ -0,0 +1,84 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var utils = require('ripple/platform/webworks.core/2.0.0/client/utils'); + +describe("utils", function () { + beforeEach(function () { + global.FileReader = jasmine.createSpy(); + global.BlobBuilder = global.WebKitBlobBuilder = jasmine.createSpy(); + }); + + afterEach(function () { + delete global.FileReader; + delete global.BlobBuilder; + delete global.WebKitBlobBuilder; + }); + + describe("handset", function () { + describe("platform spec index", function () { + it("includes module according to proper object structure", function () { + var spec = require('ripple/platform/webworks.handset/2.0.0/spec'); + expect(spec.objects.blackberry.children.utils).toEqual({ + path: "webworks.core/2.0.0/client/utils", + feature: "blackberry.utils" + }); + }); + }); + }); + + describe("tablet", function () { + describe("platform spec index", function () { + it("includes module according to proper object structure", function () { + var spec = require('ripple/platform/webworks.tablet/2.0.0/spec'); + expect(spec.objects.blackberry.children.utils).toEqual({ + path: "webworks.core/2.0.0/client/utils", + feature: "blackberry.utils" + }); + }); + }); + }); + + describe("blobToString and stringToBlob", function () { + it("can translate a blob into a string and back", function () { + var blobBuilder = { + append: jasmine.createSpy(), + getBlob: jasmine.createSpy().andReturn({}) + }, + str = "da foo", + fileReader = { + readAsText: jasmine.createSpy().andCallFake(function (blob, encoding) { + fileReader.result = str; + runs(function () { + fileReader.onloadend(); + }); + }), + result: null + }, + blob; + + FileReader.andReturn(fileReader); + BlobBuilder.andReturn(blobBuilder); + + blob = utils.stringToBlob(str); + + expect(blob.uuid).toBeDefined(); + expect(utils.blobToString(blob)).toEqual(fileReader.result); + expect(fileReader.readAsText).toHaveBeenCalledWith(blob); + expect(utils.stringToBlob(str)).toEqual(blob); + expect(blobBuilder.append).toHaveBeenCalledWith(str); + }); + }); +}); From d91080c48fca9d91e80f3ed019c94c4daf53862a Mon Sep 17 00:00:00 2001 From: brent lintner Date: Thu, 1 Sep 2011 21:57:14 -0400 Subject: [PATCH 011/182] updated jasmine submodule to latest --- build/btest/test.html | 6 +++--- thirdparty/jasmine | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/btest/test.html b/build/btest/test.html index 851862ee..1536da1f 100644 --- a/build/btest/test.html +++ b/build/btest/test.html @@ -25,9 +25,9 @@ - - - + + +

- -

Join the Ripple Community

diff --git a/lib/ripple/config.js b/lib/ripple/config.js deleted file mode 100644 index f414e074..00000000 --- a/lib/ripple/config.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var exception = require('ripple/exception'), - _environmentConfiguration = { - "Production": { - "apiURL": "http://api.tinyhippos.com" - }, - - "Demo": { - "apiURL": "http://apidemo.tinyhippos.com" - }, - - "Local": { - "apiURL": "http://127.0.0.1:4567" - } - }, - _environment = "Production"; - -module.exports = { - getAPIURL: function () { - return _environmentConfiguration[_environment].apiURL; - }, - - setEnvironment: function (env) { - if (!_environmentConfiguration[env]) { - exception.raise(exception.types.Application, "No configuration found for selected environment: " + env); - } - _environment = env; - } -}; diff --git a/lib/ripple/constants.js b/lib/ripple/constants.js index 7e9b15f7..81cde9cd 100644 --- a/lib/ripple/constants.js +++ b/lib/ripple/constants.js @@ -14,6 +14,8 @@ * limitations under the License. */ module.exports = { + "API_URL": "http://api.tinyhippos.com", + "SERVICES": { "GOOGLE_MAPS_URI": "http://maps.google.com/maps/api/staticmap?size=476x476&maptype=roadmap", "GOOGLE_MAPS_API_KEY": "ABQIAAAA-CaPZHXR-0Tzhui_h6gpjhSE_2rGlnYiB7L-ZGVwgaut5s7OYRSlBAaHCzBuZf2_23_vrCOfPxXHjA" diff --git a/lib/ripple/devices.js b/lib/ripple/devices.js index 2861476b..851e5f86 100644 --- a/lib/ripple/devices.js +++ b/lib/ripple/devices.js @@ -52,7 +52,6 @@ function _currentID() { _self = module.exports = { initialize: function () { _devices = [ - "Aero", "Bold9700", "Bold9900", "FWVGA", diff --git a/lib/ripple/devices/Aero.js b/lib/ripple/devices/Aero.js deleted file mode 100644 index f044fefa..00000000 --- a/lib/ripple/devices/Aero.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011 Research In Motion Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module.exports = { - "group": "Dell", - - "id": "Areo", - "name": "Dell Aero", - "osName": "Android", - "osVersion": "1.5", - "manufacturer": "Dell", - "model": "Aero", - "uuid": "42", - "firmware": "Android", - - "screen": { - "width": 360, - "height": 640 - }, - "viewPort": { - "portrait": { - "width": 360, - "height": 640, - "paddingTop": 0, - "paddingLeft": 0 - }, - "landscape": { - "width": 640, - "height": 360, - "paddingTop": 0, - "paddingLeft": 0 - } - }, - - "browser": ["Webkit"], - "ppi": 209.8, - "platforms": ["web"], - "userAgent": "Mozilla/5.0 (Linux; U; Android 1.5; en-us; Dell Aero Build/MASTER) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1" -}; diff --git a/lib/ripple/platform/phonegap/1.0/Contact.js b/lib/ripple/platform/phonegap/1.0/Contact.js index d0844e9f..723474be 100644 --- a/lib/ripple/platform/phonegap/1.0/Contact.js +++ b/lib/ripple/platform/phonegap/1.0/Contact.js @@ -54,7 +54,7 @@ module.exports = function ( connected ) { - return ({ + return { id: id || Math.uuid(undefined, 16), displayName: displayName, name: name, @@ -99,5 +99,5 @@ module.exports = function ( copy.id = null; return copy; } - }); + }; }; diff --git a/lib/ripple/xhr/cors.js b/lib/ripple/xhr/cors.js index b197d7fa..c25c3ad7 100644 --- a/lib/ripple/xhr/cors.js +++ b/lib/ripple/xhr/cors.js @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var config = require('ripple/config'), - helpers = require('ripple/xhr/helpers'), +var helpers = require('ripple/xhr/helpers'), + constants = require('ripple/constants'), _console = require('ripple/console'), XHR = require('ripple/xhr/base'); @@ -34,8 +34,7 @@ function _XMLHttpRequest() { xhr.open = function (method, url, async, user, password) { if (!helpers.isLocalRequest(url)) { - url = config.getAPIURL() + - "/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url); + url = constants.API_URL + "/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url); } origMethods.open.apply(xhr, Array.prototype.slice.call(arguments)); diff --git a/lib/ripple/xhr/jsonp.js b/lib/ripple/xhr/jsonp.js index b1cdac81..d6f658d5 100644 --- a/lib/ripple/xhr/jsonp.js +++ b/lib/ripple/xhr/jsonp.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var config = require('ripple/config'), +var constants = require('ripple/constants'), exception = require('ripple/exception'), utils = require('ripple/utils'), helpers = require('ripple/xhr/helpers'), @@ -126,8 +126,7 @@ function _XMLHttpRequest() { }; _jxhr.onerror = xhr.onerror; - _jxhr.open(method, config.getAPIURL() + - "/jsonp_xhr_proxy?callback=?&tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url)); + _jxhr.open(method, constants.API_URL + "/jsonp_xhr_proxy?callback=?&tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url)); } }; diff --git a/package.json b/package.json index c53a7937..d3516991 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,10 @@ "name": "ripple", "version": "0.6.1", "description": "A browser based html5 mobile application development and testing tool", - "homepage": "http://github.com/blackberry/ripple", + "homepage": "http://github.com/blackberry/Rippe-UI", "author": { "name": "Research In Motion", - "url": "http://github.com/blackberry/ripple" + "url": "http://github.com/blackberry/Ripple-UI" }, "licenses": [{ "type": "Apache 2.0", diff --git a/test/assets/config/config_no_widet_node.xml b/test/assets/config/config_no_widget_node.xml similarity index 100% rename from test/assets/config/config_no_widet_node.xml rename to test/assets/config/config_no_widget_node.xml diff --git a/test/unit/phonegap/accelerometer.js b/test/unit/phonegap/accelerometer.js index 22b5b0d1..938003af 100644 --- a/test/unit/phonegap/accelerometer.js +++ b/test/unit/phonegap/accelerometer.js @@ -32,7 +32,7 @@ describe("phonegap_accelerometer", function () { }); // TODO: why does this fail when not run atomicly - xit("accelleration info is updated on AccelerometerInfoChangedEvent", function () { + xit("acceleration info is updated on AccelerometerInfoChangedEvent", function () { event.trigger("AccelerometerInfoChangedEvent", [{ x: 9.8, y: 9.8, diff --git a/test/unit/webworks.tablet/systemEvent.js b/test/unit/webworks.tablet/systemEvent.js index 214b8a17..7ba1ea00 100644 --- a/test/unit/webworks.tablet/systemEvent.js +++ b/test/unit/webworks.tablet/systemEvent.js @@ -163,7 +163,7 @@ describe("webworks.tablet system event", function () { expect(baton.pass).toHaveBeenCalledWith({code: 1, data: 3}); // state CHARGING }); - it("passes state CHARGING when charging is false", function () { + it("passes state CHARGING when charging is true", function () { var baton = new MockBaton(); server.deviceBatteryStateChange({}, {}, baton); event.trigger("DeviceBatteryStateChanged", [true], true); diff --git a/test/unit/widgetConfig.js b/test/unit/widgetConfig.js index 4d0da390..ff704820 100644 --- a/test/unit/widgetConfig.js +++ b/test/unit/widgetConfig.js @@ -87,12 +87,8 @@ describeBrowser("widgetConfig", function () { }); it("config_file_validation_returns_returns_proper_nodes_as_being_validated", function () { - var configXML, - result; - - configXML = _getConfig("config.xml"); - - result = widgetConfig.validate(configXML).widget; + var configXML = _getConfig("config.xml"), + result = widgetConfig.validate(configXML).widget; expect(result.validationResult[0].valid).toEqual(true); expect(result.children["name"].validationResult[0].valid).toEqual(true); @@ -103,12 +99,8 @@ describeBrowser("widgetConfig", function () { }); it("config_file_validation_validates_for_required_widget_and_icon_nodes", function () { - var configXML, - result; - - configXML = _getConfig("config_no_widet_node.xml"); - - result = widgetConfig.validate(configXML).widget; + var configXML = _getConfig("config_no_widget_node.xml"), + result = widgetConfig.validate(configXML).widget; expect(result).toBeTruthy(); expect(result.validationResult[0].message).toEqual("widget node expected, but not found"); diff --git a/thirdparty/node-XMLHttpRequest b/thirdparty/node-XMLHttpRequest index fdcdd8a9..13d0ef11 160000 --- a/thirdparty/node-XMLHttpRequest +++ b/thirdparty/node-XMLHttpRequest @@ -1 +1 @@ -Subproject commit fdcdd8a9e82a85611aa56d83b871076134a242e4 +Subproject commit 13d0ef11c228692e8349d1f545ba0010cff04908 From 3561ad5a755232c3e0a8ee01a11736a9dedfce69 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Sat, 27 Aug 2011 14:57:03 -0400 Subject: [PATCH 017/182] linting (and tweaks surrounding it) --- .csslintrc | 5 --- Jakefile | 2 +- build/btest.js | 8 +++-- build/lint.js | 4 +-- ext/assets/styles/main.css | 47 +++++++++++++++++++++------- lib/ripple/devices/Bold9700/skin.css | 8 +++-- lib/ripple/devices/Bold9900/skin.css | 8 +++-- lib/ripple/devices/Playbook/skin.css | 4 +++ lib/ripple/devices/Torch/skin.css | 22 +++++++------ 9 files changed, 71 insertions(+), 37 deletions(-) diff --git a/.csslintrc b/.csslintrc index 62b686be..9a5e3bb4 100644 --- a/.csslintrc +++ b/.csslintrc @@ -1,13 +1,8 @@ [ - "unique-headings", - "qualified-headings", - "ids", - "font-sizes", "floats", "overqualified-elements", "zero-units", "universal-selector", - "regex-selectors", "import", "font-faces", "vendor-prefix", diff --git a/Jakefile b/Jakefile index 46d0b7ed..137e6931 100644 --- a/Jakefile +++ b/Jakefile @@ -30,7 +30,7 @@ task('test', [], function () { desc("boot test server for running all tests in the browser"); task('btest', [], require('./build/btest')); -desc("runs jshint + csslint - jake lint [path1,path2]"); +desc("runs jshint + csslint - jake lint [path1] [path2]"); task('lint', [], function () { require('./build/lint')(complete, Array.prototype.slice.call(arguments)); }, true); diff --git a/build/btest.js b/build/btest.js index e851481e..7c366845 100644 --- a/build/btest.js +++ b/build/btest.js @@ -20,6 +20,10 @@ module.exports = function () { utils = require('./build/utils'), libs = [], tests = [], + html = fs.readFileSync(__dirname + "/btest/test.html", "utf-8"), + doc, + modules, + specs, app = connect( connect.static(__dirname + "/../lib/"), connect.static(__dirname + "/../"), @@ -32,9 +36,7 @@ module.exports = function () { res.end(doc); }); }) - ), - html = fs.readFileSync(__dirname + "/btest/test.html", "utf-8"), - doc, modules, specs; + ); utils.collect(__dirname + "/../lib", libs); utils.collect(__dirname + "/../test", tests); diff --git a/build/lint.js b/build/lint.js index 8f4da9d3..af4b7460 100644 --- a/build/lint.js +++ b/build/lint.js @@ -33,12 +33,12 @@ function _lintJS(files, done) { function _lintCSS(files, done) { var rules = JSON.parse(fs.readFileSync(__dirname + "/../.csslintrc", "utf-8")), - options = ["--rules=" + rules, "--format=compact", "ext", "lib", "test"]; + options = ["--rules=" + rules, "--format=compact"]; _spawn('csslint', files.concat(options), done); } module.exports = function (done, files) { _lintJS(files && files.length > 0 ? files : ["."], function () { - _lintCSS(files && files.length > 0 ? files : ["ext", "lib", "test"], done); + _lintCSS(files && files.length > 0 ? files : ["ext/assets/styles", "lib", "test"], done); }); }; diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index 0a2548ab..df851145 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -77,6 +77,7 @@ input, textarea, keygen, select, button, isindex, datagrid { .main input[type^=text], .main input[type^=number], .main select, .main textarea { -webkit-appearance: none; + -moz-appearance: none; padding: 0.4em 1em !important; } @@ -137,7 +138,7 @@ section, header, footer, aside, nav { display: block; } /* ------------------------------> Middle/Device Wrapper Section */ -section.middle{ +.middle{ margin: 0 auto; top: 75px; position: relative; @@ -175,7 +176,7 @@ section.middle{ section.right, section.left{ position: absolute; - top: 0px; + top: 0; min-height: 100%; padding: 0; width: 344px; @@ -334,6 +335,12 @@ section.left { left: 0; } -webkit-box-orient: horizontal; -webkit-box-pack: center; -webkit-box-align: center; + -moz-box-orient: horizontal; + -moz-box-pack: center; + -moz-box-align: center; + -ms-box-orient: horizontal; + -ms-box-pack: center; + -ms-box-align: center; overflow-y: auto; background: rgba(0, 0, 0, 0.25); } @@ -345,6 +352,8 @@ section.left { left: 0; } overflow: hidden; color: #FFF; -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; background: rgba(0,0,0,1.0); } @@ -364,6 +373,8 @@ section.left { left: 0; } .overlay-dialog-buttons > input{ -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; margin: 5px; } @@ -386,17 +397,22 @@ section.left { left: 0; } overflow-y: auto; color: #FFF; -webkit-border-top-right-radius: 8px; + border-top-right-radius: 8px; background: rgba(0,0,0,1.0); } .overlay-menu-box::-webkit-scrollbar { width: 0.50ex; -webkit-border-radius: 1ex; + -moz-border-radius: 1ex; + border-radius: 1ex; } .overlay-menu-box::-webkit-scrollbar-thumb { background: #0f55ad; - -webkit-border-radius: 1ex; + -webkit-border-radius: 1ex; + -moz-border-radius: 1ex; + border-radius: 1ex; } .overlay-menu-item, .overlay-menu-item-default { @@ -429,9 +445,9 @@ section.left { left: 0; } left: 30%; padding: .5em 1em; font-size: 0.92em; - -webkit-box-shadow: 0px 1px 10px rgb(0,0,0); - -moz-box-shadow: 0px 1px 10px rgb(0,0,0); - box-shadow: 0px 1px 10px rgb(0,0,0); + -webkit-box-shadow: 0 1px 10px rgb(0,0,0); + -moz-box-shadow: 0 1px 10px rgb(0,0,0); + box-shadow: 0 1px 10px rgb(0,0,0); z-index: 1100; } @@ -442,6 +458,7 @@ section.left { left: 0; } cursor: pointer; padding: 3px 5px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; border-radius: 6px; } @@ -466,6 +483,9 @@ section.left { left: 0; } #layout-landscape { -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); transform: rotate(-90deg); } @@ -516,6 +536,8 @@ section.left { left: 0; } color: #000; background-color: rgba(180,180,180,0.7); -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; padding: 5px; } @@ -615,9 +637,6 @@ section.left { left: 0; } font-weight: bold; } -.information-widgetversion { -} - #emulator-booting { position: absolute; width: 100%; @@ -674,6 +693,8 @@ section.left { left: 0; } background: #1e1e1e; border: solid rgba(204, 204, 204, 0.9); -webkit-box-shadow: 0 0 15px rgba(153, 153, 153, 0.75); + -moz-box-shadow: 0 0 15px rgba(153, 153, 153, 0.75); + box-shadow: 0 0 15px rgba(153, 153, 153, 0.75); } .viewport-wrapper { @@ -715,7 +736,7 @@ section.left { left: 0; } width: 100%; height: 100%; position: absolute; - top: 0px; + top: 0; text-align:center; vertical-align: middle; display: none; @@ -779,7 +800,7 @@ section.left { left: 0; } width: 100%; height: 100%; position: absolute; - top: 0px; + top: 0; text-align:center; vertical-align: middle; display: none; @@ -834,6 +855,8 @@ section.left { left: 0; } ::-webkit-resizer { -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; background-color: #333333; } @@ -842,6 +865,8 @@ section.left { left: 0; } min-width: 0.8em; margin: 0 .25em; -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; background-color: #333333; } diff --git a/lib/ripple/devices/Bold9700/skin.css b/lib/ripple/devices/Bold9700/skin.css index 4762c6cc..301bae1e 100644 --- a/lib/ripple/devices/Bold9700/skin.css +++ b/lib/ripple/devices/Bold9700/skin.css @@ -17,8 +17,8 @@ Bold9700 (561x1009) offset (40x181)*/ .viewport-wrapper-Bold9700 { - width:480px; - height:360px; + width: 480px; + height: 360px; border: none; } @@ -44,9 +44,11 @@ position: relative; padding: 181px 0 0 40px; width: 521px; - height:828px; + height: 828px; margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Bold9700.png') no-repeat; } diff --git a/lib/ripple/devices/Bold9900/skin.css b/lib/ripple/devices/Bold9900/skin.css index a4f3e174..5b4f1231 100644 --- a/lib/ripple/devices/Bold9900/skin.css +++ b/lib/ripple/devices/Bold9900/skin.css @@ -17,8 +17,8 @@ Bold9900 (726x1258) offset (41x196)*/ .viewport-wrapper-Bold9900 { - width:640px; - height:480px; + width: 640px; + height: 480px; border: none; } @@ -44,9 +44,11 @@ position: relative; padding: 196px 0 0 41px; width: 685px; - height:1062px; + height: 1062px; margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Bold9900.png') no-repeat; } diff --git a/lib/ripple/devices/Playbook/skin.css b/lib/ripple/devices/Playbook/skin.css index 8feecd90..cb740314 100644 --- a/lib/ripple/devices/Playbook/skin.css +++ b/lib/ripple/devices/Playbook/skin.css @@ -30,6 +30,8 @@ margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Playbook_landscape.png') no-repeat; } @@ -48,5 +50,7 @@ margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Playbook.png') no-repeat; } diff --git a/lib/ripple/devices/Torch/skin.css b/lib/ripple/devices/Torch/skin.css index 4c870efa..8365324c 100644 --- a/lib/ripple/devices/Torch/skin.css +++ b/lib/ripple/devices/Torch/skin.css @@ -16,20 +16,23 @@ /* ------------------------------> Torch Skin (444x779) offset (40x142)*/ + .viewport-wrapper-Torch { - width:360px; - height:480px; + width: 360px; + height: 480px; border: none; } .device-wrapper-Torch { position: relative; padding: 142px 0 0 40px; - width:404px; - height:637px; + width: 404px; + height: 637px; margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Torch.png') no-repeat; } @@ -53,20 +56,21 @@ .viewport-wrapper-landscape-Torch { margin: -99px 0 0 103px; - width:480px; - height:360px; + width: 480px; + height: 360px; border: none; } - .device-wrapper-landscape-Torch { position: relative; padding: 142px 0 0 40px; - width:739px; - height:302px; + width: 739px; + height: 302px; margin: 0 auto; border: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; background: url('../images/Torch_landscape.png') no-repeat; } From 4a8af2841c8745d21ff00d82add32545429771aa Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 6 Sep 2011 13:17:36 -0400 Subject: [PATCH 018/182] added csslint to configure script --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 5eebde04..10c915d5 100755 --- a/configure +++ b/configure @@ -1,4 +1,4 @@ -npm install -g jake jshint uglify-js +npm install -g jake jshint csslint@0.5.0 uglify-js npm install jsdom sinon jasmine-node jWorkflow connect argsparser git submodule init git submodule update From af61b678d85bc781fd22e097099c109c35411eda Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 7 Sep 2011 15:54:42 -0400 Subject: [PATCH 019/182] Added bb.app.system.onSwipeDown & onSwipeStart for Tablet (triggerable from events pane) Added the ability to trigger bb.app.event.onBackground & onForeground from event pane. --- .../webworks.core/2.0.0/spec/events.js | 15 ++++++ .../webworks.tablet/2.0.0/client/appEvent.js | 4 +- .../webworks.tablet/2.0.0/server/appEvent.js | 26 +++++++++++ .../platform/webworks.tablet/2.0.0/spec.js | 2 +- .../webworks.tablet/2.0.0/spec/events.js | 42 +++++++++++++++++ test/unit/webworks.tablet/appEvent.js | 46 ++++++++++++++++--- 6 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js index 4fcd3c3f..7bc891a8 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js @@ -38,6 +38,21 @@ module.exports = { } }, "context": "blackberry.system.event" + }, + "appEvent": { + "events": { + "AppRequestBackground": { + name: "AppRequestBackground", + description: "onBackground", + args: false + }, + "AppRequestForeground": { + name: "AppRequestForeground", + description: "onForeground", + args: false + } + }, + "context": "blackberry.app.event" } } }; diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/client/appEvent.js b/lib/ripple/platform/webworks.tablet/2.0.0/client/appEvent.js index a213cbf1..05a35fd9 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/client/appEvent.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/client/appEvent.js @@ -41,11 +41,11 @@ _self = { }, onSwipeDown: function (handler) { - throw "not implemented"; + _poll("onSwipeDown", handler); }, onSwipeStart: function (handler) { - throw "not implemented"; + _poll("onSwipeStart", handler); } }; diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/server/appEvent.js b/lib/ripple/platform/webworks.tablet/2.0.0/server/appEvent.js index 16c00607..90b35c13 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/server/appEvent.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/server/appEvent.js @@ -16,6 +16,8 @@ var event = require('ripple/event'), _bg, _fg, + _swipeDown, + _swipeStart, _exit; event.on("AppRequestBackground", function () { @@ -30,6 +32,18 @@ event.on("AppRequestForeground", function () { return baton && baton.pass({code: 1}); }); +event.on("AppSwipeDown", function () { + var baton = _swipeDown; + _swipeDown = null; + return baton && baton.pass({code: 1}); +}); + +event.on("AppSwipeStart", function () { + var baton = _swipeStart; + _swipeStart = null; + return baton && baton.pass({code: 1}); +}); + module.exports = { onBackground: function (get, post, baton) { baton.take(); @@ -41,5 +55,17 @@ module.exports = { baton.take(); _fg = baton; return {code: 1}; + }, + + onSwipeDown: function (get, post, baton) { + baton.take(); + _swipeDown = baton; + return {code: 1}; + }, + + onSwipeStart: function (get, post, baton) { + baton.take(); + _swipeStart = baton; + return {code: 1}; } }; diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/spec.js b/lib/ripple/platform/webworks.tablet/2.0.0/spec.js index c5127ea3..88de5a88 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/spec.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/spec.js @@ -24,7 +24,7 @@ module.exports = { ui: require('ripple/platform/webworks.core/2.0.0/spec/ui'), device: require('ripple/platform/webworks.tablet/2.0.0/spec/device'), config: require('ripple/platform/webworks.core/2.0.0/spec/config'), - events: require('ripple/platform/webworks.core/2.0.0/spec/events'), + events: require('ripple/platform/webworks.tablet/2.0.0/spec/events'), objects: { XMLHttpRequest: { diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js b/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js new file mode 100644 index 00000000..e0d1aeab --- /dev/null +++ b/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js @@ -0,0 +1,42 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var _self, + utils = require('ripple/utils'), + events = utils.copy(require('ripple/platform/webworks.core/2.0.0/spec/events')); + +_self = { + "contexts": { + "appEvent": { + "events": { + "AppSwipeDown": { + name: "AppSwipeDown", + description: "onSwipeDown", + args: false + }, + "AppSwipeStart": { + name: "AppSwipeStart", + description: "onSwipeStart", + args: false + } + }, + "context": "blackberry.app.event" + } + } +}; + +utils.mixin(_self.contexts.appEvent.events, events.contexts.appEvent.events); + +module.exports = events; diff --git a/test/unit/webworks.tablet/appEvent.js b/test/unit/webworks.tablet/appEvent.js index 9ff751a9..08390f83 100644 --- a/test/unit/webworks.tablet/appEvent.js +++ b/test/unit/webworks.tablet/appEvent.js @@ -46,14 +46,22 @@ describe("webworks_appEvent", function () { }); describe("onSwipeStart", function () { - it("throws an exception", function () { - expect(client.onSwipeStart).toThrow("not implemented"); + it("polls the transport appropriately", function () { + spyOn(transport, "poll"); + client.onSwipeStart(null); + expect(transport.poll.argsForCall[0][0]).toEqual("blackberry/app/event/onSwipeStart"); + expect(transport.poll.argsForCall[0][1]).toEqual({}); + expect(typeof transport.poll.argsForCall[0][2]).toEqual("function"); // could tighten... }); }); describe("onSwipeDown", function () { - it("throws an exception", function () { - expect(client.onSwipeDown).toThrow("not implemented"); + it("polls the transport appropriately", function () { + spyOn(transport, "poll"); + client.onSwipeDown(null); + expect(transport.poll.argsForCall[0][0]).toEqual("blackberry/app/event/onSwipeDown"); + expect(transport.poll.argsForCall[0][1]).toEqual({}); + expect(typeof transport.poll.argsForCall[0][2]).toEqual("function"); // could tighten... }); }); @@ -77,13 +85,35 @@ describe("webworks_appEvent", function () { }); }); + describe("onSwipeDown", function () { + it("takes the baton", function () { + var baton = new MockBaton(); + + appEvent.onSwipeDown({}, {}, baton); + expect(baton.take).toHaveBeenCalled(); + }); + }); + + describe("onSwipeStart", function () { + it("takes the baton", function () { + var baton = new MockBaton(); + + appEvent.onSwipeStart({}, {}, baton); + expect(baton.take).toHaveBeenCalled(); + }); + }); + describe("the correct baton is passed when", function () { it("raises AppRequestBackground", function () { var bg = new MockBaton(), - fg = new MockBaton(); + fg = new MockBaton(), + sd = new MockBaton(), + ss = new MockBaton(); appEvent.onBackground({}, {}, bg); appEvent.onForeground({}, {}, fg); + appEvent.onSwipeDown({}, {}, sd); + appEvent.onSwipeStart({}, {}, ss); event.trigger("AppRequestBackground", [], true); expect(bg.pass).toHaveBeenCalled(); @@ -92,10 +122,14 @@ describe("webworks_appEvent", function () { it("raises AppRequestForeground", function () { var bg = new MockBaton(), - fg = new MockBaton(); + fg = new MockBaton(), + sd = new MockBaton(), + ss = new MockBaton(); appEvent.onBackground({}, {}, bg); appEvent.onForeground({}, {}, fg); + appEvent.onSwipeDown({}, {}, sd); + appEvent.onSwipeStart({}, {}, ss); event.trigger("AppRequestForeground", [], true); expect(bg.pass).not.toHaveBeenCalled(); From 045937744f67d6c5994c050bf61e4235b649c4b1 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 7 Sep 2011 15:48:49 -0400 Subject: [PATCH 020/182] refactored spec/events schema --- .../webworks.core/2.0.0/spec/events.js | 69 +++++------ lib/ripple/ui/plugins/platformEvents.js | 110 ++++++------------ .../ui/plugins/platformEvents/panel.html | 10 +- 3 files changed, 72 insertions(+), 117 deletions(-) diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js index 7bc891a8..049e7d20 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js @@ -13,46 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +var event = require('ripple/event'); + module.exports = { - "contexts": { - "systemEvent": { - "events": { - "CoverageChange": { - name: "CoverageChange", - description: "onCoverageChange", - args: false - }, - "HardwareKey": { - name: "HardwareKey", - description: "onHardwareKey", - args: [ - "Back", - "Menu", - "Convenience 1", - "Convenience 2", - "Start Call", - "End Call", - "Volume Down", - "Volume Up" - ] - } - }, - "context": "blackberry.system.event" - }, - "appEvent": { - "events": { - "AppRequestBackground": { - name: "AppRequestBackground", - description: "onBackground", - args: false - }, - "AppRequestForeground": { - name: "AppRequestForeground", - description: "onForeground", - args: false - } - }, - "context": "blackberry.app.event" + "app.event.onBackground": { + callback: function () { + event.trigger("AppRequestBackground"); + } + }, + "app.event.onForeground": { + callback: function () { + event.trigger("AppRequestForeground"); + } + }, + "system.event.CoverageChange": { + callback: function () { + event.trigger("CoverageChange"); + } + }, + "system.event.HardwareKey": { + args: [ + "Back", + "Menu", + "Convenience 1", + "Convenience 2", + "Start Call", + "End Call", + "Volume Down", + "Volume Up" + ], + callback: function (key) { + event.trigger("HardwareKey", [key]); } } }; diff --git a/lib/ripple/ui/plugins/platformEvents.js b/lib/ripple/ui/plugins/platformEvents.js index 4c03ad21..a68c2241 100644 --- a/lib/ripple/ui/plugins/platformEvents.js +++ b/lib/ripple/ui/plugins/platformEvents.js @@ -21,99 +21,57 @@ var _console = require('ripple/console'), module.exports = { panel: { - domId: "events-container", + domId: "platform-events-container", collapsed: true, pane: "right" }, initialize: function () { - var eventContainer = document.getElementById("event-container"), - // TODO: modify to platform.getPlatformEvents() - spec = platform.current(), - eventSelect, eventArgs, events, fireEventButton; + var eventSelect = document.getElementById("platform-events-select"), + spec = platform.current(); if (!spec.events) { return; } - utils.forEach(spec.events.contexts, function (eventContext, name) { - - eventSelect = utils.createElement("select", { - "id": "events-select-" + name, - "class": "ui-state-default ui-corner-all" - }); - - eventArgs = utils.createElement("select", { - id: "events-args-" + name, - "class": "ui-state-default ui-corner-all" - }); - - events = eventContext.events; - - utils.forEach(events, function (event) { - eventSelect.appendChild(utils.createElement("option", { - "innerText": event.description, - "value": event.name - })); - }); - - fireEventButton = utils.createElement("button", { - "id": "event-button-" + name, - "class": "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" - }); - - fireEventButton.appendChild(utils.createElement("span", { - "class": "ui-button-text", - "innerText": "Fire Event" + utils.forEach(spec.events, function (method, name) { + eventSelect.appendChild(utils.createElement("option", { + "innerText": name, + "value": name })); + }); - eventContainer.appendChild(utils.createElement("p", { - "innerText": "Context = " + eventContext.context - })); - eventContainer.appendChild(eventSelect); - eventContainer.appendChild(eventArgs); - eventContainer.appendChild(utils.createElement("br")); - eventContainer.appendChild(fireEventButton); - - jQuery(eventArgs).hide(); - - jQuery(fireEventButton).click(function () { - var select = jQuery("#" + eventSelect.id)[0], - args = []; - - if (events[select.value].args) { - args.push(eventArgs.value); - } - _console.log("fired event => " + eventContext.context + "." + select.children[select.selectedIndex].innerText); - try { - event.trigger(select.value, args); - } - catch (e) { - exception.throwMaskedException(e); - } - }); - - jQuery(eventSelect).change(function () { - var args = jQuery(eventArgs); + jQuery("#platform-events-fire").click(function () { + var eventName = document.getElementById("platform-events-select").value, + args = spec.events[eventName].args ? document.getElementById("platform-events-args").value : null, + callback = spec.events[eventName].callback; - args.empty(); + _console.log("fired event => " + eventName); - if (events[this.value].args) { + try { + callback(args); + } catch (e) { + exception.throwMaskedException(e); + } + }); - utils.forEach(events[this.value].args, function (arg, index) { - eventArgs.appendChild(utils.createElement("option", { - innerText: arg, - value: index - })); - }); + jQuery(eventSelect).change(function () { + var argsSelect = jQuery("#platform-events-args"), + args = spec.events[this.value].args; - args.show(); - } - else { - args.hide(); - } + argsSelect.empty(); - }); + if (args) { + utils.forEach(spec.events[this.value].args, function (arg, index) { + argsSelect.append(utils.createElement("option", { + innerText: arg, + value: index + })); + }); + argsSelect.show(); + } else { + argsSelect.hide(); + } }); } }; diff --git a/lib/ripple/ui/plugins/platformEvents/panel.html b/lib/ripple/ui/plugins/platformEvents/panel.html index 559450a4..65887e6a 100644 --- a/lib/ripple/ui/plugins/platformEvents/panel.html +++ b/lib/ripple/ui/plugins/platformEvents/panel.html @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. --> -
+
Events
@@ -21,7 +21,13 @@
- From 6c2d0b47527c2841446da175d69a7f6e57d6af0f Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 7 Sep 2011 15:52:06 -0400 Subject: [PATCH 021/182] support manuallly firing events in the PhoneGap Events API --- lib/ripple/platform/phonegap/1.0/spec.js | 1 + .../platform/phonegap/1.0/spec/events.js | 34 +++++++++ lib/ripple/platform/phonegap/1.0/spec/ui.js | 3 +- test/unit/phonegap/events.js | 73 +++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 lib/ripple/platform/phonegap/1.0/spec/events.js create mode 100644 test/unit/phonegap/events.js diff --git a/lib/ripple/platform/phonegap/1.0/spec.js b/lib/ripple/platform/phonegap/1.0/spec.js index bdd951fa..05d21228 100644 --- a/lib/ripple/platform/phonegap/1.0/spec.js +++ b/lib/ripple/platform/phonegap/1.0/spec.js @@ -9,6 +9,7 @@ module.exports = { config: require('ripple/platform/phonegap/1.0/spec/config'), device: require('ripple/platform/phonegap/1.0/spec/device'), ui: require('ripple/platform/phonegap/1.0/spec/ui'), + events: require('ripple/platform/phonegap/1.0/spec/events'), objects: { PhoneGap: { diff --git a/lib/ripple/platform/phonegap/1.0/spec/events.js b/lib/ripple/platform/phonegap/1.0/spec/events.js new file mode 100644 index 00000000..5724d95c --- /dev/null +++ b/lib/ripple/platform/phonegap/1.0/spec/events.js @@ -0,0 +1,34 @@ +function _fires(name, data) { + return function () { + var evt = document.createEvent("Events"); + evt.initEvent(name, true, false); + document.dispatchEvent(evt); + }; +} + +module.exports = { + "deviceready": { + callback: _fires("deviceready") + }, + "backbutton": { + callback: _fires("backbutton") + }, + "menubutton": { + callback: _fires("menubutton") + }, + "pause": { + callback: _fires("pause") + }, + "resume": { + callback: _fires("resume") + }, + "searchbutton": { + callback: _fires("searchbutton") + }, + "online": { + callback: _fires("online") + }, + "offline": { + callback: _fires("offline") + } +}; diff --git a/lib/ripple/platform/phonegap/1.0/spec/ui.js b/lib/ripple/platform/phonegap/1.0/spec/ui.js index 8de321a0..4ff34941 100644 --- a/lib/ripple/platform/phonegap/1.0/spec/ui.js +++ b/lib/ripple/platform/phonegap/1.0/spec/ui.js @@ -18,6 +18,7 @@ module.exports = { "accelerometer", "deviceSettings", "geoView", - "widgetConfig" + "widgetConfig", + "platformEvents" ] }; diff --git a/test/unit/phonegap/events.js b/test/unit/phonegap/events.js new file mode 100644 index 00000000..266855e7 --- /dev/null +++ b/test/unit/phonegap/events.js @@ -0,0 +1,73 @@ +describe("phonegap events", function () { + var spec = require('ripple/platform/phonegap/1.0/spec'), + events = spec.events; + + function _expectsEventToFire(name) { + var evt = {initEvent: jasmine.createSpy()}; + + spyOn(document, "createEvent").andReturn(evt); + spyOn(document, "dispatchEvent"); + + events[name].callback(); + + expect(document.createEvent).toHaveBeenCalledWith("Events"); + expect(evt.initEvent).toHaveBeenCalledWith(name, true, false); + expect(document.dispatchEvent).toHaveBeenCalledWith(evt); + } + + describe("spec/ui", function () { + it("includes the platformEvents ui plugin", function () { + expect(spec.ui.plugins.some(function (plugin) { + return plugin === "platformEvents"; + })).toBe(true); + }); + }); + + describe("deviceready", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("deviceready"); + }); + }); + + describe("backbutton", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("backbutton"); + }); + }); + + describe("menubutton", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("menubutton"); + }); + }); + + describe("pause", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("pause"); + }); + }); + + describe("resume", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("resume"); + }); + }); + + describe("searchbutton", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("searchbutton"); + }); + }); + + describe("online", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("online"); + }); + }); + + describe("offline", function () { + it("fires respective event off the document", function () { + _expectsEventToFire("offline"); + }); + }); +}); From 92a8dc41d8986a038504f507caaaf50362b7989d Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 7 Sep 2011 17:04:29 -0400 Subject: [PATCH 022/182] refactored new spec/events schemas, moved webworks.handset only events into its own spec/ --- .../webworks.core/2.0.0/spec/events.js | 20 -------- .../platform/webworks.handset/2.0.0/spec.js | 2 +- .../webworks.handset/2.0.0/spec/events.js | 46 +++++++++++++++++++ .../webworks.tablet/2.0.0/spec/events.js | 28 +++++------ test/unit/webworks.tablet/systemEvent.js | 21 ++++++++- test/unit/webworks/systemEvent.js | 45 +++++++++++++++++- 6 files changed, 122 insertions(+), 40 deletions(-) create mode 100644 lib/ripple/platform/webworks.handset/2.0.0/spec/events.js diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js index 049e7d20..91f09faa 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/events.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/events.js @@ -25,25 +25,5 @@ module.exports = { callback: function () { event.trigger("AppRequestForeground"); } - }, - "system.event.CoverageChange": { - callback: function () { - event.trigger("CoverageChange"); - } - }, - "system.event.HardwareKey": { - args: [ - "Back", - "Menu", - "Convenience 1", - "Convenience 2", - "Start Call", - "End Call", - "Volume Down", - "Volume Up" - ], - callback: function (key) { - event.trigger("HardwareKey", [key]); - } } }; diff --git a/lib/ripple/platform/webworks.handset/2.0.0/spec.js b/lib/ripple/platform/webworks.handset/2.0.0/spec.js index a4c33be2..7fad5dba 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/spec.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/spec.js @@ -24,7 +24,7 @@ module.exports = { ui: require('ripple/platform/webworks.core/2.0.0/spec/ui'), device: require('ripple/platform/webworks.handset/2.0.0/spec/device'), config: require('ripple/platform/webworks.core/2.0.0/spec/config'), - events: require('ripple/platform/webworks.core/2.0.0/spec/events'), + events: require('ripple/platform/webworks.handset/2.0.0/spec/events'), objects: { XMLHttpRequest: { diff --git a/lib/ripple/platform/webworks.handset/2.0.0/spec/events.js b/lib/ripple/platform/webworks.handset/2.0.0/spec/events.js new file mode 100644 index 00000000..c675d28f --- /dev/null +++ b/lib/ripple/platform/webworks.handset/2.0.0/spec/events.js @@ -0,0 +1,46 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var _self, + utils = require('ripple/utils'), + event = require('ripple/event'), + events = utils.copy(require('ripple/platform/webworks.core/2.0.0/spec/events')); + +_self = { + "system.event.onCoverageChange": { + callback: function () { + event.trigger("CoverageChange"); + } + }, + "system.event.onHardwareKey": { + args: [ + "Back", + "Menu", + "Convenience 1", + "Convenience 2", + "Start Call", + "End Call", + "Volume Down", + "Volume Up" + ], + callback: function (key) { + event.trigger("HardwareKey", [key]); + } + } +}; + +utils.mixin(events, _self); + +module.exports = _self; diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js b/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js index e0d1aeab..178aa493 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/spec/events.js @@ -15,28 +15,22 @@ */ var _self, utils = require('ripple/utils'), + event = require('ripple/event'), events = utils.copy(require('ripple/platform/webworks.core/2.0.0/spec/events')); _self = { - "contexts": { - "appEvent": { - "events": { - "AppSwipeDown": { - name: "AppSwipeDown", - description: "onSwipeDown", - args: false - }, - "AppSwipeStart": { - name: "AppSwipeStart", - description: "onSwipeStart", - args: false - } - }, - "context": "blackberry.app.event" + "app.event.onSwipeDown": { + callback: function () { + event.trigger("AppSwipeDown"); + } + }, + "app.event.onSwipeStart": { + callback: function () { + event.trigger("AppSwipeStart"); } } }; -utils.mixin(_self.contexts.appEvent.events, events.contexts.appEvent.events); +utils.mixin(events, _self); -module.exports = events; +module.exports = _self; diff --git a/test/unit/webworks.tablet/systemEvent.js b/test/unit/webworks.tablet/systemEvent.js index 7ba1ea00..c39bc3ad 100644 --- a/test/unit/webworks.tablet/systemEvent.js +++ b/test/unit/webworks.tablet/systemEvent.js @@ -25,12 +25,31 @@ describe("webworks.tablet system event", function () { }; describe("platform spec", function () { + var spec = require('ripple/platform/webworks.tablet/2.0.0/spec'); + // NOTE: system and system.event for Playbook do not require feature declarations (see docs) it("includes the module according to proper object structure", function () { - var spec = require('ripple/platform/webworks.tablet/2.0.0/spec'); expect(spec.objects.blackberry.children.system.children.event.path) .toEqual("webworks.tablet/2.0.0/client/systemEvent"); }); + + describe("events", function () { + describe("app.event.onSwipeDown callback", function () { + it("triggers AppSwipeDown", function () { + spyOn(event, "trigger"); + spec.events["app.event.onSwipeDown"].callback(); + expect(event.trigger).toHaveBeenCalledWith("AppSwipeDown"); + }); + }); + + describe("app.event.onSwipeStart callback", function () { + it("triggers AppSwipeStart", function () { + spyOn(event, "trigger"); + spec.events["app.event.onSwipeStart"].callback(); + expect(event.trigger).toHaveBeenCalledWith("AppSwipeStart"); + }); + }); + }); }); describe("server index", function () { diff --git a/test/unit/webworks/systemEvent.js b/test/unit/webworks/systemEvent.js index 5265f078..06364d68 100644 --- a/test/unit/webworks/systemEvent.js +++ b/test/unit/webworks/systemEvent.js @@ -23,6 +23,49 @@ describe("webworks.handset system event", function () { this.pass = jasmine.createSpy('baton.pass'); }; + describe("core platform spec", function () { + var events = require('ripple/platform/webworks.core/2.0.0/spec/events'); + + describe("events", function () { + describe("app.event.onBackground callback", function () { + it("triggers AppSwipeDown", function () { + spyOn(event, "trigger"); + events["app.event.onBackground"].callback(); + expect(event.trigger).toHaveBeenCalledWith("AppRequestBackground"); + }); + }); + + describe("app.event.onForeground callback", function () { + it("triggers AppSwipeStart", function () { + spyOn(event, "trigger"); + events["app.event.onForeground"].callback(); + expect(event.trigger).toHaveBeenCalledWith("AppRequestForeground"); + }); + }); + }); + }); + + describe("handset platform spec", function () { + describe("events", function () { + var events = require('ripple/platform/webworks.handset/2.0.0/spec').events; + + describe("system.event.onHardwareKey callback", function () { + it("triggers HardwareKey", function () { + spyOn(event, "trigger"); + events["system.event.onHardwareKey"].callback(2); + expect(event.trigger).toHaveBeenCalledWith("HardwareKey", [2]); + }); + }); + + describe("system.event.onCoverageChange callback", function () { + it("triggers CoverageChange", function () { + spyOn(event, "trigger"); + events["system.event.onCoverageChange"].callback(); + expect(event.trigger).toHaveBeenCalledWith("CoverageChange"); + }); + }); + }); + }); describe("using server", function () { it("exposes the system event module", function () { var webworks = require('ripple/platform/webworks.handset/2.0.0/server'); @@ -64,7 +107,7 @@ describe("webworks.handset system event", function () { expect(baton.take).toHaveBeenCalled(); }); - it("passes the baton when CoverageChanged is raised", function () { + it("passes the baton when CoverageChange is raised", function () { var baton = new MockBaton(); sysEvent.onCoverageChange({}, {}, baton); event.trigger("CoverageChange", [], true); From 4295fd0dbaf29a8802fbde331e21a18f111ca38c Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 7 Sep 2011 21:39:17 -0400 Subject: [PATCH 023/182] removed sinon --- build/btest/test.html | 10 - configure | 2 +- test/unit/accelerometer.js | 26 +- test/unit/emulatorBridge.js | 6 - test/unit/exception.js | 234 ++- test/unit/geo.js | 108 +- test/unit/phonegap/contacts.js | 183 ++- test/unit/phonegap/notification.js | 21 +- test/unit/platform.builder.js | 34 +- test/unit/resizer.js | 25 +- test/unit/webworks/Message.js | 30 +- test/unit/webworks/invoke.js | 53 +- test/unit/webworks/sms.js | 17 +- thirdparty/sinon.js | 2447 ---------------------------- 14 files changed, 362 insertions(+), 2834 deletions(-) delete mode 100644 thirdparty/sinon.js diff --git a/build/btest/test.html b/build/btest/test.html index 1536da1f..35b80b41 100644 --- a/build/btest/test.html +++ b/build/btest/test.html @@ -72,9 +72,6 @@ }; - - - @@ -91,13 +88,6 @@ require.define('thirdparty/Math.uuid', function (require, module, exports) {}); - - - - diff --git a/build/build/conf.js b/build/build/conf.js index 3c815a4b..7a15f10d 100644 --- a/build/build/conf.js +++ b/build/build/conf.js @@ -32,7 +32,6 @@ module.exports = { "browser-require/require.js", "jquery.js", "jquery.ui.js", - "jquery.dimensions.js", "jquery.tooltip.js", "Math.uuid.js", "jXHR.js", diff --git a/build/build/web.js b/build/build/web.js index c58d8389..bb6c2305 100644 --- a/build/build/web.js +++ b/build/build/web.js @@ -17,7 +17,7 @@ var childProcess = require('child_process'), fs = require('fs'), _c = require('./conf'); -function copy(from, callback) { +function copy(from, callback) { var cmd = 'cp -r ' + from + ' ' + _c.DEPLOY + "web"; childProcess.exec(cmd, callback); } diff --git a/lib/ripple/ui/plugins/about.js b/lib/ripple/ui/plugins/about.js index eb60e702..00cd192b 100644 --- a/lib/ripple/ui/plugins/about.js +++ b/lib/ripple/ui/plugins/about.js @@ -16,7 +16,8 @@ module.exports = { initialize: function () { $("#about-dialog").dialog({ - autoOpen: false + autoOpen: false, + position: 'center' }); }, show: function () { diff --git a/thirdparty/jquery.dimensions.js b/thirdparty/jquery.dimensions.js deleted file mode 100644 index 0655c649..00000000 --- a/thirdparty/jquery.dimensions.js +++ /dev/null @@ -1,655 +0,0 @@ -/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * $LastChangedDate: 2007-08-17 13:14:11 -0500 (Fri, 17 Aug 2007) $ - * $Rev: 2759 $ - * - * Version: 1.1.2 - * - * Requires: jQuery 1.1.3+ - */ - -(function($){ - -// store a copy of the core height and width methods -var height = $.fn.height, - width = $.fn.width; - -$.fn.extend({ - /** - * If used on document, returns the document's height (innerHeight). - * If used on window, returns the viewport's (window) height. - * See core docs on height() to see what happens when used on an element. - * - * @example $("#testdiv").height() - * @result 200 - * - * @example $(document).height() - * @result 800 - * - * @example $(window).height() - * @result 400 - * - * @name height - * @type Number - * @cat Plugins/Dimensions - */ - height: function() { - if ( !this[0] ) error(); - if ( this[0] == window ) - if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) ) - return self.innerHeight - (($(document).height() > self.innerHeight) ? getScrollbarWidth() : 0); - else if ( $.browser.safari ) - return self.innerHeight; - else - return $.boxModel && document.documentElement.clientHeight || document.body.clientHeight; - - if ( this[0] == document ) - return Math.max( ($.boxModel && document.documentElement.scrollHeight || document.body.scrollHeight), document.body.offsetHeight ); - - return height.apply(this, arguments); - }, - - /** - * If used on document, returns the document's width (innerWidth). - * If used on window, returns the viewport's (window) width. - * See core docs on width() to see what happens when used on an element. - * - * @example $("#testdiv").width() - * @result 200 - * - * @example $(document).width() - * @result 800 - * - * @example $(window).width() - * @result 400 - * - * @name width - * @type Number - * @cat Plugins/Dimensions - */ - width: function() { - if (!this[0]) error(); - if ( this[0] == window ) - if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) ) - return self.innerWidth - (($(document).width() > self.innerWidth) ? getScrollbarWidth() : 0); - else if ( $.browser.safari ) - return self.innerWidth; - else - return $.boxModel && document.documentElement.clientWidth || document.body.clientWidth; - - if ( this[0] == document ) - if ($.browser.mozilla) { - // mozilla reports scrollWidth and offsetWidth as the same - var scrollLeft = self.pageXOffset; - self.scrollTo(99999999, self.pageYOffset); - var scrollWidth = self.pageXOffset; - self.scrollTo(scrollLeft, self.pageYOffset); - return document.body.offsetWidth + scrollWidth; - } - else - return Math.max( (($.boxModel && !$.browser.safari) && document.documentElement.scrollWidth || document.body.scrollWidth), document.body.offsetWidth ); - - return width.apply(this, arguments); - }, - - /** - * Gets the inner height (excludes the border and includes the padding) for the first matched element. - * If used on document, returns the document's height (innerHeight). - * If used on window, returns the viewport's (window) height. - * - * @example $("#testdiv").innerHeight() - * @result 210 - * - * @name innerHeight - * @type Number - * @cat Plugins/Dimensions - */ - innerHeight: function() { - if (!this[0]) error(); - return this[0] == window || this[0] == document ? - this.height() : - this.is(':visible') ? - this[0].offsetHeight - num(this, 'borderTopWidth') - num(this, 'borderBottomWidth') : - this.height() + num(this, 'paddingTop') + num(this, 'paddingBottom'); - }, - - /** - * Gets the inner width (excludes the border and includes the padding) for the first matched element. - * If used on document, returns the document's width (innerWidth). - * If used on window, returns the viewport's (window) width. - * - * @example $("#testdiv").innerWidth() - * @result 210 - * - * @name innerWidth - * @type Number - * @cat Plugins/Dimensions - */ - innerWidth: function() { - if (!this[0]) error(); - return this[0] == window || this[0] == document ? - this.width() : - this.is(':visible') ? - this[0].offsetWidth - num(this, 'borderLeftWidth') - num(this, 'borderRightWidth') : - this.width() + num(this, 'paddingLeft') + num(this, 'paddingRight'); - }, - - /** - * Gets the outer height (includes the border and padding) for the first matched element. - * If used on document, returns the document's height (innerHeight). - * If used on window, returns the viewport's (window) height. - * - * The margin can be included in the calculation by passing an options map with margin - * set to true. - * - * @example $("#testdiv").outerHeight() - * @result 220 - * - * @example $("#testdiv").outerHeight({ margin: true }) - * @result 240 - * - * @name outerHeight - * @type Number - * @param Map options Optional settings to configure the way the outer height is calculated. - * @cat Plugins/Dimensions - */ - outerHeight: function(options) { - if (!this[0]) error(); - options = $.extend({ margin: false }, options || {}); - return this[0] == window || this[0] == document ? - this.height() : - this.is(':visible') ? - this[0].offsetHeight + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0) : - this.height() - + num(this,'borderTopWidth') + num(this, 'borderBottomWidth') - + num(this, 'paddingTop') + num(this, 'paddingBottom') - + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0); - }, - - /** - * Gets the outer width (including the border and padding) for the first matched element. - * If used on document, returns the document's width (innerWidth). - * If used on window, returns the viewport's (window) width. - * - * The margin can be included in the calculation by passing an options map with margin - * set to true. - * - * @example $("#testdiv").outerWidth() - * @result 1000 - * - * @example $("#testdiv").outerWidth({ margin: true }) - * @result 1020 - * - * @name outerHeight - * @type Number - * @param Map options Optional settings to configure the way the outer width is calculated. - * @cat Plugins/Dimensions - */ - outerWidth: function(options) { - if (!this[0]) error(); - options = $.extend({ margin: false }, options || {}); - return this[0] == window || this[0] == document ? - this.width() : - this.is(':visible') ? - this[0].offsetWidth + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0) : - this.width() - + num(this, 'borderLeftWidth') + num(this, 'borderRightWidth') - + num(this, 'paddingLeft') + num(this, 'paddingRight') - + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0); - }, - - /** - * Gets how many pixels the user has scrolled to the right (scrollLeft). - * Works on containers with overflow: auto and window/document. - * - * @example $(window).scrollLeft() - * @result 100 - * - * @example $(document).scrollLeft() - * @result 100 - * - * @example $("#testdiv").scrollLeft() - * @result 100 - * - * @name scrollLeft - * @type Number - * @cat Plugins/Dimensions - */ - /** - * Sets the scrollLeft property for each element and continues the chain. - * Works on containers with overflow: auto and window/document. - * - * @example $(window).scrollLeft(100).scrollLeft() - * @result 100 - * - * @example $(document).scrollLeft(100).scrollLeft() - * @result 100 - * - * @example $("#testdiv").scrollLeft(100).scrollLeft() - * @result 100 - * - * @name scrollLeft - * @param Number value A positive number representing the desired scrollLeft. - * @type jQuery - * @cat Plugins/Dimensions - */ - scrollLeft: function(val) { - if (!this[0]) error(); - if ( val != undefined ) - // set the scroll left - return this.each(function() { - if (this == window || this == document) - window.scrollTo( val, $(window).scrollTop() ); - else - this.scrollLeft = val; - }); - - // return the scroll left offest in pixels - if ( this[0] == window || this[0] == document ) - return self.pageXOffset || - $.boxModel && document.documentElement.scrollLeft || - document.body.scrollLeft; - - return this[0].scrollLeft; - }, - - /** - * Gets how many pixels the user has scrolled to the bottom (scrollTop). - * Works on containers with overflow: auto and window/document. - * - * @example $(window).scrollTop() - * @result 100 - * - * @example $(document).scrollTop() - * @result 100 - * - * @example $("#testdiv").scrollTop() - * @result 100 - * - * @name scrollTop - * @type Number - * @cat Plugins/Dimensions - */ - /** - * Sets the scrollTop property for each element and continues the chain. - * Works on containers with overflow: auto and window/document. - * - * @example $(window).scrollTop(100).scrollTop() - * @result 100 - * - * @example $(document).scrollTop(100).scrollTop() - * @result 100 - * - * @example $("#testdiv").scrollTop(100).scrollTop() - * @result 100 - * - * @name scrollTop - * @param Number value A positive number representing the desired scrollTop. - * @type jQuery - * @cat Plugins/Dimensions - */ - scrollTop: function(val) { - if (!this[0]) error(); - if ( val != undefined ) - // set the scroll top - return this.each(function() { - if (this == window || this == document) - window.scrollTo( $(window).scrollLeft(), val ); - else - this.scrollTop = val; - }); - - // return the scroll top offset in pixels - if ( this[0] == window || this[0] == document ) - return self.pageYOffset || - $.boxModel && document.documentElement.scrollTop || - document.body.scrollTop; - - return this[0].scrollTop; - }, - - /** - * Gets the top and left positioned offset in pixels. - * The positioned offset is the offset between a positioned - * parent and the element itself. - * - * For accurate calculations make sure to use pixel values for margins, borders and padding. - * - * @example $("#testdiv").position() - * @result { top: 100, left: 100 } - * - * @example var position = {}; - * $("#testdiv").position(position) - * @result position = { top: 100, left: 100 } - * - * @name position - * @param Object returnObject Optional An object to store the return value in, so as not to break the chain. If passed in the - * chain will not be broken and the result will be assigned to this object. - * @type Object - * @cat Plugins/Dimensions - */ - position: function(returnObject) { - return this.offset({ margin: false, scroll: false, relativeTo: this.offsetParent() }, returnObject); - }, - - /** - * Gets the location of the element in pixels from the top left corner of the viewport. - * The offset method takes an optional map of key value pairs to configure the way - * the offset is calculated. Here are the different options. - * - * (Boolean) margin - Should the margin of the element be included in the calculations? True by default. - * (Boolean) border - Should the border of the element be included in the calculations? False by default. - * (Boolean) padding - Should the padding of the element be included in the calculations? False by default. - * (Boolean) scroll - Should the scroll offsets of the parent elements be included in the calculations? True by default. - * When true it adds the total scroll offsets of all parents to the total offset and also adds two - * properties to the returned object, scrollTop and scrollLeft. - * (Boolean) lite - When true it will use the offsetLite method instead of the full-blown, slower offset method. False by default. - * Only use this when margins, borders and padding calculations don't matter. - * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative). - * It will retreive the offset relative to this parent element. By default it is the body element. - * - * Also an object can be passed as the second paramater to - * catch the value of the return and continue the chain. - * - * For accurate calculations make sure to use pixel values for margins, borders and padding. - * - * Known issues: - * - Issue: A div positioned relative or static without any content before it and its parent will report an offsetTop of 0 in Safari - * Workaround: Place content before the relative div ... and set height and width to 0 and overflow to hidden - * - * @example $("#testdiv").offset() - * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 } - * - * @example $("#testdiv").offset({ scroll: false }) - * @result { top: 90, left: 90 } - * - * @example var offset = {} - * $("#testdiv").offset({ scroll: false }, offset) - * @result offset = { top: 90, left: 90 } - * - * @name offset - * @param Map options Optional settings to configure the way the offset is calculated. - * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the - * chain will not be broken and the result will be assigned to this object. - * @type Object - * @cat Plugins/Dimensions - */ - offset: function(options, returnObject) { - if (!this[0]) error(); - var x = 0, y = 0, sl = 0, st = 0, - elem = this[0], parent = this[0], op, parPos, elemPos = $.css(elem, 'position'), - mo = $.browser.mozilla, ie = $.browser.msie, oa = $.browser.opera, - sf = $.browser.safari, sf3 = $.browser.safari && parseInt($.browser.version) > 520, - absparent = false, relparent = false, - options = $.extend({ margin: true, border: false, padding: false, scroll: true, lite: false, relativeTo: document.body }, options || {}); - - // Use offsetLite if lite option is true - if (options.lite) return this.offsetLite(options, returnObject); - // Get the HTMLElement if relativeTo is a jquery collection - if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0]; - - if (elem.tagName == 'BODY') { - // Safari 2 is the only one to get offsetLeft and offsetTop properties of the body "correct" - // Except they all mess up when the body is positioned absolute or relative - x = elem.offsetLeft; - y = elem.offsetTop; - // Mozilla ignores margin and subtracts border from body element - if (mo) { - x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2); - y += num(elem, 'marginTop') + (num(elem, 'borderTopWidth') *2); - } else - // Opera ignores margin - if (oa) { - x += num(elem, 'marginLeft'); - y += num(elem, 'marginTop'); - } else - // IE does not add the border in Standards Mode - if ((ie && jQuery.boxModel)) { - x += num(elem, 'borderLeftWidth'); - y += num(elem, 'borderTopWidth'); - } else - // Safari 3 doesn't not include border or margin - if (sf3) { - x += num(elem, 'marginLeft') + num(elem, 'borderLeftWidth'); - y += num(elem, 'marginTop') + num(elem, 'borderTopWidth'); - } - } else { - do { - parPos = $.css(parent, 'position'); - - x += parent.offsetLeft; - y += parent.offsetTop; - - // Mozilla and IE do not add the border - // Mozilla adds the border for table cells - if ((mo && !parent.tagName.match(/^t[d|h]$/i)) || ie || sf3) { - // add borders to offset - x += num(parent, 'borderLeftWidth'); - y += num(parent, 'borderTopWidth'); - - // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent - if (mo && parPos == 'absolute') absparent = true; - // IE does not include the border on the body if an element is position static and without an absolute or relative parent - if (ie && parPos == 'relative') relparent = true; - } - - op = parent.offsetParent || document.body; - if (options.scroll || mo) { - do { - if (options.scroll) { - // get scroll offsets - sl += parent.scrollLeft; - st += parent.scrollTop; - } - - // Opera sometimes incorrectly reports scroll offset for elements with display set to table-row or inline - if (oa && ($.css(parent, 'display') || '').match(/table-row|inline/)) { - sl = sl - ((parent.scrollLeft == parent.offsetLeft) ? parent.scrollLeft : 0); - st = st - ((parent.scrollTop == parent.offsetTop) ? parent.scrollTop : 0); - } - - // Mozilla does not add the border for a parent that has overflow set to anything but visible - if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') { - x += num(parent, 'borderLeftWidth'); - y += num(parent, 'borderTopWidth'); - } - - parent = parent.parentNode; - } while (parent != op); - } - parent = op; - - // exit the loop if we are at the relativeTo option but not if it is the body or html tag - if (parent == options.relativeTo && !(parent.tagName == 'BODY' || parent.tagName == 'HTML')) { - // Mozilla does not add the border for a parent that has overflow set to anything but visible - if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') { - x += num(parent, 'borderLeftWidth'); - y += num(parent, 'borderTopWidth'); - } - // Safari 2 and opera includes border on positioned parents - if ( ((sf && !sf3) || oa) && parPos != 'static' ) { - x -= num(op, 'borderLeftWidth'); - y -= num(op, 'borderTopWidth'); - } - break; - } - if (parent.tagName == 'BODY' || parent.tagName == 'HTML') { - // Safari 2 and IE Standards Mode doesn't add the body margin for elments positioned with static or relative - if (((sf && !sf3) || (ie && $.boxModel)) && elemPos != 'absolute' && elemPos != 'fixed') { - x += num(parent, 'marginLeft'); - y += num(parent, 'marginTop'); - } - // Safari 3 does not include the border on body - // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent - // IE does not include the border on the body if an element is positioned static and without an absolute or relative parent - if ( sf3 || (mo && !absparent && elemPos != 'fixed') || - (ie && elemPos == 'static' && !relparent) ) { - x += num(parent, 'borderLeftWidth'); - y += num(parent, 'borderTopWidth'); - } - break; // Exit the loop - } - } while (parent); - } - - var returnValue = handleOffsetReturn(elem, options, x, y, sl, st); - - if (returnObject) { $.extend(returnObject, returnValue); return this; } - else { return returnValue; } - }, - - /** - * Gets the location of the element in pixels from the top left corner of the viewport. - * This method is much faster than offset but not as accurate when borders and margins are - * on the element and/or its parents. This method can be invoked - * by setting the lite option to true in the offset method. - * The offsetLite method takes an optional map of key value pairs to configure the way - * the offset is calculated. Here are the different options. - * - * (Boolean) margin - Should the margin of the element be included in the calculations? True by default. - * (Boolean) border - Should the border of the element be included in the calculations? False by default. - * (Boolean) padding - Should the padding of the element be included in the calcuations? False by default. - * (Boolean) scroll - Sould the scroll offsets of the parent elements be included int he calculations? True by default. - * When true it adds the total scroll offsets of all parents to the total offset and also adds two - * properties to the returned object, scrollTop and scrollLeft. - * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative). - * It will retreive the offset relative to this parent element. By default it is the body element. - * - * @name offsetLite - * @param Map options Optional settings to configure the way the offset is calculated. - * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the - * chain will not be broken and the result will be assigned to this object. - * @type Object - * @cat Plugins/Dimensions - */ - offsetLite: function(options, returnObject) { - if (!this[0]) error(); - var x = 0, y = 0, sl = 0, st = 0, parent = this[0], offsetParent, - options = $.extend({ margin: true, border: false, padding: false, scroll: true, relativeTo: document.body }, options || {}); - - // Get the HTMLElement if relativeTo is a jquery collection - if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0]; - - do { - x += parent.offsetLeft; - y += parent.offsetTop; - - offsetParent = parent.offsetParent || document.body; - if (options.scroll) { - // get scroll offsets - do { - sl += parent.scrollLeft; - st += parent.scrollTop; - parent = parent.parentNode; - } while(parent != offsetParent); - } - parent = offsetParent; - } while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML' && parent != options.relativeTo); - - var returnValue = handleOffsetReturn(this[0], options, x, y, sl, st); - - if (returnObject) { $.extend(returnObject, returnValue); return this; } - else { return returnValue; } - }, - - /** - * Returns a jQuery collection with the positioned parent of - * the first matched element. This is the first parent of - * the element that has position (as in relative or absolute). - * - * @name offsetParent - * @type jQuery - * @cat Plugins/Dimensions - */ - offsetParent: function() { - if (!this[0]) error(); - var offsetParent = this[0].offsetParent; - while ( offsetParent && (offsetParent.tagName != 'BODY' && $.css(offsetParent, 'position') == 'static') ) - offsetParent = offsetParent.offsetParent; - return $(offsetParent); - } -}); - -/** - * Throws an error message when no elements are in the jQuery collection - * @private - */ -var error = function() { - throw "Dimensions: jQuery collection is empty"; -}; - -/** - * Handles converting a CSS Style into an Integer. - * @private - */ -var num = function(el, prop) { - return parseInt($.css(el.jquery?el[0]:el,prop))||0; -}; - -/** - * Handles the return value of the offset and offsetLite methods. - * @private - */ -var handleOffsetReturn = function(elem, options, x, y, sl, st) { - if ( !options.margin ) { - x -= num(elem, 'marginLeft'); - y -= num(elem, 'marginTop'); - } - - // Safari and Opera do not add the border for the element - if ( options.border && (($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) { - x += num(elem, 'borderLeftWidth'); - y += num(elem, 'borderTopWidth'); - } else if ( !options.border && !(($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) { - x -= num(elem, 'borderLeftWidth'); - y -= num(elem, 'borderTopWidth'); - } - - if ( options.padding ) { - x += num(elem, 'paddingLeft'); - y += num(elem, 'paddingTop'); - } - - // do not include scroll offset on the element ... opera sometimes reports scroll offset as actual offset - if ( options.scroll && (!$.browser.opera || elem.offsetLeft != elem.scrollLeft && elem.offsetTop != elem.scrollLeft) ) { - sl -= elem.scrollLeft; - st -= elem.scrollTop; - } - - return options.scroll ? { top: y - st, left: x - sl, scrollTop: st, scrollLeft: sl } - : { top: y, left: x }; -}; - -/** - * Gets the width of the OS scrollbar - * @private - */ -var scrollbarWidth = 0; -var getScrollbarWidth = function() { - if (!scrollbarWidth) { - var testEl = $('
') - .css({ - width: 100, - height: 100, - overflow: 'auto', - position: 'absolute', - top: -1000, - left: -1000 - }) - .appendTo('body'); - scrollbarWidth = 100 - testEl - .append('
') - .find('div') - .css({ - width: '100%', - height: 200 - }) - .width(); - testEl.remove(); - } - return scrollbarWidth; -}; - -})(jQuery); From 3c0b83312d9f213791b1151a1618544d61ee8e1b Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Thu, 1 Sep 2011 16:26:43 -0400 Subject: [PATCH 041/182] some work on the settings dialog --- lib/ripple/ui.js | 3 +- .../ui/plugins/{about.js => about-dialog.js} | 0 .../{about => about-dialog}/dialog.html | 0 lib/ripple/ui/plugins/options.js | 15 +- lib/ripple/ui/plugins/settings-dialog.js | 129 ++++++++++++++++++ .../ui/plugins/settings-dialog/dialog.html | 18 +++ 6 files changed, 161 insertions(+), 4 deletions(-) rename lib/ripple/ui/plugins/{about.js => about-dialog.js} (100%) rename lib/ripple/ui/plugins/{about => about-dialog}/dialog.html (100%) create mode 100644 lib/ripple/ui/plugins/settings-dialog.js create mode 100644 lib/ripple/ui/plugins/settings-dialog/dialog.html diff --git a/lib/ripple/ui.js b/lib/ripple/ui.js index e26a381b..aa632f63 100644 --- a/lib/ripple/ui.js +++ b/lib/ripple/ui.js @@ -26,7 +26,8 @@ var _self, _systemPlugins = [ "omnibar", "options", - "about", + "about-dialog", + "settings-dialog", "firstRunCheck", "devices", "goodVibrations", diff --git a/lib/ripple/ui/plugins/about.js b/lib/ripple/ui/plugins/about-dialog.js similarity index 100% rename from lib/ripple/ui/plugins/about.js rename to lib/ripple/ui/plugins/about-dialog.js diff --git a/lib/ripple/ui/plugins/about/dialog.html b/lib/ripple/ui/plugins/about-dialog/dialog.html similarity index 100% rename from lib/ripple/ui/plugins/about/dialog.html rename to lib/ripple/ui/plugins/about-dialog/dialog.html diff --git a/lib/ripple/ui/plugins/options.js b/lib/ripple/ui/plugins/options.js index eaad3ffb..111d2b2d 100644 --- a/lib/ripple/ui/plugins/options.js +++ b/lib/ripple/ui/plugins/options.js @@ -14,7 +14,8 @@ * limitations under the License. */ var wrench = document.getElementById('options-button'), - about = require('ripple/ui/plugins/about'), + about = require('ripple/ui/plugins/about-dialog'), + settings = require('ripple/ui/plugins/settings-dialog'), hide, show; @@ -36,14 +37,22 @@ module.exports = { $("#options-menu").bind("click", function (event) { switch (event.target.parentElement.id) { case "options-menu-build": - break; case "options-menu-launch": - break; case "options-menu-sign": + var action = event.target.parentElement.id.split("-")[2]; + if (!settings.can(action)) { + settings.show(action); + } + else { + alert(action); + } break; case "options-menu-about": about.show(); break; + case "options-menu-settings": + settings.show(); + break; default: break; } diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js new file mode 100644 index 00000000..959ab037 --- /dev/null +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -0,0 +1,129 @@ +/* + * Copyright 2011 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var db = require('ripple/db'), + utils = require('ripple/utils'), + _with = function (data) { + return { + check: { + build: function () { + return data.sdkPath && + data.projectRoot && + data.buildPath && + data.projectName; + }, + sign: function () { + return false; + }, + launch: function () { + return false; + } + } + }; + }; + +function create() { + var table = function (action) { + var _table = $(""), + _row = { + row: function (prop, desc) { + var id = "settings-" + action + "-" + prop.toLowerCase(), + row = $("" + + "" + + "" + + ""); + + row.appendTo(_table); + + return _row; + }, + appendTo: function (id) { + $(id).html(_table); + } + }; + + return _row; + }; + + table('build') + .row("sdkPath", "SDK Path") + .row("projectRoot", "Project Root") + .row("buildPath", "Build Path") + .row("projectName", "Project Name") + .appendTo("#settings-tabs-build"); + + table('launch') + .row("sdkPath", "SDK Path") + .row("projectRoot", "Project Root") + .appendTo("#settings-tabs-launch"); +} + +function populate(config) { + var bind = function (action, prop) { + var id = "#settings-" + action + "-" + prop.toLowerCase(); + utils.bindAutoSaveEvent($(id).val(config[prop]), function () { + config[prop] = $(id).val(); + db.saveObject("build-settings", config); + }); + }; + + bind("build", "sdkPath"); + bind("build", "projectRoot"); + bind("build", "buildPath"); + bind("build", "projectName"); +} + +module.exports = { + initialize: function () { + $("#settings-dialog").dialog({ + autoOpen: false, + modal: true, + width: 800, + height: 600, + position: 'center' + }).hide(); + + create(); + $("#settings-tabs").tabs(); + }, + + can: function(action) { + var config = db.retrieveObject("build-settings") || {}; + return _with(config).check[action](); + }, + + show: function(action) { + var config = db.retrieveObject("build-settings") || {}; + + populate(config); + + var tab = 0; + + switch (action) { + case "build": + tab = 0; + break; + case "sign": + tab = 1; + break; + case "launch": + tab = 2; + break; + } + + $("#settings-tabs").tabs("select", tab); + $("#settings-dialog").dialog("open"); + } +}; diff --git a/lib/ripple/ui/plugins/settings-dialog/dialog.html b/lib/ripple/ui/plugins/settings-dialog/dialog.html new file mode 100644 index 00000000..b8a10bb8 --- /dev/null +++ b/lib/ripple/ui/plugins/settings-dialog/dialog.html @@ -0,0 +1,18 @@ +
+
+ +
+
+
+
+
+
+
+
+
+
From 8e546970d1a1addbb9f2c8907cc5bb1908754a70 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Tue, 6 Sep 2011 15:46:17 -0400 Subject: [PATCH 042/182] switched to fieldsets and added calls to xhr --- ext/assets/styles/main.css | 9 + lib/ripple/ui/plugins/about-dialog.js | 4 +- lib/ripple/ui/plugins/options.js | 3 +- lib/ripple/ui/plugins/settings-dialog.js | 260 ++++++++++++------ .../ui/plugins/settings-dialog/dialog.html | 6 - 5 files changed, 196 insertions(+), 86 deletions(-) diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index 6d54e2c3..f347c7ae 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -921,3 +921,12 @@ section.left { left: 0; } .omni-bar input { width: 95%; } + +/* ------------------------------> + fieldset */ + +fieldset { + border-radius: 5px; + margin: 5px 0; +} + diff --git a/lib/ripple/ui/plugins/about-dialog.js b/lib/ripple/ui/plugins/about-dialog.js index 00cd192b..92c48f61 100644 --- a/lib/ripple/ui/plugins/about-dialog.js +++ b/lib/ripple/ui/plugins/about-dialog.js @@ -16,8 +16,8 @@ module.exports = { initialize: function () { $("#about-dialog").dialog({ - autoOpen: false, - position: 'center' + autoOpen: false, + position: 'center' }); }, show: function () { diff --git a/lib/ripple/ui/plugins/options.js b/lib/ripple/ui/plugins/options.js index 111d2b2d..6acb94b7 100644 --- a/lib/ripple/ui/plugins/options.js +++ b/lib/ripple/ui/plugins/options.js @@ -40,11 +40,12 @@ module.exports = { case "options-menu-launch": case "options-menu-sign": var action = event.target.parentElement.id.split("-")[2]; + if (!settings.can(action)) { settings.show(action); } else { - alert(action); + settings.perform(action); } break; case "options-menu-about": diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 959ab037..4024afb3 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -15,74 +15,171 @@ */ var db = require('ripple/db'), utils = require('ripple/utils'), - _with = function (data) { - return { - check: { - build: function () { - return data.sdkPath && - data.projectRoot && - data.buildPath && - data.projectName; - }, - sign: function () { - return false; - }, - launch: function () { - return false; + platform = require('ripple/platform'), + transport = require('ripple/platform/webworks.core/2.0.0/client/transport'), + required = { + build: { + "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName"], + "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName"] + }, + sign: { + "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName", "cskPassword", "p12password"], + "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "password"] + }, + launch: { + "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName", "playbookIP", "playbookPW"], + "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "emulator"] + } + }, + url = "http://10.137.42.27:9900/ripple"; + +function validate(settings, action) { + var missing = required[action][platform.current().id].reduce(function (result, field) { + if (!settings.hasOwnProperty(field)) { + result.push(field); + } + return result; + }, []); + + return !!missing.length; +} + +function table(action) { + var _table = $("
"), + _row = { + row: function (prop, desc, opts) { + var id = "settings-" + action + "-" + prop.toLowerCase(), + input = "", + row; + + opts = opts || { type: "text" }; + + if (opts.type === "select") { + input = ""; + } + else { + input = ""; } + + row = $("" + + "" + + "" + + ""); + + row.appendTo(_table); + + return _row; + }, + appendTo: function (id) { + var fs = $("
" + action + "
"); + + $(_table).appendTo(fs); + fs.appendTo($(id)); } }; - }; + return _row; +} function create() { - var table = function (action) { - var _table = $("
" + input + "
"), - _row = { - row: function (prop, desc) { - var id = "settings-" + action + "-" + prop.toLowerCase(), - row = $("" + - "" + - "" + - ""); - - row.appendTo(_table); - - return _row; - }, - appendTo: function (id) { - $(id).html(_table); - } - }; - - return _row; - }; + var sign = table('sign'), + launch = table('launch'); table('build') - .row("sdkPath", "SDK Path") - .row("projectRoot", "Project Root") - .row("buildPath", "Build Path") .row("projectName", "Project Name") + .row("sdk", "SDK Path") + .row("projectPath", "Project Root") + .row("outputPath", "Build Path") .appendTo("#settings-tabs-build"); - table('launch') - .row("sdkPath", "SDK Path") - .row("projectRoot", "Project Root") - .appendTo("#settings-tabs-launch"); + if (platform.current().id === "webworks.handset") { + sign.row("password", "Password", { + type: "password" + }); + + launch.row("emulator", "Emulator", { + type: "select", + values: { + "9000-5.0.0.592": "9000-5.0.0.592", + "9800-6.0.0.141": "9800-6.0.0.141", + "9930-7.0.0.261": "9930-7.0.0.261" + } + }); + } + else if (platform.current().id === "webworks.tablet") { + sign.row("cskPassword", "CSK Password", { + type: "password" + }); + sign.row("p12Password", "P12 Password", { + type: "password" + }); + + launch.row("playbookIP", "Playbook IP"); + launch.row("playbookPW", "Playbook Password"); + } + + sign.appendTo("#settings-tabs-build"); + launch.appendTo("#settings-tabs-build"); } -function populate(config) { +function populate(settings) { var bind = function (action, prop) { - var id = "#settings-" + action + "-" + prop.toLowerCase(); - utils.bindAutoSaveEvent($(id).val(config[prop]), function () { - config[prop] = $(id).val(); - db.saveObject("build-settings", config); - }); + var id = "#settings-" + action + "-" + prop.toLowerCase(), + node = $(id), + save = function () { + if (node.val()) { + settings[prop] = node.val(); + } + else { + delete settings[prop]; + } + db.saveObject("build-settings", settings, platform.getPersistencePrefix()); + }; + + node.val(settings[prop]); + utils.bindAutoSaveEvent(node, save); + node.change(save); }; - bind("build", "sdkPath"); - bind("build", "projectRoot"); - bind("build", "buildPath"); + bind("build", "sdk"); + bind("build", "projectPath"); + bind("build", "outputPath"); bind("build", "projectName"); + + bind("sign", "password"); + bind("sign", "cskPassword"); + bind("sign", "p12Password"); + + bind("launch", "emulator"); + bind("launch", "playbookIP"); + bind("launch", "playbookPW"); +} + +function _url(action) { + var target = ""; + + switch (platform.current().id) { + case "webworks.tablet": + target = "tablet"; + break; + case "webworks.handset": + target = "smartphone"; + break; + } + + return url + "/" + action + "/" + target; +} + +function check(id, cb) { + $.ajax({ + url: url + "/build_status/" + id, + type: "GET", + async: true, + success: cb + }); } module.exports = { @@ -90,8 +187,7 @@ module.exports = { $("#settings-dialog").dialog({ autoOpen: false, modal: true, - width: 800, - height: 600, + width: 600, position: 'center' }).hide(); @@ -99,31 +195,41 @@ module.exports = { $("#settings-tabs").tabs(); }, - can: function(action) { - var config = db.retrieveObject("build-settings") || {}; - return _with(config).check[action](); + can: function (action) { + var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}; + return !validate(settings, action); }, - show: function(action) { - var config = db.retrieveObject("build-settings") || {}; - - populate(config); - - var tab = 0; - - switch (action) { - case "build": - tab = 0; - break; - case "sign": - tab = 1; - break; - case "launch": - tab = 2; - break; - } - - $("#settings-tabs").tabs("select", tab); + show: function (action) { + var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}; + populate(settings); $("#settings-dialog").dialog("open"); + }, + + perform: function (action) { + console.log(action); + var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}, + poll = function (resp) { + console.log(resp.data.id + ": " + resp.data.status); + if (resp && resp.data.status === "building") { + setTimeout(function () { + check(resp.data.id, poll); + }, 500); + } + }; + + $.ajax({ + url: _url(action), + type: "POST", + data: settings, + async: true, + success: function (msg) { + console.log(msg); + poll(msg); + }, + error: function (error) { + console.log(error); + } + }); } }; diff --git a/lib/ripple/ui/plugins/settings-dialog/dialog.html b/lib/ripple/ui/plugins/settings-dialog/dialog.html index b8a10bb8..f9b2ce8c 100644 --- a/lib/ripple/ui/plugins/settings-dialog/dialog.html +++ b/lib/ripple/ui/plugins/settings-dialog/dialog.html @@ -2,16 +2,10 @@
-
-
-
-
From 1b362c73acb58f38d8e1378fbeac6f5d70a9c64e Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Wed, 7 Sep 2011 17:18:10 -0400 Subject: [PATCH 043/182] better integration with the build service, added support for getting the sim list --- ext/assets/index.html | 2 +- ext/assets/styles/main.css | 4 ++ lib/ripple/ui/plugins/options.js | 13 ++-- lib/ripple/ui/plugins/settings-dialog.js | 87 +++++++++++++++++------- 4 files changed, 76 insertions(+), 30 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index f30a26e9..9dd4e051 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -39,7 +39,7 @@
  • Build
  • Sign
  • -
  • Launch
  • +
  • Launch

  • Settings...

  • diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index f347c7ae..cf83c8a1 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -930,3 +930,7 @@ fieldset { margin: 5px 0; } +.not-ready { + opacity: 0.2; +} + diff --git a/lib/ripple/ui/plugins/options.js b/lib/ripple/ui/plugins/options.js index 6acb94b7..84bbdd5b 100644 --- a/lib/ripple/ui/plugins/options.js +++ b/lib/ripple/ui/plugins/options.js @@ -32,15 +32,20 @@ hide = function () { }; module.exports = { - initialize: function (prev, baton) { + initialize: function () { $("#options-menu").menu().hide(); $("#options-menu").bind("click", function (event) { - switch (event.target.parentElement.id) { + var target = $("#" + event.target.parentElement.id), + action = target.attr("id").split("-")[2]; + + if (target.hasClass("not-ready")) { + return; + } + + switch (target.attr("id")) { case "options-menu-build": case "options-menu-launch": case "options-menu-sign": - var action = event.target.parentElement.id.split("-")[2]; - if (!settings.can(action)) { settings.show(action); } diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 4024afb3..4032d12d 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -16,6 +16,7 @@ var db = require('ripple/db'), utils = require('ripple/utils'), platform = require('ripple/platform'), + notifications = require('ripple/notifications'), transport = require('ripple/platform/webworks.core/2.0.0/client/transport'), required = { build: { @@ -28,10 +29,11 @@ var db = require('ripple/db'), }, launch: { "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName", "playbookIP", "playbookPW"], - "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "emulator"] + "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "simulator"] } }, - url = "http://10.137.42.27:9900/ripple"; + simulators = null, + url = "http://127.0.0.1:9900/ripple"; function validate(settings, action) { var missing = required[action][platform.current().id].reduce(function (result, field) { @@ -47,22 +49,23 @@ function validate(settings, action) { function table(action) { var _table = $("
"), _row = { - row: function (prop, desc, opts) { - var id = "settings-" + action + "-" + prop.toLowerCase(), + row: function (item, desc, opts) { + var id = "settings-" + action + "-" + item.toLowerCase(), input = "", row; opts = opts || { type: "text" }; - if (opts.type === "select") { - input = ""; - } - else { - input = ""; + switch (opts.type) { + case "select": + input = ""; + break; } row = $("" + @@ -100,13 +103,13 @@ function create() { type: "password" }); - launch.row("emulator", "Emulator", { - type: "select", - values: { - "9000-5.0.0.592": "9000-5.0.0.592", - "9800-6.0.0.141": "9800-6.0.0.141", - "9930-7.0.0.261": "9930-7.0.0.261" - } + launch.row("simulator", "Simulator", { + type: "select" + }); + + launch.row("simulatorStatus", "Simulator", { + type: "span", + text: "Searching for simulators ..." }); } else if (platform.current().id === "webworks.tablet") { @@ -123,6 +126,9 @@ function create() { sign.appendTo("#settings-tabs-build"); launch.appendTo("#settings-tabs-build"); + + + $("#settings-launch-simulator").parent().parent().hide(); } function populate(settings) { @@ -153,7 +159,7 @@ function populate(settings) { bind("sign", "cskPassword"); bind("sign", "p12Password"); - bind("launch", "emulator"); + bind("launch", "simulator"); bind("launch", "playbookIP"); bind("launch", "playbookPW"); } @@ -183,7 +189,7 @@ function check(id, cb) { } module.exports = { - initialize: function () { + initialize: function (p, baton) { $("#settings-dialog").dialog({ autoOpen: false, modal: true, @@ -191,6 +197,36 @@ module.exports = { position: 'center' }).hide(); + if (platform.current().id === "webworks.handset") { + $.ajax({ + url: url + "/simulators", + type: "GET", + async: true, + success: function (resp) { + var sims = resp.data.simulators; + + if (sims.length > 0) { + $(resp.data.simulators.map(function (sim) { + return ""; + }).join()).appendTo("#settings-launch-simulator"); + + $("#options-menu-launch").removeClass("not-ready"); + $("#settings-launch-simulatorstatus").parent().parent().hide(); + $("#settings-launch-simulator").parent().parent().show(); + } + else { + $("#settings-launch-simulatorstatus").text("No simulators found :("); + } + }, + error: function () { + $("#settings-launch-simulatorstatus").text("Error attempting to get simulators :("); + } + }); + } + else { + $("#options-menu-launch").removeClass("not-ready"); + } + create(); $("#settings-tabs").tabs(); }, @@ -207,15 +243,17 @@ module.exports = { }, perform: function (action) { - console.log(action); var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}, poll = function (resp) { - console.log(resp.data.id + ": " + resp.data.status); if (resp && resp.data.status === "building") { setTimeout(function () { check(resp.data.id, poll); }, 500); } + else { + + console.log(resp.data.id + ": " + resp.data.status); + } }; $.ajax({ @@ -224,7 +262,6 @@ module.exports = { data: settings, async: true, success: function (msg) { - console.log(msg); poll(msg); }, error: function (error) { From 30bddf8fe4abd113e7228956f579f945d769f95e Mon Sep 17 00:00:00 2001 From: Dan Silivestru Date: Wed, 7 Sep 2011 18:47:34 -0400 Subject: [PATCH 044/182] minor changes to the options menu and the settings dialog. Also fixed the ripple logo not displaying --- ext/assets/styles/main.css | 3 +++ ext/assets/themes/dark/theme.css | 4 ++-- ext/assets/themes/light/theme.css | 4 ++-- lib/ripple/ui/plugins/settings-dialog.js | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index cf83c8a1..dae3fe4a 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -670,6 +670,7 @@ section.left { left: 0; } } .panel-table td:nth-child(2) { + width: 50%; text-align: right; } @@ -735,6 +736,8 @@ section.left { left: 0; } } #options-menu { + font-size: 1.2em; + padding: 5px; width: 250px; top: 30px; right: 20px; diff --git a/ext/assets/themes/dark/theme.css b/ext/assets/themes/dark/theme.css index 404a6524..98a8a2d8 100644 --- a/ext/assets/themes/dark/theme.css +++ b/ext/assets/themes/dark/theme.css @@ -523,7 +523,7 @@ input.ui-button { padding: .4em 1em; } color: #F0F0F0; } .logo { - background-image: url("/images/ripplelogo.png"); + background-image: url("../../images/ripplelogo.png"); } .panel-table td { @@ -534,4 +534,4 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ -} \ No newline at end of file +} diff --git a/ext/assets/themes/light/theme.css b/ext/assets/themes/light/theme.css index c6ce195c..5395fd90 100644 --- a/ext/assets/themes/light/theme.css +++ b/ext/assets/themes/light/theme.css @@ -534,7 +534,7 @@ input.ui-button { padding: .4em 1em; } color: #212121; } .logo { - background-image: url("/images/ripplelogo.png"); + background-image: url("../../images/ripplelogo.png"); } .panel-table td { @@ -545,4 +545,4 @@ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ -} \ No newline at end of file +} diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 4032d12d..a2522bd4 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -193,7 +193,7 @@ module.exports = { $("#settings-dialog").dialog({ autoOpen: false, modal: true, - width: 600, + width: 700, position: 'center' }).hide(); From fc9e03aa30df765afe7fdd7f157e6299a0a6996d Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Thu, 8 Sep 2011 14:37:49 -0400 Subject: [PATCH 045/182] disabled menu items for non webworks platforms, moved registration of save handler so we don't end up binding it every time we show the dialog --- ext/assets/index.html | 6 +- lib/ripple/ui/plugins/options.js | 3 +- lib/ripple/ui/plugins/settings-dialog.js | 146 ++++++++++-------- .../ui/plugins/settings-dialog/dialog.html | 3 - 4 files changed, 85 insertions(+), 73 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index 9dd4e051..0c1e66ce 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -37,11 +37,11 @@ diff --git a/lib/ripple/ui/plugins/options.js b/lib/ripple/ui/plugins/options.js index 84bbdd5b..f263b73e 100644 --- a/lib/ripple/ui/plugins/options.js +++ b/lib/ripple/ui/plugins/options.js @@ -36,7 +36,7 @@ module.exports = { $("#options-menu").menu().hide(); $("#options-menu").bind("click", function (event) { var target = $("#" + event.target.parentElement.id), - action = target.attr("id").split("-")[2]; + action; if (target.hasClass("not-ready")) { return; @@ -46,6 +46,7 @@ module.exports = { case "options-menu-build": case "options-menu-launch": case "options-menu-sign": + action = target.attr("id").split("-")[2]; if (!settings.can(action)) { settings.show(action); } diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index a2522bd4..d4f25ed4 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -32,8 +32,7 @@ var db = require('ripple/db'), "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "simulator"] } }, - simulators = null, - url = "http://127.0.0.1:9900/ripple"; + host = "http://127.0.0.1:9900/ripple"; function validate(settings, action) { var missing = required[action][platform.current().id].reduce(function (result, field) { @@ -52,6 +51,17 @@ function table(action) { row: function (item, desc, opts) { var id = "settings-" + action + "-" + item.toLowerCase(), input = "", + save = function () { + var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()); + + if ($("#" + id).val()) { + settings[item] = $("#" + id).val(); + } + else { + delete settings[item]; + } + db.saveObject("build-settings", settings, platform.getPersistencePrefix()); + }, row; opts = opts || { type: "text" }; @@ -75,6 +85,9 @@ function table(action) { row.appendTo(_table); + //bind save handlers to the row + utils.bindAutoSaveEvent(row.find("#" + id).change(save), save); + return _row; }, appendTo: function (id) { @@ -87,11 +100,13 @@ function table(action) { return _row; } + function create() { - var sign = table('sign'), + var build = table('build'), + sign = table('sign'), launch = table('launch'); - table('build') + build .row("projectName", "Project Name") .row("sdk", "SDK Path") .row("projectPath", "Project Root") @@ -127,44 +142,29 @@ function create() { sign.appendTo("#settings-tabs-build"); launch.appendTo("#settings-tabs-build"); - $("#settings-launch-simulator").parent().parent().hide(); } function populate(settings) { - var bind = function (action, prop) { - var id = "#settings-" + action + "-" + prop.toLowerCase(), - node = $(id), - save = function () { - if (node.val()) { - settings[prop] = node.val(); - } - else { - delete settings[prop]; - } - db.saveObject("build-settings", settings, platform.getPersistencePrefix()); - }; - - node.val(settings[prop]); - utils.bindAutoSaveEvent(node, save); - node.change(save); - }; - - bind("build", "sdk"); - bind("build", "projectPath"); - bind("build", "outputPath"); - bind("build", "projectName"); - - bind("sign", "password"); - bind("sign", "cskPassword"); - bind("sign", "p12Password"); - - bind("launch", "simulator"); - bind("launch", "playbookIP"); - bind("launch", "playbookPW"); + var fill = function (action, prop) { + $("#settings-" + action + "-" + prop.toLowerCase()).val(settings[prop]); + }; + + fill("build", "sdk"); + fill("build", "projectPath"); + fill("build", "outputPath"); + fill("build", "projectName"); + + fill("sign", "password"); + fill("sign", "cskPassword"); + fill("sign", "p12Password"); + + fill("launch", "simulator"); + fill("launch", "playbookIP"); + fill("launch", "playbookPW"); } -function _url(action) { +function url(action) { var target = ""; switch (platform.current().id) { @@ -176,18 +176,49 @@ function _url(action) { break; } - return url + "/" + action + "/" + target; + return host + "/" + action + "/" + target; } function check(id, cb) { $.ajax({ - url: url + "/build_status/" + id, + url: host + "/build_status/" + id, type: "GET", async: true, success: cb }); } +function enable(action) { + $("#options-menu-" + action).removeClass("not-ready"); + $("#settings-" + action + "-simulatorstatus").parent().parent().hide(); + $("#settings-" + action + "-simulator").parent().parent().show(); +} + +function getSimulators() { + $.ajax({ + url: host + "/simulators", + type: "GET", + async: true, + success: function (resp) { + var sims = resp.data.simulators; + + if (sims.length > 0) { + $(resp.data.simulators.map(function (sim) { + return ""; + }).join()).appendTo("#settings-launch-simulator"); + + enable("launch"); + } + else { + $("#settings-launch-simulatorstatus").text("No simulators found :("); + } + }, + error: function () { + $("#settings-launch-simulatorstatus").text("Error attempting to get simulators :("); + } + }); +} + module.exports = { initialize: function (p, baton) { $("#settings-dialog").dialog({ @@ -198,33 +229,16 @@ module.exports = { }).hide(); if (platform.current().id === "webworks.handset") { - $.ajax({ - url: url + "/simulators", - type: "GET", - async: true, - success: function (resp) { - var sims = resp.data.simulators; - - if (sims.length > 0) { - $(resp.data.simulators.map(function (sim) { - return ""; - }).join()).appendTo("#settings-launch-simulator"); - - $("#options-menu-launch").removeClass("not-ready"); - $("#settings-launch-simulatorstatus").parent().parent().hide(); - $("#settings-launch-simulator").parent().parent().show(); - } - else { - $("#settings-launch-simulatorstatus").text("No simulators found :("); - } - }, - error: function () { - $("#settings-launch-simulatorstatus").text("Error attempting to get simulators :("); - } - }); + enable("build"); + enable("sign"); + enable("settings"); + getSimulators(); } - else { - $("#options-menu-launch").removeClass("not-ready"); + else if (platform.current().id === "webworks.tablet") { + enable("build"); + enable("sign"); + enable("launch"); + enable("settings"); } create(); @@ -246,18 +260,18 @@ module.exports = { var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}, poll = function (resp) { if (resp && resp.data.status === "building") { + console.log(resp.data.id + ": " + resp.data.status); setTimeout(function () { check(resp.data.id, poll); }, 500); } else { - console.log(resp.data.id + ": " + resp.data.status); } }; $.ajax({ - url: _url(action), + url: url(action), type: "POST", data: settings, async: true, diff --git a/lib/ripple/ui/plugins/settings-dialog/dialog.html b/lib/ripple/ui/plugins/settings-dialog/dialog.html index f9b2ce8c..94fd59d6 100644 --- a/lib/ripple/ui/plugins/settings-dialog/dialog.html +++ b/lib/ripple/ui/plugins/settings-dialog/dialog.html @@ -2,11 +2,8 @@
-
-
From 83e986f683b6145f8d3bfc913d8f716df2d164f8 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Thu, 8 Sep 2011 16:03:25 -0400 Subject: [PATCH 046/182] highlight missing fields, add button to peform action when missing data --- ext/assets/styles/main.css | 4 ++ lib/ripple/ui/plugins/settings-dialog.js | 64 ++++++++++++------- .../ui/plugins/settings-dialog/dialog.html | 1 + 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index dae3fe4a..0a3f7ae6 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -937,3 +937,7 @@ fieldset { opacity: 0.2; } +.cap-text { + text-transform: capitalize; +} + diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index d4f25ed4..fabdc2f3 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -32,24 +32,20 @@ var db = require('ripple/db'), "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "simulator"] } }, - host = "http://127.0.0.1:9900/ripple"; + host = "http://127.0.0.1:9900/ripple", + _self; -function validate(settings, action) { - var missing = required[action][platform.current().id].reduce(function (result, field) { - if (!settings.hasOwnProperty(field)) { - result.push(field); - } - return result; - }, []); - - return !!missing.length; +function missing(settings, action) { + return required[action][platform.current().id].filter(function (field) { + return !settings.hasOwnProperty(field); + }); } function table(action) { var _table = $("
"), _row = { row: function (item, desc, opts) { - var id = "settings-" + action + "-" + item.toLowerCase(), + var id = "settings-field-" + item.toLowerCase(), input = "", save = function () { var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()); @@ -91,7 +87,7 @@ function table(action) { return _row; }, appendTo: function (id) { - var fs = $("
" + action + "
"); + var fs = $("
" + action + "
"); $(_table).appendTo(fs); fs.appendTo($(id)); @@ -142,12 +138,12 @@ function create() { sign.appendTo("#settings-tabs-build"); launch.appendTo("#settings-tabs-build"); - $("#settings-launch-simulator").parent().parent().hide(); + $("#settings-field-simulator").parent().parent().hide(); } function populate(settings) { var fill = function (action, prop) { - $("#settings-" + action + "-" + prop.toLowerCase()).val(settings[prop]); + $("#settings-field-" + prop.toLowerCase()).val(settings[prop]); }; fill("build", "sdk"); @@ -190,8 +186,8 @@ function check(id, cb) { function enable(action) { $("#options-menu-" + action).removeClass("not-ready"); - $("#settings-" + action + "-simulatorstatus").parent().parent().hide(); - $("#settings-" + action + "-simulator").parent().parent().show(); + $("#settings-field-simulatorstatus").parent().parent().hide(); + $("#settings-field-simulator").parent().parent().show(); } function getSimulators() { @@ -205,29 +201,33 @@ function getSimulators() { if (sims.length > 0) { $(resp.data.simulators.map(function (sim) { return ""; - }).join()).appendTo("#settings-launch-simulator"); + }).join()).appendTo("#settings-field-simulator"); enable("launch"); } else { - $("#settings-launch-simulatorstatus").text("No simulators found :("); + $("#settings-field-simulatorstatus").text("No simulators found :("); } }, error: function () { - $("#settings-launch-simulatorstatus").text("Error attempting to get simulators :("); + $("#settings-field-simulatorstatus").text("Error attempting to get simulators :("); } }); } -module.exports = { - initialize: function (p, baton) { +_self = { + initialize: function () { $("#settings-dialog").dialog({ autoOpen: false, modal: true, width: 700, + title: "Settings", position: 'center' }).hide(); + $("#settings-tabs").tabs(); + $("#settings-action").button(); + if (platform.current().id === "webworks.handset") { enable("build"); enable("sign"); @@ -242,18 +242,34 @@ module.exports = { } create(); - $("#settings-tabs").tabs(); }, can: function (action) { var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}; - return !validate(settings, action); + return missing(settings, action).length === 0; }, show: function (action) { var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}; populate(settings); $("#settings-dialog").dialog("open"); + $("#settings-action").button("option", "label", action || "")[action ? "show" : "hide"](); + + if (action) { + missing(settings, action).forEach(function (field) { + $("#settings-field-" + field.toLowerCase()).effect("highlight", {color: "red"}, 1500); + }); + + $("#settings-action").unbind("click").click(function () { + if (_self.can(action)) { + _self.perform(action); + $("#settings-dialog").dialog("close"); + } + else { + _self.show(action); + } + }); + } }, perform: function (action) { @@ -284,3 +300,5 @@ module.exports = { }); } }; + +module.exports = _self; diff --git a/lib/ripple/ui/plugins/settings-dialog/dialog.html b/lib/ripple/ui/plugins/settings-dialog/dialog.html index 94fd59d6..b4dd84aa 100644 --- a/lib/ripple/ui/plugins/settings-dialog/dialog.html +++ b/lib/ripple/ui/plugins/settings-dialog/dialog.html @@ -6,4 +6,5 @@
+ From c2e7e18c53d683e87b4fd6ddf5605d39f611d6ed Mon Sep 17 00:00:00 2001 From: Dan Silivestru Date: Thu, 8 Sep 2011 16:56:45 -0400 Subject: [PATCH 047/182] added notifications to build --- lib/ripple/ui/plugins/settings-dialog.js | 35 ++++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index fabdc2f3..bed5d0c0 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -48,7 +48,7 @@ function table(action) { var id = "settings-field-" + item.toLowerCase(), input = "", save = function () { - var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()); + var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}; if ($("#" + id).val()) { settings[item] = $("#" + id).val(); @@ -175,15 +175,6 @@ function url(action) { return host + "/" + action + "/" + target; } -function check(id, cb) { - $.ajax({ - url: host + "/build_status/" + id, - type: "GET", - async: true, - success: cb - }); -} - function enable(action) { $("#options-menu-" + action).removeClass("not-ready"); $("#settings-field-simulatorstatus").parent().parent().hide(); @@ -275,14 +266,28 @@ _self = { perform: function (action) { var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {}, poll = function (resp) { + var notifications = require("ripple/notifications"); + if (resp && resp.data.status === "building") { - console.log(resp.data.id + ": " + resp.data.status); setTimeout(function () { - check(resp.data.id, poll); + $.ajax({ + url: host + "/build_status/" + resp.data.id, + type: "GET", + async: true, + success: poll, + error: function (error, errorText) { + notifications.openNotification("error", "Build request failed with message: " + errorText); + } + }); }, 500); } else { - console.log(resp.data.id + ": " + resp.data.status); + if (resp.data.code === 1) { + notifications.openNotification("error", "Build request failed with message: " + resp.msg); + } + else { + notifications.openNotification("normal", "Build succeded!"); + } } }; @@ -294,8 +299,8 @@ _self = { success: function (msg) { poll(msg); }, - error: function (error) { - console.log(error); + error: function (xhr, errorText) { + notifications.openNotification("error", "Build request failed with message: " + errorText); } }); } From a053d61234667feb6488a63833b178d1d2d331a3 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Fri, 9 Sep 2011 10:23:24 -0400 Subject: [PATCH 048/182] removed constants for notification types --- lib/ripple/constants.js | 4 ---- lib/ripple/notifications.js | 6 +++--- .../platform/phonegap/1.0/notification.js | 4 ++-- .../webworks.core/2.0.0/server/system.js | 2 +- .../webworks.handset/2.0.0/server/app.js | 4 ++-- .../2.0.0/server/audioPlayer.js | 2 +- .../webworks.handset/2.0.0/server/invoke.js | 2 +- .../webworks.handset/2.0.0/server/sms.js | 2 +- .../webworks.tablet/2.0.0/server/invoke.js | 2 +- test/unit/notifications.js | 20 ++++++++++++------- test/unit/phonegap/notification.js | 4 ++-- test/unit/webworks/app.js | 6 +++--- test/unit/webworks/invoke.js | 6 +++--- test/unit/webworks/sms.js | 4 ++-- test/unit/webworks/system.js | 2 +- 15 files changed, 36 insertions(+), 34 deletions(-) diff --git a/lib/ripple/constants.js b/lib/ripple/constants.js index 81cde9cd..a3af8eb0 100644 --- a/lib/ripple/constants.js +++ b/lib/ripple/constants.js @@ -146,10 +146,6 @@ module.exports = { "CLOSE_BUTTON_CLASS": "panel-notification-closebtn", "MESSAGE_TEXT_CONTAINER_CLASS": "panel-notification-text", "CSS_PREFIX": "panel-notification-", - "TYPES": { - "NORMAL": "normal", - "ERROR": "error" - }, "STATE_TYPES": { "OPEN": 1, "CLOSE": 2 diff --git a/lib/ripple/notifications.js b/lib/ripple/notifications.js index 635a7a6c..ed319d5c 100644 --- a/lib/ripple/notifications.js +++ b/lib/ripple/notifications.js @@ -19,9 +19,9 @@ var constants = require('ripple/constants'), event = require('ripple/event'); function _validateAndInitNType(nType) { - nType = nType || constants.NOTIFICATIONS.TYPES.NORMAL; + nType = nType || "normal"; - if (nType !== constants.NOTIFICATIONS.TYPES.NORMAL && nType !== constants.NOTIFICATIONS.TYPES.ERROR) { + if (nType !== "normal" && nType !== "error") { exception.raise(exception.types.NotificationType, "Unknown Notification Type == " + nType + ",when dealing with Console notification."); } @@ -51,7 +51,7 @@ function _processNotification(nType, stateType, message) { case constants.NOTIFICATIONS.STATE_TYPES.OPEN: display = "display: block;"; //need to do this better. displayText = message; - if (nType === constants.NOTIFICATIONS.TYPES.ERROR) { + if (nType === "error") { displayText = "Oh Snap!\n\n" + displayText; className += " ui-state-error ui-corner-all"; notificationIcon = ''; diff --git a/lib/ripple/platform/phonegap/1.0/notification.js b/lib/ripple/platform/phonegap/1.0/notification.js index 47ad9bb2..dd9abe93 100644 --- a/lib/ripple/platform/phonegap/1.0/notification.js +++ b/lib/ripple/platform/phonegap/1.0/notification.js @@ -21,14 +21,14 @@ var notifications = require('ripple/notifications'), module.exports = { alert: function (message, title, buttonName) { - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, message); + notifications.openNotification("normal", message); }, beep: function (times) { for (var i = times; i > 0; i--) { _console.log("beep!"); } - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, "BEEP x " + times); + notifications.openNotification("normal", "BEEP x " + times); }, vibrate: function (milliseconds) { diff --git a/lib/ripple/platform/webworks.core/2.0.0/server/system.js b/lib/ripple/platform/webworks.core/2.0.0/server/system.js index b03d96eb..2fed5f05 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/server/system.js +++ b/lib/ripple/platform/webworks.core/2.0.0/server/system.js @@ -62,7 +62,7 @@ _self = { setHomeScreenBackground: function (args) { var path = args.filePath, msg = "Set home screen background to " + path + "."; - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); + notifications.openNotification("normal", msg); return {code: 1}; }, hasPermission: function (args) { diff --git a/lib/ripple/platform/webworks.handset/2.0.0/server/app.js b/lib/ripple/platform/webworks.handset/2.0.0/server/app.js index 2ff915e0..8b60ee53 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/server/app.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/server/app.js @@ -99,13 +99,13 @@ _self = { (args.hover ? " hover " : " ") + "icon to " + args.uri; - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); + notifications.openNotification("normal", msg); return {code: 1}; }, setHomeScreenName: function (args) { var msg = "The application set the home screen name to " + args.text; - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); + notifications.openNotification("normal", msg); return {code: 1}; }, diff --git a/lib/ripple/platform/webworks.handset/2.0.0/server/audioPlayer.js b/lib/ripple/platform/webworks.handset/2.0.0/server/audioPlayer.js index 6d24c521..464e6083 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/server/audioPlayer.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/server/audioPlayer.js @@ -53,7 +53,7 @@ container = utils.createElement("section", { document.getElementById("ui").appendChild(container); function _errClosed(method) { - notifications.openNotification(constants.NOTIFICATIONS.TYPES.ERROR, + notifications.openNotification("error", "attempted to call " + method + " on a player that is already closed. This is a very bad thing to do :)"); return false; } diff --git a/lib/ripple/platform/webworks.handset/2.0.0/server/invoke.js b/lib/ripple/platform/webworks.handset/2.0.0/server/invoke.js index 89858f66..cc7b2883 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/server/invoke.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/server/invoke.js @@ -15,7 +15,7 @@ */ var notifications = require('ripple/notifications'), constants = require('ripple/constants'), - type = constants.NOTIFICATIONS.TYPES.NORMAL, + type = "normal", name = { "0": "Address Book", "1": "Bluetooth Config", diff --git a/lib/ripple/platform/webworks.handset/2.0.0/server/sms.js b/lib/ripple/platform/webworks.handset/2.0.0/server/sms.js index d74f5bd4..2f5a7fb8 100644 --- a/lib/ripple/platform/webworks.handset/2.0.0/server/sms.js +++ b/lib/ripple/platform/webworks.handset/2.0.0/server/sms.js @@ -40,7 +40,7 @@ _self = { send: function (args) { var msg = "To " + args.address + ": " + args.message; - notifications.openNotification(constants.NOTIFICATIONS.TYPES.NORMAL, msg); + notifications.openNotification("normal", msg); _console.log(msg); return {code: 1}; } diff --git a/lib/ripple/platform/webworks.tablet/2.0.0/server/invoke.js b/lib/ripple/platform/webworks.tablet/2.0.0/server/invoke.js index cde3337d..98e37005 100644 --- a/lib/ripple/platform/webworks.tablet/2.0.0/server/invoke.js +++ b/lib/ripple/platform/webworks.tablet/2.0.0/server/invoke.js @@ -15,7 +15,7 @@ */ var notifications = require('ripple/notifications'), constants = require('ripple/constants'), - type = constants.NOTIFICATIONS.TYPES.NORMAL, + type = "normal", name = { "camera://": "Camera", "map://": "Maps", diff --git a/test/unit/notifications.js b/test/unit/notifications.js index 13acae6a..b28c682d 100644 --- a/test/unit/notifications.js +++ b/test/unit/notifications.js @@ -62,7 +62,7 @@ describe("notifications", function () { }); it("openNotification_throws_no_exception_when_valid_command", function () { - var nType = constants.NOTIFICATIONS.TYPES.NORMAL, + var nType = "normal", msg = "some type of notification"; expect(function () { notifications.closeNotification(nType, msg); @@ -70,7 +70,7 @@ describe("notifications", function () { }); it("openNotification_updates_dom_objects_properly_when_opening_normal_notification", function () { - var nType = constants.NOTIFICATIONS.TYPES.NORMAL, + var nType = "normal", msg = "some type of notification", box, msgBox; @@ -84,13 +84,16 @@ describe("notifications", function () { }); it("closeNotification_updates_dom_objects_properly_when_closing_normal_notification", function () { - notifications.closeNotification(constants.NOTIFICATIONS.TYPES.NORMAL); - var box = document.getElementById(constants.NOTIFICATIONS.MAIN_CONTAINER_CLASS); + notifications.closeNotification("normal"); + + var box = document.getElementById(constants.NOTIFICATIONS.MAIN_CONTAINER_CLASS), + msgBox = document.getElementById(constants.NOTIFICATIONS.MESSAGE_TEXT_CONTAINER_CLASS); + expect(box.getAttribute("style")).toEqual("display: none;"); }); it("openNotification_updates_dom_objects_properly_when_opening_error_notification", function () { - var nType = constants.NOTIFICATIONS.TYPES.ERROR, + var nType = "error", msg = "type of notification", box, msgBox; @@ -104,8 +107,11 @@ describe("notifications", function () { }); it("closeNotification_updates_dom_objects_properly_when_closing_error_notification", function () { - notifications.closeNotification(constants.NOTIFICATIONS.TYPES.ERROR); - var box = document.getElementById(constants.NOTIFICATIONS.MAIN_CONTAINER_CLASS); + notifications.closeNotification("error"); + + var box = document.getElementById(constants.NOTIFICATIONS.MAIN_CONTAINER_CLASS), + msgBox = document.getElementById(constants.NOTIFICATIONS.MESSAGE_TEXT_CONTAINER_CLASS); + expect(box.getAttribute("style")).toEqual("display: none;"); }); }); diff --git a/test/unit/phonegap/notification.js b/test/unit/phonegap/notification.js index 547c5efd..11ea167a 100644 --- a/test/unit/phonegap/notification.js +++ b/test/unit/phonegap/notification.js @@ -30,9 +30,9 @@ describe("phonegap notifications", function () { }); it("it opens a notification with the supplied message", function () { - spyOn(notifications, "openNotification"); + spyOn(notifications, "openNotification"); notification.alert("His name was Robert Paulson"); - expect(notifications.openNotification).toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, + expect(notifications.openNotification).toHaveBeenCalledWith("normal", "His name was Robert Paulson"); }); }); diff --git a/test/unit/webworks/app.js b/test/unit/webworks/app.js index 85c8e9f4..80a736fd 100644 --- a/test/unit/webworks/app.js +++ b/test/unit/webworks/app.js @@ -272,7 +272,7 @@ describe("webworks_app", function () { uri: "icon.png", hover: true }); - expect(notifications.openNotification).toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, + expect(notifications.openNotification).toHaveBeenCalledWith("normal", "The application set the home screen hover icon to icon.png"); }); @@ -281,7 +281,7 @@ describe("webworks_app", function () { appServer.setHomeScreenIcon({ uri: "foo.png" }); - expect(notifications.openNotification).toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, + expect(notifications.openNotification).toHaveBeenCalledWith("normal", "The application set the home screen icon to foo.png"); }); @@ -290,7 +290,7 @@ describe("webworks_app", function () { appServer.setHomeScreenName({ text: "Awesometown" }); - expect(notifications.openNotification).toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, + expect(notifications.openNotification).toHaveBeenCalledWith("normal", "The application set the home screen name to Awesometown"); }); diff --git a/test/unit/webworks/invoke.js b/test/unit/webworks/invoke.js index fd138046..1f21bda4 100644 --- a/test/unit/webworks/invoke.js +++ b/test/unit/webworks/invoke.js @@ -23,13 +23,13 @@ describe("webworks_invoke", function () { it("raises a notification when calling invoke", function () { spyOn(notifications, "openNotification"); - + webworks.blackberry.invoke.invoke({ appType: "http://www.google.com" }); expect(notifications.openNotification) - .toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, "Requested to launch: Browser application."); + .toHaveBeenCalledWith("normal", "Requested to launch: Browser application."); }); it("calls the correct invoke URI", function () { @@ -61,7 +61,7 @@ describe("webworks_invoke", function () { }); expect(notifications.openNotification) - .toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, "Requested to launch: Browser application."); + .toHaveBeenCalledWith("normal", "Requested to launch: Browser application."); }); it("calls the correct invoke URI", function () { diff --git a/test/unit/webworks/sms.js b/test/unit/webworks/sms.js index 497dfc06..5ac41951 100644 --- a/test/unit/webworks/sms.js +++ b/test/unit/webworks/sms.js @@ -75,13 +75,13 @@ describe("webworks_sms", function () { it("send raises a notification", function () { spyOn(platform, "current").andReturn({name: "generic"}); spyOn(notifications, "openNotification"); - + sms.send({ message: "Pick up some milk", address: "5199541707" }); - expect(notifications.openNotification).toHaveBeenCalledWith(constants.NOTIFICATIONS.TYPES.NORMAL, + expect(notifications.openNotification).toHaveBeenCalledWith("normal", "To 5199541707: Pick up some milk"); }); diff --git a/test/unit/webworks/system.js b/test/unit/webworks/system.js index 43648e91..b19d4f30 100644 --- a/test/unit/webworks/system.js +++ b/test/unit/webworks/system.js @@ -161,7 +161,7 @@ describe("webworks system", function () { var args = {filePath: "the path"}; spyOn(notifications, "openNotification"); system.setHomeScreenBackground(args); - expect(notifications.openNotification.mostRecentCall.args[0]).toEqual(constants.NOTIFICATIONS.TYPES.NORMAL); + expect(notifications.openNotification.mostRecentCall.args[0]).toEqual("normal"); expect(notifications.openNotification.mostRecentCall.args[1]).toMatch(args.filePath); }); }); From 3e3e95b0d656df0da906a37f6b657a03a38a7693 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Fri, 9 Sep 2011 14:06:00 -0400 Subject: [PATCH 049/182] updated some strings as per feedback --- ext/assets/index.html | 4 ++-- ext/assets/styles/main.css | 2 +- lib/ripple/ui/plugins/settings-dialog.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index 0c1e66ce..bb00d370 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -38,8 +38,8 @@
  • Build
  • -
  • Sign
  • -
  • Launch
  • +
  • Build & Sign
  • +
  • Build & Launch

  • Settings...

  • diff --git a/ext/assets/styles/main.css b/ext/assets/styles/main.css index 0a3f7ae6..2766b1f1 100644 --- a/ext/assets/styles/main.css +++ b/ext/assets/styles/main.css @@ -914,7 +914,7 @@ section.left { left: 0; } z-index: 999; } .omni-bar .ui-icon { - display: inline-block; + display: inline-block; } .omni-bar .ui-icon:hover { diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index bed5d0c0..a7f148e6 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -103,10 +103,10 @@ function create() { launch = table('launch'); build - .row("projectName", "Project Name") .row("sdk", "SDK Path") .row("projectPath", "Project Root") - .row("outputPath", "Build Path") + .row("projectName", "Archive Name") + .row("outputPath", "Output Folder") .appendTo("#settings-tabs-build"); if (platform.current().id === "webworks.handset") { From 245e2a844ad98f8a102cbdd5826d98f5b61e9657 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Fri, 9 Sep 2011 14:09:56 -0400 Subject: [PATCH 050/182] always pass the debug flag and set it to true when building / launching / signing --- lib/ripple/ui/plugins/settings-dialog.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index a7f148e6..43ea5b43 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -291,6 +291,9 @@ _self = { } }; + //always set debug to true + settings.debug = true; + $.ajax({ url: url(action), type: "POST", From a118c38017b83af171aa5451c8b7bd3883762ab5 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Fri, 9 Sep 2011 14:58:01 -0400 Subject: [PATCH 051/182] only enable the omnibar on the web version --- build/build/web.js | 4 +++- ext/assets/index.html | 2 +- lib/ripple/bootstrap.js | 9 +++++++-- lib/ripple/ui.js | 9 ++++++++- lib/ripple/ui/plugins/omnibar.js | 2 ++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/build/build/web.js b/build/build/web.js index bb6c2305..1287101f 100644 --- a/build/build/web.js +++ b/build/build/web.js @@ -36,7 +36,9 @@ module.exports = function (src, baton) { fs.writeFileSync(css, fs.readFileSync(css, "utf-8") + src.skins); fs.writeFileSync(index, doc); - fs.writeFileSync(injection, src.js + "require('ripple/bootstrap').bootstrap();"); + fs.writeFileSync(injection, src.js + + "require('ripple/ui').register('omnibar');" + + "require('ripple/bootstrap').bootstrap();"); copy(_c.PACKAGE_JSON, function () { baton.pass(src); diff --git a/ext/assets/index.html b/ext/assets/index.html index bb00d370..47176448 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -29,7 +29,7 @@
    beta
    -
    +
diff --git a/lib/ripple/ui/plugins/push/panel.html b/lib/ripple/ui/plugins/push/panel.html index 03b43538..851c2815 100644 --- a/lib/ripple/ui/plugins/push/panel.html +++ b/lib/ripple/ui/plugins/push/panel.html @@ -33,7 +33,7 @@
- +
From d05c3381ef873c1dc79df0be6f4a2a8d1dc9b4b1 Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Wed, 21 Sep 2011 11:31:57 -0400 Subject: [PATCH 095/182] added content config validation section to fix #119 --- .../webworks.core/2.0.0/spec/config.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js index 2bc25ca7..7ebd7949 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js @@ -414,6 +414,28 @@ module.exports = { occurrence: 0 } } + }, + "content": { + nodeName: "content", + required: false, + occurrence: 1, + attributes: { + src: { + attributeName: "src", + required: true, + type: "string" + }, + type: { + attributeName: "type", + required: false, + type: "string" + }, + charset: { + attributeName: "charset", + required: false, + type: "string" + } + } } } } From 24cbc694afdfcbc47c422780a72363f0daf90738 Mon Sep 17 00:00:00 2001 From: Gord Tanner Date: Wed, 21 Sep 2011 14:07:21 -0400 Subject: [PATCH 096/182] added rim:navigation for #118 and switch content to required for #119 as per docs --- .../platform/webworks.core/2.0.0/spec/config.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js index 7ebd7949..d00c87e4 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js @@ -415,9 +415,22 @@ module.exports = { } } }, + "rim:navigation": { + nodeName: "rim:navigation", + required: false, + occurrence: 1, + attributes: { + mode: { + attributeName: "mode", + required: false, + type: "list", + listValues: ["focus"] + } + } + }, "content": { nodeName: "content", - required: false, + required: true, occurrence: 1, attributes: { src: { From b6bc3db076509e757d06a398f0c9b4ba5891ffc0 Mon Sep 17 00:00:00 2001 From: Gord Tanner Date: Wed, 21 Sep 2011 16:15:56 -0400 Subject: [PATCH 097/182] updated phonegap contact object properties and ctors for #108 --- lib/ripple/platform/phonegap/1.0/Contact.js | 48 ++++++------------- .../platform/phonegap/1.0/ContactAddress.js | 17 ++++--- .../platform/phonegap/1.0/ContactField.js | 4 +- .../phonegap/1.0/ContactOrganization.js | 18 +++---- 4 files changed, 34 insertions(+), 53 deletions(-) diff --git a/lib/ripple/platform/phonegap/1.0/Contact.js b/lib/ripple/platform/phonegap/1.0/Contact.js index a50fdc14..df395d84 100644 --- a/lib/ripple/platform/phonegap/1.0/Contact.js +++ b/lib/ripple/platform/phonegap/1.0/Contact.js @@ -38,46 +38,28 @@ module.exports = function ( addresses, ims, organizations, - published, - updated, birthday, - anniversary, - gender, note, - preferredUsername, photos, - tags, - relationships, - urls, - accounts, - utcOffset, - connected + categories, + urls ) { return { id: id || Math.uuid(undefined, 16), - displayName: displayName, - name: name, - nickname: nickname, - phoneNumbers: phoneNumbers || [], - emails: emails || [], - addresses: addresses || [], - ims: ims || [], - organizations: organizations || [], - published: published, - updated: updated, - birthday: birthday, - anniversary: anniversary, - gender: gender, - note: note, - preferredUsername: preferredUsername, - photos: photos || [], - tags: tags || [], - relationships: relationships || [], - urls: urls || [], - accounts: accounts || [], - utcOffset: utcOffset, - connected: connected, + displayName: displayName || null, + name: name || null, + nickname: nickname || null, + phoneNumbers: phoneNumbers || null, + emails: emails || null, + addresses: addresses || null, + ims: ims || null, + organizations: organizations || null, + birthday: birthday || null, + note: note || null, + photos: photos || null, + categories: categories || null, + urls: urls || null, save: function (success, error) { var _self = this, lastUpdated = this.updated; // hackish diff --git a/lib/ripple/platform/phonegap/1.0/ContactAddress.js b/lib/ripple/platform/phonegap/1.0/ContactAddress.js index 92c6b9b2..0144791e 100644 --- a/lib/ripple/platform/phonegap/1.0/ContactAddress.js +++ b/lib/ripple/platform/phonegap/1.0/ContactAddress.js @@ -13,13 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -module.exports = function (formatted, streetAddress, locality, region, postalCode, country) { +module.exports = function (pref, type, formatted, streetAddress, locality, region, postalCode, country, id) { return { - formatted: formatted, - streetAddress: streetAddress, - locality: locality, - region: region, - postalCode: postalCode, - country: country + pref: pref || null, + type: type || null, + formatted: formatted || null, + streetAddress: streetAddress || null, + locality: locality || null, + region: region || null, + postalCode: postalCode || null, + country: country || null, + id: id || null }; }; diff --git a/lib/ripple/platform/phonegap/1.0/ContactField.js b/lib/ripple/platform/phonegap/1.0/ContactField.js index 23cbb405..8869dde5 100644 --- a/lib/ripple/platform/phonegap/1.0/ContactField.js +++ b/lib/ripple/platform/phonegap/1.0/ContactField.js @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -module.exports = function (type, value, primary) { +module.exports = function (type, value, pref) { return { type: type, value: value, - primary: primary || false + pref: pref || false }; }; diff --git a/lib/ripple/platform/phonegap/1.0/ContactOrganization.js b/lib/ripple/platform/phonegap/1.0/ContactOrganization.js index c00fc646..c2685546 100644 --- a/lib/ripple/platform/phonegap/1.0/ContactOrganization.js +++ b/lib/ripple/platform/phonegap/1.0/ContactOrganization.js @@ -13,16 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -module.exports = function (name, department, title, startDate, endDate, location, description) { - var org = { - name: name, - department: department, - title: title, - startDate: startDate, - endDate: endDate, - location: location, - description: description +module.exports = function (pref, type, name, dept, title) { + return { + pref: pref || null, + type: type || null, + name: name || null, + department: department || null, + title: title || null }; - - return org; }; From 9b80c70183d2949686ea52b911eab04354063590 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Tue, 20 Sep 2011 13:46:48 -0400 Subject: [PATCH 098/182] Fixes Issue #131 to restore x-axis value after shaking, also improved 3D device interaction in accelerometer panel (follows mouse in x-axis) --- lib/ripple/accelerometer.js | 8 ++++++-- lib/ripple/ui/plugins/accelerometer.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/ripple/accelerometer.js b/lib/ripple/accelerometer.js index f77222fd..5f77420a 100644 --- a/lib/ripple/accelerometer.js +++ b/lib/ripple/accelerometer.js @@ -73,7 +73,11 @@ _self = { }, shake: function (shakeXtimes) { - var id, count = 1, stopCount = shakeXtimes || 17; + var id, + count = 1, + stopCount = shakeXtimes || 17 + oldX = _motion.accelerationIncludingGravity.x; + id = setInterval(function () { var freq = 1, @@ -81,7 +85,7 @@ _self = { value = Math.round(amp * Math.sin(freq * count * (180 / Math.PI)) * 100) / 100; if (count > stopCount) { - _motion.accelerationIncludingGravity.x = 0; + _motion.accelerationIncludingGravity.x = oldX; event.trigger("AccelerometerInfoChangedEvent", [_motion]); clearInterval(id); return; diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index 654233e4..9804cd0b 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -98,7 +98,7 @@ function _createCanvas() { node.addEventListener("mousemove", function (e) { if (_mouseDown) { - _offsets.x = (_offsets.x + _oldX - e.offsetX) % 360; + _offsets.x = (_offsets.x - _oldX + e.offsetX) % 360; _offsets.y = (_offsets.y + _oldY - e.offsetY) % 360; _updateCanvas(_offsets.x, _offsets.y); From a89ef3e66b9ad026578fa7ebde75e620c569142d Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 21 Sep 2011 14:34:48 -0400 Subject: [PATCH 099/182] Corrected computed values for accelerometer plugin for x, y, z, alpha, beta, gamma. --- lib/ripple/accelerometer.js | 6 ++-- lib/ripple/ui/plugins/accelerometer.js | 45 ++++++++++++++++++-------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/ripple/accelerometer.js b/lib/ripple/accelerometer.js index 5f77420a..ab0d8b66 100644 --- a/lib/ripple/accelerometer.js +++ b/lib/ripple/accelerometer.js @@ -73,9 +73,9 @@ _self = { }, shake: function (shakeXtimes) { - var id, - count = 1, - stopCount = shakeXtimes || 17 + var id, + count = 1, + stopCount = shakeXtimes || 17, oldX = _motion.accelerationIncludingGravity.x; diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index 9804cd0b..2c9f9b29 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -97,24 +97,43 @@ function _createCanvas() { ThreeDee.setLight(-300, -300, 800); node.addEventListener("mousemove", function (e) { + var beta, gamma, cosX, sinX, cosY, sinY; if (_mouseDown) { - _offsets.x = (_offsets.x - _oldX + e.offsetX) % 360; + _offsets.x = (_offsets.x + _oldX - e.offsetX) % 360; _offsets.y = (_offsets.y + _oldY - e.offsetY) % 360; - _updateCanvas(_offsets.x, _offsets.y); - - var cosX = Math.cos((_offsets.x) * (Math.PI / 180)), - sinX = Math.sin((_offsets.x) * (Math.PI / 180)), - cosY = Math.cos((_offsets.y) * (Math.PI / 180)), - sinY = Math.sin((_offsets.y) * (Math.PI / 180)); + // enforce gamma in [-90,90] as per w3c spec + gamma = -_offsets.x; + if (gamma < -90) { + gamma = -90; + } + if (gamma > 90) { + gamma = 90; + } + + // enforce beta in [-180,180] as per w3c spec + beta = -_offsets.y % 360; + if (beta < -180) { + beta += 360; + } + else if (beta >= 180) { + beta -= 360; + } + + _updateCanvas(0, -beta, gamma); + + cosX = Math.cos((gamma) * (Math.PI / 180)); + sinX = Math.sin((gamma) * (Math.PI / 180)); + cosY = Math.cos((beta) * (Math.PI / 180)); + sinY = Math.sin((beta) * (Math.PI / 180)); accelerometer.setInfo({ - x: sinX * 9.81, - z: -cosX * cosY * 9.81, - y: sinY * cosX * 9.81, - alpha: (-_offsets.x + 360) % 360, - beta: -_offsets.y % 90, - gamma: 0 //gamma radiation is dangerous, stay away + x: -9.81 * cosY * sinX, + y: 9.81 * sinY, + z: 9.81 * cosY * cosX, + alpha: 0, + beta: beta, + gamma: gamma }); _oldX = e.offsetX; From 80e2ab9b774a1c3a49a9559db96643765d67f478 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 21 Sep 2011 15:06:47 -0400 Subject: [PATCH 100/182] Corrected initial startup values for accelerometer plugin. --- lib/ripple/accelerometer.js | 4 ++-- lib/ripple/ui/plugins/accelerometer.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ripple/accelerometer.js b/lib/ripple/accelerometer.js index ab0d8b66..ae591f99 100644 --- a/lib/ripple/accelerometer.js +++ b/lib/ripple/accelerometer.js @@ -21,7 +21,7 @@ var _self, Acceleration = require('ripple/platform/w3c/1.0/Acceleration'), _motion = { acceleration: new Acceleration(0, 0, 0), - accelerationIncludingGravity: new Acceleration(0, 0, -9.81), + accelerationIncludingGravity: new Acceleration(0, 0, 9.81), rotationRate: new Rotation(0, 0, 0), orientation: new Rotation(0, 0, 0), timestamp: new Date().getTime() @@ -54,7 +54,7 @@ _self = { else { _motion = { acceleration: new Acceleration(0, 0, 0), - accelerationIncludingGravity: new Acceleration(0, 0, 0), + accelerationIncludingGravity: new Acceleration(0, 0, 9.81), rotationRate: new Rotation(0, 0, 0), orientation: new Rotation(0, 0, 0), timestamp: new Date().getTime() diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index 2c9f9b29..b47e69ec 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -19,7 +19,7 @@ var ui = require('ripple/ui'), _offsets = { x: 0, y: 0, - z: 0 + z: 9.81 }, _oldX, _oldY, From a6b38a93fea75fbc6ce5279ebe2858dde4c3cd2a Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 21 Sep 2011 16:12:22 -0400 Subject: [PATCH 101/182] Updated accelerometer to report values as seen on device. --- lib/ripple/accelerometer.js | 4 ++-- lib/ripple/ui/plugins/accelerometer.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ripple/accelerometer.js b/lib/ripple/accelerometer.js index ae591f99..588c1589 100644 --- a/lib/ripple/accelerometer.js +++ b/lib/ripple/accelerometer.js @@ -21,7 +21,7 @@ var _self, Acceleration = require('ripple/platform/w3c/1.0/Acceleration'), _motion = { acceleration: new Acceleration(0, 0, 0), - accelerationIncludingGravity: new Acceleration(0, 0, 9.81), + accelerationIncludingGravity: new Acceleration(0, 0, -9.81), rotationRate: new Rotation(0, 0, 0), orientation: new Rotation(0, 0, 0), timestamp: new Date().getTime() @@ -54,7 +54,7 @@ _self = { else { _motion = { acceleration: new Acceleration(0, 0, 0), - accelerationIncludingGravity: new Acceleration(0, 0, 9.81), + accelerationIncludingGravity: new Acceleration(0, 0, -9.81), rotationRate: new Rotation(0, 0, 0), orientation: new Rotation(0, 0, 0), timestamp: new Date().getTime() diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index b47e69ec..80e1dba4 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -19,7 +19,7 @@ var ui = require('ripple/ui'), _offsets = { x: 0, y: 0, - z: 9.81 + z: -9.81 }, _oldX, _oldY, @@ -128,9 +128,9 @@ function _createCanvas() { sinY = Math.sin((beta) * (Math.PI / 180)); accelerometer.setInfo({ - x: -9.81 * cosY * sinX, - y: 9.81 * sinY, - z: 9.81 * cosY * cosX, + x: 9.81 * cosY * sinX, + y: -9.81 * sinY, + z: -9.81 * cosY * cosX, alpha: 0, beta: beta, gamma: gamma From 5e04b993320e0c04e69941ddeb80e02e8806aa04 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Thu, 22 Sep 2011 10:51:31 -0400 Subject: [PATCH 102/182] cleaned up omnibar ui a bit --- ext/assets/index.html | 28 ++++++++++++++++++++-------- ext/assets/ripple.css | 31 +++++++++++++++++++++++++------ lib/ripple/ui/plugins/omnibar.js | 2 +- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index 51961433..f7b9338d 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -29,17 +29,29 @@
beta
-
- +
+ + + From f88c233c9a5e582b96006c6b13666b85d78cc553 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 22 Sep 2011 12:07:12 -0400 Subject: [PATCH 104/182] Lint fixes. --- lib/ripple/ui/plugins/accelerometer.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index 1a83120c..43c580d4 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -95,10 +95,10 @@ function _updateCanvas(a, b, g) { function _createCanvas() { var node = document.querySelector("#accelerometer-canvas"), - x=0, y=0, z=-9.81, - alpha=0, beta=0, gamma=0, - cosX, sinX, cosY, sinY, - deltaAlpha=360; + x = 0, y = 0, z = -9.81, + alpha = 0, beta = 0, gamma = 0, + cosX, sinX, cosY, sinY, + deltaAlpha = 360; ThreeDee.setCenter(150, 100); ThreeDee.setLight(-300, -300, 800); @@ -141,12 +141,12 @@ function _createCanvas() { } else if (_mouseDown && _shiftKeyDown) { var factor = 2.5; - deltaAlpha = (deltaAlpha - (_oldAlphaX - e.offsetX)*factor) % 360; + deltaAlpha = (deltaAlpha - (_oldAlphaX - e.offsetX) * factor) % 360; alpha = (360 - deltaAlpha) % 360; _oldAlphaX = e.offsetX; } - _updateCanvas(deltaAlpha, -beta, gamma); + _updateCanvas(deltaAlpha, -beta, gamma); accelerometer.setInfo({ x: x, y: y, From 6efd4583d86f4b2dbec637d12cb053f190d2cd29 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 22 Sep 2011 13:27:31 -0400 Subject: [PATCH 105/182] Improved behaviour for manipulating alpha with 'shift' key. --- lib/ripple/ui/plugins/accelerometer.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index 43c580d4..f1a4427f 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -140,8 +140,7 @@ function _createCanvas() { _oldY = e.offsetY; } else if (_mouseDown && _shiftKeyDown) { - var factor = 2.5; - deltaAlpha = (deltaAlpha - (_oldAlphaX - e.offsetX) * factor) % 360; + deltaAlpha = (deltaAlpha - (_oldAlphaX - e.offsetX) * 2.5) % 360; alpha = (360 - deltaAlpha) % 360; _oldAlphaX = e.offsetX; } @@ -161,7 +160,6 @@ function _createCanvas() { node.addEventListener("mousedown", function (e) { _oldX = e.offsetX; _oldY = e.offsetY; - _oldAlphaX = e.offsetX; _mouseDown = true; }); @@ -176,6 +174,7 @@ function _createCanvas() { document.addEventListener("keydown", function (e) { if (e.keyCode === 16) { // Shift Key + _oldAlphaX = _oldX; _shiftKeyDown = true; } }); From 2c943eec711e02c6151f52357794cdd1b82f6b4d Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 22 Sep 2011 13:53:25 -0400 Subject: [PATCH 106/182] Change accelerometer panel instructions. --- lib/ripple/ui/plugins/accelerometer/panel.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/accelerometer/panel.html b/lib/ripple/ui/plugins/accelerometer/panel.html index 9ad00249..4abba1e4 100644 --- a/lib/ripple/ui/plugins/accelerometer/panel.html +++ b/lib/ripple/ui/plugins/accelerometer/panel.html @@ -28,7 +28,7 @@ From 68fb67261774b919c9db117873b977656e2c874c Mon Sep 17 00:00:00 2001 From: Ken Whatmough Date: Thu, 22 Sep 2011 14:43:21 -0400 Subject: [PATCH 107/182] Added fix for 3D rotation of device in accelerometer panel. --- lib/ripple/ui/plugins/accelerometer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/accelerometer.js b/lib/ripple/ui/plugins/accelerometer.js index f1a4427f..95f73a6e 100644 --- a/lib/ripple/ui/plugins/accelerometer.js +++ b/lib/ripple/ui/plugins/accelerometer.js @@ -84,7 +84,8 @@ function _updateAccelerometerPanel(motion) { function _updateCanvas(a, b, g) { ThreeDee.loadMesh(_shape); g = g || 0; - ThreeDee.rotate(b, g, a); + ThreeDee.rotate(0, g, 0); + ThreeDee.rotate(b, 0, a); ThreeDee.backface(); ThreeDee.shade(); ThreeDee.zSort(); From 6b1e218aef31f379aa712f62c820d7f51042b63c Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Thu, 22 Sep 2011 15:52:57 -0400 Subject: [PATCH 108/182] fix omnibar stretching too far in QTWebkit build --- ext/assets/index.html | 4 ++-- ext/assets/ripple.css | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index f7b9338d..f29bff98 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -30,7 +30,7 @@
diff --git a/ext/assets/ripple.css b/ext/assets/ripple.css index 13fb698b..3d2b0d70 100644 --- a/ext/assets/ripple.css +++ b/ext/assets/ripple.css @@ -1021,6 +1021,14 @@ section.left { left: 0; } float: right; } + .progress { + font-size: 1.5em; + font-weight: bold; + letter-spacing: 2px; + float: right; + padding-right: 5px; + } + .omni-bar input { width: 80%; } diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index fd5eff6a..5b17781f 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -45,6 +45,8 @@ var db = require('ripple/db'), }, port = window.stagewebview ? stagewebview.serverPort : "9900", host = "http://127.0.0.1:" + port + "/ripple", + progressContainer = jQuery("#options-progress"), + progressInterval, _self; function missing(settings, action) { @@ -247,6 +249,27 @@ function getSimulators() { }); } +function _startProgress() { + if (progressInterval) { + window.clearInterval(progressInterval); + } + progressInterval = window.setInterval(function () { + if (progressContainer.html().length === 5) { + progressContainer.html("."); + } + else { + progressContainer.html(progressContainer.html() + "."); + } + }, 250); +} + +function _endProgress() { + window.clearInterval(progressInterval); + progressInterval = null; + progressContainer.innerHTML = ""; +} + + _self = { initialize: function () { $("#settings-dialog").dialog({ @@ -323,6 +346,7 @@ _self = { success: poll, error: function (error, errorText) { notifications.openNotification("error", "Build request failed with message: " + errorText); + _endProgress(); } }); }, 500); @@ -333,6 +357,7 @@ _self = { _settings.save(settings); } notifications.openNotification("normal", "Build succeded!"); + _endProgress(); } } }; @@ -343,6 +368,7 @@ _self = { data: settings, async: true, success: function (msg) { + _startProgress(); poll(msg); }, error: function (xhr, errorText) { From df3479b235d6deb9b7a9cbdab5beb9f1ae60da80 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Fri, 30 Sep 2011 16:06:52 -0400 Subject: [PATCH 155/182] Small fixes to progress indictor. --- lib/ripple/ui/plugins/settings-dialog.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 5b17781f..ccf1ddc9 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -266,7 +266,7 @@ function _startProgress() { function _endProgress() { window.clearInterval(progressInterval); progressInterval = null; - progressContainer.innerHTML = ""; + progressContainer.html(""); } @@ -335,6 +335,7 @@ _self = { if (resp && resp.code !== 0) { notifications.openNotification("error", "Build request failed with message: " + resp.msg); + _endProgress(); } else { if (resp && resp.data.status === "building") { From 17cf3de04b0ae1264a9710a5b17428331b5ba7b3 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Fri, 30 Sep 2011 16:39:53 -0400 Subject: [PATCH 156/182] updated config fetching to work on world refresh, fixed config validation when no access node is present (webworks) --- .../platform/webworks.core/2.0.0/spec/config.js | 8 ++++---- lib/ripple/ui/plugins/omnibar.js | 10 +++++++--- lib/ripple/utils.js | 9 ++++++--- test/unit/utils.js | 17 +++++++++++------ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js index a492d125..a9917d08 100644 --- a/lib/ripple/platform/webworks.core/2.0.0/spec/config.js +++ b/lib/ripple/platform/webworks.core/2.0.0/spec/config.js @@ -68,12 +68,12 @@ module.exports = { return { uri: access.attributes.uri.value, subdomains: access.attributes.subdomains.value, - features: accessFeatures.filter(function (f) { + features: accessFeatures ? accessFeatures.filter(function (f) { return f.node && f.node.parentNode && f.node.parentNode.attributes.uri.value === access.attributes.uri.value; - }) + }) : null }; }).reduce(function (result, access) { - return access.features.reduce(function (features, validationResult) { + return access.features ? access.features.reduce(function (features, validationResult) { var feature = features[validationResult.attributes.id.value] || toFeature(validationResult); feature.URIs.push({ value: access.uri, @@ -81,7 +81,7 @@ module.exports = { }); features[feature.id] = feature; return features; - }, result); + }, result) : result; }, widgetInfo.features); return widgetInfo; diff --git a/lib/ripple/ui/plugins/omnibar.js b/lib/ripple/ui/plugins/omnibar.js index 52b40221..b5d411c4 100644 --- a/lib/ripple/ui/plugins/omnibar.js +++ b/lib/ripple/ui/plugins/omnibar.js @@ -25,6 +25,10 @@ function _persist(url) { db.save("current-url", url); } +function _currentURL() { + return db.retrieve("current-url") || "about:blank"; +} + module.exports = { initialize: function (prev, baton) { var omnibar = _omnibar(), @@ -40,7 +44,7 @@ module.exports = { $(".omni-bar").show(); - omnibar.value = db.retrieve("current-url") || "about:blank"; + omnibar.value = _currentURL(); omnibar.addEventListener("keydown", function (event) { if (event.keyCode === '13' || event.keyCode === 13) { // enter @@ -63,7 +67,7 @@ module.exports = { emulatorBridge.window().location.reload(); }); }, - value : function () { - return _omnibar().value; + currentURL : function () { + return _currentURL(); } }; diff --git a/lib/ripple/utils.js b/lib/ripple/utils.js index 8f6cf580..1641156e 100644 --- a/lib/ripple/utils.js +++ b/lib/ripple/utils.js @@ -147,11 +147,14 @@ self = module.exports = { appLocation: function () { if (require('ripple/ui').registered("omnibar")) { - var path = require('ripple/ui/plugins/omnibar').value().replace(/\/$/, ""), + var path = require('ripple/ui/plugins/omnibar').currentURL().replace(/\/$/, ""), parts; if ((parts = path.match(/^((http[s]?|ftp):\/\/)(.+\/)?([^\/].+)$/i)) !== null && parts.length === 5) { - if (parts[3]) { + if (parts[4] === "about:blank") { + path = ""; + } + else if (parts[3]) { path = parts[1] + parts[3]; if (parts[4].indexOf(".") === -1) { path += parts[4] + "/"; @@ -162,7 +165,7 @@ self = module.exports = { } } else { - path = null; + path = ""; } return path; } diff --git a/test/unit/utils.js b/test/unit/utils.js index 10160ec9..b1453543 100644 --- a/test/unit/utils.js +++ b/test/unit/utils.js @@ -506,34 +506,39 @@ describe("utils", function () { }); it("with a trailing slash", function () { - spyOn(omnibar, "value").andReturn("http://127.0.0.1/UI/"); + spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI/"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("without a trailing slash", function () { - spyOn(omnibar, "value").andReturn("http://127.0.0.1/UI"); + spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("with a specific file", function () { - spyOn(omnibar, "value").andReturn("http://127.0.0.1/UI/yui.html"); + spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI/yui.html"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("with a subdomain", function () { - spyOn(omnibar, "value").andReturn("http://rippledemo.tinyhippos.com/"); + spyOn(omnibar, "currentURL").andReturn("http://rippledemo.tinyhippos.com/"); expect(utils.appLocation()).toBe("http://rippledemo.tinyhippos.com/"); }); it("with simple domain", function () { - spyOn(omnibar, "value").andReturn("http://rim.com"); + spyOn(omnibar, "currentURL").andReturn("http://rim.com"); expect(utils.appLocation()).toBe("http://rim.com/"); }); it("with simple domain", function () { - spyOn(omnibar, "value").andReturn("http://rim.com"); + spyOn(omnibar, "currentURL").andReturn("http://rim.com"); expect(utils.appLocation()).toBe("http://rim.com/"); }); + + it("and returns an empty string when about:blank ", function () { + spyOn(omnibar, "currentURL").andReturn("http://about:blank"); + expect(utils.appLocation()).toBe(""); + }); }); describe("when omnibar is disabled", function () { From dc975c97c005e4a3c873149b9ac91c8d94a0fb1a Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Fri, 30 Sep 2011 16:56:51 -0400 Subject: [PATCH 157/182] Fixes issue #169 - Replace all instances of build with package --- ext/assets/index.html | 6 +++--- lib/ripple/ui/plugins/settings-dialog/dialog.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/assets/index.html b/ext/assets/index.html index 5e58bda8..0c8b3243 100644 --- a/ext/assets/index.html +++ b/ext/assets/index.html @@ -49,9 +49,9 @@
    -
  • Build
  • -
  • Build & Sign
  • -
  • Build & Launch
  • +
  • Package
  • +
  • Package & Sign
  • +
  • Package & Launch

  • Settings...

  • diff --git a/lib/ripple/ui/plugins/settings-dialog/dialog.html b/lib/ripple/ui/plugins/settings-dialog/dialog.html index b4dd84aa..3944a92e 100644 --- a/lib/ripple/ui/plugins/settings-dialog/dialog.html +++ b/lib/ripple/ui/plugins/settings-dialog/dialog.html @@ -1,7 +1,7 @@
    From 20418368415dfb7b8f6e250822049532b356077f Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Sat, 1 Oct 2011 15:59:58 -0400 Subject: [PATCH 158/182] Fixes issue #175 - Relative path of banner icon should use application's base path --- lib/ripple/ui/plugins/information.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/information.js b/lib/ripple/ui/plugins/information.js index 5748876e..96a6bb48 100644 --- a/lib/ripple/ui/plugins/information.js +++ b/lib/ripple/ui/plugins/information.js @@ -80,7 +80,11 @@ function _updateBanner(icon, count) { jQuery(bannerSection).fadeOut(1000); } - iconImg.src = icon; + iconImg.src = utils.appLocation() + icon; + if (icon.indexOf("http") === 0) { + iconImg.src = icon; + } + countSpan.innerHTML = count > 99 ? "99+" : count; } From b7ce958413c455d2f50646ae07fb0376add8700a Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 4 Oct 2011 11:51:54 -0400 Subject: [PATCH 159/182] added keyboard shortcuts for manipulating omnibar history - #168 #52 --- lib/ripple/ui/plugins/omnibar.js | 47 ++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/ripple/ui/plugins/omnibar.js b/lib/ripple/ui/plugins/omnibar.js index b5d411c4..1cbca42b 100644 --- a/lib/ripple/ui/plugins/omnibar.js +++ b/lib/ripple/ui/plugins/omnibar.js @@ -29,12 +29,21 @@ function _currentURL() { return db.retrieve("current-url") || "about:blank"; } +function _back() { + emulatorBridge.window().history.back(); +} + +function _forward() { + emulatorBridge.window().history.forward(); +} + +function _reload() { + emulatorBridge.window().location.reload(); +} + module.exports = { initialize: function (prev, baton) { - var omnibar = _omnibar(), - back = document.getElementById("history-back"), - forward = document.getElementById("history-forward"), - reload = document.getElementById("history-reload"); + var omnibar = _omnibar(); jQuery(".logo, .beta, .left, .right, .left-panel-collapse, .right-panel-collapse").css({ "marginTop": "35px" @@ -55,17 +64,31 @@ module.exports = { } }); - back.addEventListener("click", function () { - emulatorBridge.window().history.back(); - }); + window.addEventListener("keydown", function (event) { + var hasMetaOrAltPressed = (event.metaKey || event.ctrlKey), + key = parseInt(event.keyCode, 10); - forward.addEventListener("click", function () { - emulatorBridge.window().history.forward(); - }); + if (key === 37 && hasMetaOrAltPressed) { // cmd/ctrl + left arrow + event.preventDefault(); + _back(); + } + + if (key === 39 && hasMetaOrAltPressed) { // cmd/ctrl + right arrow + event.stopPropagation(); + event.preventDefault(); + _forward(); + } - reload.addEventListener("click", function () { - emulatorBridge.window().location.reload(); + if (key === 82 && hasMetaOrAltPressed) { // cmd/ctrl + r + event.stopPropagation(); + event.preventDefault(); + _reload(); + } }); + + document.getElementById("history-back").addEventListener("click", _back); + document.getElementById("history-forward").addEventListener("click", _forward); + document.getElementById("history-reload").addEventListener("click", _reload); }, currentURL : function () { return _currentURL(); From 2d0a2cc7f5156eb2154787195b4c7dc93fc907a8 Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Tue, 4 Oct 2011 12:20:20 -0400 Subject: [PATCH 160/182] update omnibar url on history change - #185 --- lib/ripple/ui/plugins/omnibar.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/ripple/ui/plugins/omnibar.js b/lib/ripple/ui/plugins/omnibar.js index 1cbca42b..54f0c84b 100644 --- a/lib/ripple/ui/plugins/omnibar.js +++ b/lib/ripple/ui/plugins/omnibar.js @@ -41,6 +41,11 @@ function _reload() { emulatorBridge.window().location.reload(); } +event.on("FrameHistoryChange", function (url) { + _omnibar().value = url; + _persist(url); +}); + module.exports = { initialize: function (prev, baton) { var omnibar = _omnibar(); From 4ae93ccfbca3b212a1d2129ba4af2f296470c84b Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Tue, 4 Oct 2011 14:03:37 -0400 Subject: [PATCH 161/182] use jQuery.isArray to fix an issue we had cloning objects in #186 --- lib/ripple/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/utils.js b/lib/ripple/utils.js index 1641156e..8c1ad168 100644 --- a/lib/ripple/utils.js +++ b/lib/ripple/utils.js @@ -397,7 +397,7 @@ self = module.exports = { copy: function (obj) { var i, - newObj = (obj instanceof Array) ? [] : {}; + newObj = jQuery.isArray(obj) ? [] : {}; if (typeof obj === 'number' || typeof obj === 'string' || From 2abfc0fa678ce7383c2c5243d97562766c5234dc Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Tue, 4 Oct 2011 15:13:03 -0400 Subject: [PATCH 162/182] Updated the about dialog to display current version of Ripple and its subcomponents. --- ext/assets/ripple.css | 9 ++++ ext/assets/themes/dark/theme.css | 5 +++ ext/assets/themes/light/theme.css | 5 +++ lib/ripple/ui/plugins/about-dialog.js | 23 +++++++++- .../ui/plugins/about-dialog/dialog.html | 26 ++++++++++- lib/ripple/utils.js | 13 ++++++ test/unit/utils.js | 45 +++++++++++++++++++ 7 files changed, 123 insertions(+), 3 deletions(-) diff --git a/ext/assets/ripple.css b/ext/assets/ripple.css index 3d2b0d70..622c3ebb 100644 --- a/ext/assets/ripple.css +++ b/ext/assets/ripple.css @@ -1033,6 +1033,15 @@ section.left { left: 0; } width: 80%; } +/* ------------------------------> + About Dialog */ +.about-logo { + background-size: 100%; + background-repeat: no-repeat; + height: 90px; + width: 118px; +} + /* ------------------------------> fieldset */ diff --git a/ext/assets/themes/dark/theme.css b/ext/assets/themes/dark/theme.css index 45e5d6d4..69b05b1e 100644 --- a/ext/assets/themes/dark/theme.css +++ b/ext/assets/themes/dark/theme.css @@ -522,10 +522,15 @@ input.ui-button { padding: .4em 1em; } .platform-select-dialog { color: #F0F0F0; } + .logo { background-image: url("../../images/ripplelogo.png"); } +.about-logo { + background-image: url("../../images/ripplelogo.png"); +} + .panel-table td { color: white; } diff --git a/ext/assets/themes/light/theme.css b/ext/assets/themes/light/theme.css index 5395fd90..766c89ec 100644 --- a/ext/assets/themes/light/theme.css +++ b/ext/assets/themes/light/theme.css @@ -533,10 +533,15 @@ input.ui-button { padding: .4em 1em; } .platform-select-dialog { color: #212121; } + .logo { background-image: url("../../images/ripplelogo.png"); } +.about-logo { + background-image: url("../../images/ripplelogo.png"); +} + .panel-table td { color: #222; } diff --git a/lib/ripple/ui/plugins/about-dialog.js b/lib/ripple/ui/plugins/about-dialog.js index 92c48f61..11bb4900 100644 --- a/lib/ripple/ui/plugins/about-dialog.js +++ b/lib/ripple/ui/plugins/about-dialog.js @@ -13,14 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +var utils = require('ripple/utils'); + module.exports = { initialize: function () { $("#about-dialog").dialog({ autoOpen: false, - position: 'center' + position: 'center', + minWidth: '400' }); }, show: function () { + var port = window.stagewebview ? stagewebview.serverPort : "9900"; + + $.ajax({ + url: "http://127.0.0.1:" + port + "/ripple/about", + async: false, + success: function (resp) { + $("#about-dialog-ripple-build-deploy-version").html("(v" + resp.data.version + ")"); + } + }); + + $.ajax({ + url: utils.rippleLocation() + "package.json", + async: false, + success: function (resp) { + $("#about-dialog-ripple-ui-version").html("(v" + resp.version + ")"); + } + }); + $("#about-dialog").dialog("open"); } }; diff --git a/lib/ripple/ui/plugins/about-dialog/dialog.html b/lib/ripple/ui/plugins/about-dialog/dialog.html index 104a0558..6b3aaf1e 100644 --- a/lib/ripple/ui/plugins/about-dialog/dialog.html +++ b/lib/ripple/ui/plugins/about-dialog/dialog.html @@ -1,3 +1,25 @@ -
    - Stuff about the version and things will go here! +
    + + Ripple Mobile Emulator + (v0.9.0) +
    +
      +
    • Ripple UI + (v0.9.0) +
    • +
    • Ripple Framework + (v0.9.0) +
    • +
    • Ripple Build & Deploy + (v0.9.0) +
    • +
    +
      +
    • + Ripple on GitHub http://blackberry.github.com/ripple +
    • +
    • + WebWorks Developer Site http://developer.blackberry.com/webworks +
    • +
    diff --git a/lib/ripple/utils.js b/lib/ripple/utils.js index 1641156e..6f9ac201 100644 --- a/lib/ripple/utils.js +++ b/lib/ripple/utils.js @@ -172,6 +172,19 @@ self = module.exports = { return self.location(); }, + rippleLocation: function () { + var loc = self.location(), + parts = loc.pathname.replace(/\/$/, "").split("/"), + base = ""; + + if (parts[parts.length - 1].indexOf(".") !== -1) { + parts = parts.splice(0, parts.length - 1); + } + base = parts.join("/"); + + return loc.protocol + "//" + loc.hostname + base + "/"; + }, + arrayContains: function (array, obj) { var i = array.length; while (i--) { diff --git a/test/unit/utils.js b/test/unit/utils.js index b1453543..0697b863 100644 --- a/test/unit/utils.js +++ b/test/unit/utils.js @@ -550,4 +550,49 @@ describe("utils", function () { }); }); + describe("rippleLocation", function () { + describe("properly returns the base path for ripple-ui", function () { + it("returns the base path when index.html is used", function () { + spyOn(utils, "location").andReturn({ + href: "http://127.0.0.1/ripple/index.html", + protocol: "http:", + hostname: "127.0.0.1", + pathname: "/ripple/index.html" + }); + expect(utils.rippleLocation()).toBe("http://127.0.0.1/ripple/"); + }); + + it("returns the base path when index.html is not specified", function () { + spyOn(utils, "location").andReturn({ + href: "http://127.0.0.1/ripple/", + protocol: "http:", + hostname: "127.0.0.1", + pathname: "/ripple/" + }); + expect(utils.rippleLocation()).toBe("http://127.0.0.1/ripple/"); + }); + + it("returns the base path when no trailing forward slash exists", function () { + spyOn(utils, "location").andReturn({ + href: "http://127.0.0.1/ripple", + protocol: "http:", + hostname: "127.0.0.1", + pathname: "/ripple" + }); + expect(utils.rippleLocation()).toBe("http://127.0.0.1/ripple/"); + }); + + it("returns the base path when hosted in multiple subdirectories", function () { + spyOn(utils, "location").andReturn({ + href: "http://127.0.0.1/i/will/put/ripple/here/", + protocol: "http:", + hostname: "127.0.0.1", + pathname: "/i/will/put/ripple/here/" + }); + expect(utils.rippleLocation()).toBe("http://127.0.0.1/i/will/put/ripple/here/"); + }); + }); + + }); + }); From deec3c499969ee09a80ae6a6f95eaf22653a7271 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Tue, 4 Oct 2011 16:21:18 -0400 Subject: [PATCH 163/182] Changed about page XHR calls to async per review comments. --- lib/ripple/ui/plugins/about-dialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ripple/ui/plugins/about-dialog.js b/lib/ripple/ui/plugins/about-dialog.js index 11bb4900..31c0e338 100644 --- a/lib/ripple/ui/plugins/about-dialog.js +++ b/lib/ripple/ui/plugins/about-dialog.js @@ -28,7 +28,7 @@ module.exports = { $.ajax({ url: "http://127.0.0.1:" + port + "/ripple/about", - async: false, + async: true, success: function (resp) { $("#about-dialog-ripple-build-deploy-version").html("(v" + resp.data.version + ")"); } @@ -36,7 +36,7 @@ module.exports = { $.ajax({ url: utils.rippleLocation() + "package.json", - async: false, + async: true, success: function (resp) { $("#about-dialog-ripple-ui-version").html("(v" + resp.version + ")"); } From 0488f47a399df6918fddc29297b6fcf37033e12b Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Tue, 4 Oct 2011 16:49:59 -0400 Subject: [PATCH 164/182] Fixes Issue #176 - Hardcode build & deploy port until framework issue is resolved --- lib/ripple/ui/plugins/about-dialog.js | 4 +++- lib/ripple/ui/plugins/settings-dialog.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ripple/ui/plugins/about-dialog.js b/lib/ripple/ui/plugins/about-dialog.js index 31c0e338..7ff9dbd9 100644 --- a/lib/ripple/ui/plugins/about-dialog.js +++ b/lib/ripple/ui/plugins/about-dialog.js @@ -24,7 +24,9 @@ module.exports = { }); }, show: function () { - var port = window.stagewebview ? stagewebview.serverPort : "9900"; + //TODO: Restore this line once framework issue is resolved + //var port = window.stagewebview ? stagewebview.serverPort : "9900"; + var port = "9900"; $.ajax({ url: "http://127.0.0.1:" + port + "/ripple/about", diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index ccf1ddc9..3b6ced6d 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -43,7 +43,9 @@ var db = require('ripple/db'), db.saveObject("build-settings", settings, platform.getPersistencePrefix()); } }, - port = window.stagewebview ? stagewebview.serverPort : "9900", + //TODO: Restore this line once framework issue is resolved + //port = window.stagewebview ? stagewebview.serverPort : "9900", + port = "9900", host = "http://127.0.0.1:" + port + "/ripple", progressContainer = jQuery("#options-progress"), progressInterval, From 12665319c78c2f13cb627e2cb7cda23a80aebc5d Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 5 Oct 2011 10:39:34 -0400 Subject: [PATCH 165/182] Lint fix --- lib/ripple/ui/plugins/information.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/information.js b/lib/ripple/ui/plugins/information.js index 96a6bb48..13d409cf 100644 --- a/lib/ripple/ui/plugins/information.js +++ b/lib/ripple/ui/plugins/information.js @@ -84,7 +84,7 @@ function _updateBanner(icon, count) { if (icon.indexOf("http") === 0) { iconImg.src = icon; } - + countSpan.innerHTML = count > 99 ? "99+" : count; } From 6b670ecdb1513c7b661fd28a7a45b1ee27f0e4fc Mon Sep 17 00:00:00 2001 From: Dan Silivestru Date: Wed, 5 Oct 2011 11:41:44 -0400 Subject: [PATCH 166/182] update omnibar to update url & persist root #185 --- lib/ripple/ui/plugins/omnibar.js | 16 +++++++++++++--- lib/ripple/utils.js | 2 +- test/unit/utils.js | 14 +++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/ripple/ui/plugins/omnibar.js b/lib/ripple/ui/plugins/omnibar.js index 54f0c84b..3eeb06a2 100644 --- a/lib/ripple/ui/plugins/omnibar.js +++ b/lib/ripple/ui/plugins/omnibar.js @@ -25,10 +25,18 @@ function _persist(url) { db.save("current-url", url); } +function _persistRoot(url) { + db.save("root-url", url); +} + function _currentURL() { return db.retrieve("current-url") || "about:blank"; } +function _rootURL() { + return db.retrieve("root-url") || "about:blank"; +} + function _back() { emulatorBridge.window().history.back(); } @@ -65,6 +73,7 @@ module.exports = { //default the protocal if not provided omnibar.value = omnibar.value.indexOf("://") < 0 ? "http://" + omnibar.value : omnibar.value; _persist(omnibar.value); + _persistRoot(omnibar.value); emulatorBridge.window().location.assign(omnibar.value); } }); @@ -79,13 +88,11 @@ module.exports = { } if (key === 39 && hasMetaOrAltPressed) { // cmd/ctrl + right arrow - event.stopPropagation(); event.preventDefault(); _forward(); } if (key === 82 && hasMetaOrAltPressed) { // cmd/ctrl + r - event.stopPropagation(); event.preventDefault(); _reload(); } @@ -95,7 +102,10 @@ module.exports = { document.getElementById("history-forward").addEventListener("click", _forward); document.getElementById("history-reload").addEventListener("click", _reload); }, - currentURL : function () { + currentURL: function () { return _currentURL(); + }, + rootURL: function () { + return _rootURL(); } }; diff --git a/lib/ripple/utils.js b/lib/ripple/utils.js index 1641156e..4fa06dcf 100644 --- a/lib/ripple/utils.js +++ b/lib/ripple/utils.js @@ -147,7 +147,7 @@ self = module.exports = { appLocation: function () { if (require('ripple/ui').registered("omnibar")) { - var path = require('ripple/ui/plugins/omnibar').currentURL().replace(/\/$/, ""), + var path = require('ripple/ui/plugins/omnibar').rootURL().replace(/\/$/, ""), parts; if ((parts = path.match(/^((http[s]?|ftp):\/\/)(.+\/)?([^\/].+)$/i)) !== null && parts.length === 5) { diff --git a/test/unit/utils.js b/test/unit/utils.js index b1453543..94e476dd 100644 --- a/test/unit/utils.js +++ b/test/unit/utils.js @@ -506,37 +506,37 @@ describe("utils", function () { }); it("with a trailing slash", function () { - spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI/"); + spyOn(omnibar, "rootURL").andReturn("http://127.0.0.1/UI/"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("without a trailing slash", function () { - spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI"); + spyOn(omnibar, "rootURL").andReturn("http://127.0.0.1/UI"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("with a specific file", function () { - spyOn(omnibar, "currentURL").andReturn("http://127.0.0.1/UI/yui.html"); + spyOn(omnibar, "rootURL").andReturn("http://127.0.0.1/UI/yui.html"); expect(utils.appLocation()).toBe("http://127.0.0.1/UI/"); }); it("with a subdomain", function () { - spyOn(omnibar, "currentURL").andReturn("http://rippledemo.tinyhippos.com/"); + spyOn(omnibar, "rootURL").andReturn("http://rippledemo.tinyhippos.com/"); expect(utils.appLocation()).toBe("http://rippledemo.tinyhippos.com/"); }); it("with simple domain", function () { - spyOn(omnibar, "currentURL").andReturn("http://rim.com"); + spyOn(omnibar, "rootURL").andReturn("http://rim.com"); expect(utils.appLocation()).toBe("http://rim.com/"); }); it("with simple domain", function () { - spyOn(omnibar, "currentURL").andReturn("http://rim.com"); + spyOn(omnibar, "rootURL").andReturn("http://rim.com"); expect(utils.appLocation()).toBe("http://rim.com/"); }); it("and returns an empty string when about:blank ", function () { - spyOn(omnibar, "currentURL").andReturn("http://about:blank"); + spyOn(omnibar, "rootURL").andReturn("http://about:blank"); expect(utils.appLocation()).toBe(""); }); }); From 7ddfeaf1d4bc3ec8a7a841c3407b066be59502f5 Mon Sep 17 00:00:00 2001 From: Dan Silivestru Date: Wed, 5 Oct 2011 11:58:21 -0400 Subject: [PATCH 167/182] bug fix for when config.xml is not present --- lib/ripple/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/app.js b/lib/ripple/app.js index a4e3804d..e3820b3f 100644 --- a/lib/ripple/app.js +++ b/lib/ripple/app.js @@ -40,7 +40,7 @@ _self = { // TODO: WTF figure this out, platform is empty object when require at require time // could be that the new platform _getBuilder code dies when called, beforre it is initialized var spec = require('ripple/platform').current(); - if (typeof spec.config.validateVersion === "function") { + if (typeof spec.config.validateVersion === "function" && configValidationObject) { return spec.config.validateVersion(configValidationObject); } From 0a5e4de7b296cdb3718eb79288609667b2ef607d Mon Sep 17 00:00:00 2001 From: Brent Lintner Date: Wed, 5 Oct 2011 12:50:04 -0400 Subject: [PATCH 168/182] dont persist singing password to local storage (webworks handset/tablet) - #177 --- lib/ripple/ui/plugins/settings-dialog.js | 32 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 3b6ced6d..0720defd 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -49,6 +49,12 @@ var db = require('ripple/db'), host = "http://127.0.0.1:" + port + "/ripple", progressContainer = jQuery("#options-progress"), progressInterval, + _passwords = { + "signingPassword": null, + "devicePassword": null, + "csk_password": null, + "p12_password": null + }, _self; function missing(settings, action) { @@ -57,6 +63,13 @@ function missing(settings, action) { }); } +function _isPasswordField(id) { + var match = typeof id === "string" && new RegExp("^" + id + "$", "i"); + return match && utils.some(_passwords, function (value, name) { + return match.test(name); + }); +} + function table(action) { var _table = $("
+ + Click with the mouse to manipulate the device.
+ Hold the Shift key to modify 'alpha' +
+
m / s^2
- Click with the mouse to manipulate the device.
+ Click and drag with the mouse to manipulate the device.
Hold the Shift key to modify 'alpha'
"), _row = { @@ -64,12 +77,15 @@ function table(action) { var id = "settings-field-" + item.toLowerCase(), input = "", save = function () { - var s = _settings.get(); - - if ($("#" + id).val()) { - s[item] = $("#" + id).val(); - if (opts.type === "number") { - s[item] = parseInt(s[item], 10); + var s = _settings.get(), + val = $("#" + id).val(); + + if (val) { + // if signingPassword is changed above, change this line as well + if (_isPasswordField(item)) { + _passwords[item] = val; + } else { + s[item] = opts.type === "number" ? parseInt(val, 10) : val; } } else { @@ -167,7 +183,9 @@ function create() { function populate(settings) { var fill = function (action, prop) { - $("#settings-field-" + prop.toLowerCase()).val(settings[prop]); + $("#settings-field-" + prop.toLowerCase()).val( + _isPasswordField(prop) ? _passwords[prop] : settings[prop] + ); }; fill("build", "sdk"); From b050727e8768ad95b642617191b0ac2da8f0c863 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 5 Oct 2011 14:17:05 -0400 Subject: [PATCH 169/182] bumped version to 0.9.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3516991..d1d8c335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ripple", - "version": "0.6.1", + "version": "0.9.0", "description": "A browser based html5 mobile application development and testing tool", "homepage": "http://github.com/blackberry/Rippe-UI", "author": { From e53fdacfa81040bf8356803a900b1d91bba99eed Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 5 Oct 2011 14:56:35 -0400 Subject: [PATCH 170/182] Removing links from about dialog. --- lib/ripple/ui/plugins/about-dialog/dialog.html | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/ripple/ui/plugins/about-dialog/dialog.html b/lib/ripple/ui/plugins/about-dialog/dialog.html index 6b3aaf1e..48ef3250 100644 --- a/lib/ripple/ui/plugins/about-dialog/dialog.html +++ b/lib/ripple/ui/plugins/about-dialog/dialog.html @@ -5,21 +5,13 @@
  • Ripple UI - (v0.9.0) + (checking...)
  • Ripple Framework (v0.9.0)
  • Ripple Build & Deploy - (v0.9.0) -
  • -
-
    -
  • - Ripple on GitHub http://blackberry.github.com/ripple -
  • -
  • - WebWorks Developer Site http://developer.blackberry.com/webworks + (checking...)
From 21409f9646bc58a3829c525f9037ba51e62b1b8f Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 5 Oct 2011 15:47:22 -0400 Subject: [PATCH 171/182] Adding package.json to cache.manifest. --- ext/cache.manifest | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/cache.manifest b/ext/cache.manifest index cc5e9c46..40dc3d85 100644 --- a/ext/cache.manifest +++ b/ext/cache.manifest @@ -2,3 +2,4 @@ CACHE MANIFEST NETWORK: * CACHE: +package.json From 5f880b6a38536c9ee6006ef2ed7f316aac25dad7 Mon Sep 17 00:00:00 2001 From: brent lintner Date: Wed, 5 Oct 2011 20:32:13 -0400 Subject: [PATCH 172/182] moved local npm dependencies to package.json, simplify configure script --- configure | 2 +- package.json | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/configure b/configure index fe8f0be3..f1076d5a 100755 --- a/configure +++ b/configure @@ -1,3 +1,3 @@ npm install -g jake jshint csslint uglify-js -npm install jsdom@0.2.4 jasmine-node@1.0.7 jWorkflow connect argsparser +npm install git submodule update --init diff --git a/package.json b/package.json index d1d8c335..5846020e 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,19 @@ }], "bin": { "ripple": "./bin/ripple" }, "main": "lib/index", + "dependencies": { + "connect": "1.7.x", + "argsparser": "0.0.x", + "jsdom": "0.2.4", + "jasmine-node": "1.0.7", + "jWorkflow": "*" + }, + "bundledDependencies": [ + "connect", + "argsparser" + ], "files": [ - "www", - "thirdparty", + "pkg/web", "node_modules", "README.md", "LICENSE", From 1f58ecb55952e5608063da5a8a02ea23398511e6 Mon Sep 17 00:00:00 2001 From: brent lintner Date: Thu, 6 Oct 2011 15:34:19 -0400 Subject: [PATCH 173/182] hacked a fix to build/package ui code, passwords were being left out since they are not in settings anymore --- lib/ripple/ui/plugins/settings-dialog.js | 51 ++++++++++++++---------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index 0720defd..bfb68078 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -49,12 +49,13 @@ var db = require('ripple/db'), host = "http://127.0.0.1:" + port + "/ripple", progressContainer = jQuery("#options-progress"), progressInterval, - _passwords = { - "signingPassword": null, - "devicePassword": null, - "csk_password": null, - "p12_password": null - }, + _passwordFields = [ + "signingPassword", + "devicePassword", + "csk_password", + "p12_password" + ], + _passwords = {}, _self; function missing(settings, action) { @@ -65,7 +66,7 @@ function missing(settings, action) { function _isPasswordField(id) { var match = typeof id === "string" && new RegExp("^" + id + "$", "i"); - return match && utils.some(_passwords, function (value, name) { + return match && utils.some(_passwordFields, function (value, name) { return match.test(name); }); } @@ -78,15 +79,11 @@ function table(action) { input = "", save = function () { var s = _settings.get(), - val = $("#" + id).val(); + v = $("#" + id).val(), + val = opts.type === "number" ? parseInt(v, 10) : v; if (val) { - // if signingPassword is changed above, change this line as well - if (_isPasswordField(item)) { - _passwords[item] = val; - } else { - s[item] = opts.type === "number" ? parseInt(val, 10) : val; - } + (_isPasswordField(item) ? _passwords : s)[item] = val; } else { delete s[item]; @@ -245,7 +242,7 @@ function getSimulators() { url: host + "/simulators", type: "GET", async: true, - data: _settings.get(), + data: _settings.get(), // assume no passwords here success: function (resp) { var sims = resp.data.simulators; @@ -322,17 +319,27 @@ _self = { }, can: function (action) { - return missing(_settings.get(), action).length === 0; + var settings = {}; + + utils.mixin(_settings.get(), settings); + utils.mixin(_passwords, settings); + + return missing(settings, action).length === 0; }, show: function (action) { - var s = _settings.get(); - populate(s); + var settings = {}; + + utils.mixin(_settings.get(), settings); + utils.mixin(_passwords, settings); + + populate(settings); + $("#settings-dialog").dialog("open"); $("#settings-action").button("option", "label", action || "")[action ? "show" : "hide"](); if (action) { - missing(s, action).forEach(function (field) { + missing(settings, action).forEach(function (field) { $("#settings-field-" + field.toLowerCase()).effect("highlight", {color: "red"}, 1500); }); @@ -350,6 +357,7 @@ _self = { perform: function (action) { var settings = _settings.get(), + data = {}, poll = function (resp) { var notifications = require("ripple/notifications"); @@ -383,10 +391,13 @@ _self = { } }; + utils.mixin(settings, data); + utils.mixin(_passwords, data); + $.ajax({ url: url(action), type: "POST", - data: settings, + data: data, async: true, success: function (msg) { _startProgress(); From 33fcf17b648d10ca9504d4e12f05453f0180c940 Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 6 Oct 2011 16:27:06 -0400 Subject: [PATCH 174/182] Fix for config.xml fetching when ripple is a chrome extension. --- lib/ripple/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/utils.js b/lib/ripple/utils.js index 4043d3e3..b26c2d02 100644 --- a/lib/ripple/utils.js +++ b/lib/ripple/utils.js @@ -169,7 +169,7 @@ self = module.exports = { } return path; } - return self.location(); + return self.rippleLocation(); }, rippleLocation: function () { From 01e5363033022031c46b44eea83ed134108594bd Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 6 Oct 2011 16:31:15 -0400 Subject: [PATCH 175/182] Updated test for appLocation --- test/unit/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utils.js b/test/unit/utils.js index 9da45dfe..e050f5fb 100644 --- a/test/unit/utils.js +++ b/test/unit/utils.js @@ -544,7 +544,7 @@ describe("utils", function () { describe("when omnibar is disabled", function () { it("returns the window.location", function () { spyOn(ui, "registered").andReturn(false); - spyOn(utils, "location").andReturn("http://www.rim.com"); + spyOn(utils, "rippleLocation").andReturn("http://www.rim.com"); expect(utils.appLocation()).toBe("http://www.rim.com"); }); }); From 87e56dca09fe6238fe676328e1ef495160d12137 Mon Sep 17 00:00:00 2001 From: Gord Tanner Date: Thu, 6 Oct 2011 16:48:30 -0400 Subject: [PATCH 176/182] hotfix workaround for #190, not ideal but gets the job done --- lib/ripple/bootstrap.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/ripple/bootstrap.js b/lib/ripple/bootstrap.js index cd934489..611e6045 100644 --- a/lib/ripple/bootstrap.js +++ b/lib/ripple/bootstrap.js @@ -36,12 +36,32 @@ function _createFrame(src) { _bound = false; _bindObjects(frame); var id = window.setInterval(function () { - if (_bound) { - window.clearInterval(id); - } else { - _bindObjects(frame); + if (_bound) { + window.clearInterval(id); + } else { + _bindObjects(frame); + } + }, 1), + ael = frame.contentWindow.addEventListener; + handlers = []; + + //HACK: This is to get around a bug in webkit where it doesn't seem to + // fire the load handlers when we readd the iframe back into the DOM + // https://github.com/blackberry/Ripple-UI/issues/190 + frame.contentWindow.addEventListener = function (event, handler) { + if (event === "load") { + handlers.push(handler); } - }, 1); + else { + ael.apply(this, arguments); + } + }; + + frame.fireHandlers = function () { + handlers.forEach(function (handler) { + return handler && handler(); + }); + }; }); return frame; @@ -72,6 +92,7 @@ function _post(src) { document.querySelector("#ui").removeChild(bootLoader); } + frame.fireHandlers(); event.trigger("TinyHipposLoaded"); _cleanBody(); From 74f136d8f7475d225513e4b47df8986919624c5a Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Thu, 6 Oct 2011 18:21:24 -0400 Subject: [PATCH 177/182] Lint fixes on epic bootstrap hotfix --- lib/ripple/bootstrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ripple/bootstrap.js b/lib/ripple/bootstrap.js index 611e6045..b6512fad 100644 --- a/lib/ripple/bootstrap.js +++ b/lib/ripple/bootstrap.js @@ -42,10 +42,10 @@ function _createFrame(src) { _bindObjects(frame); } }, 1), - ael = frame.contentWindow.addEventListener; + ael = frame.contentWindow.addEventListener, handlers = []; - //HACK: This is to get around a bug in webkit where it doesn't seem to + //HACK: This is to get around a bug in webkit where it doesn't seem to // fire the load handlers when we readd the iframe back into the DOM // https://github.com/blackberry/Ripple-UI/issues/190 frame.contentWindow.addEventListener = function (event, handler) { From 44b2a333448996fb23a61c9b8e9517698685ef5c Mon Sep 17 00:00:00 2001 From: "Gord Tanner (macbook)" Date: Fri, 7 Oct 2011 10:16:25 -0400 Subject: [PATCH 178/182] fix for jQuery ready event handler expecting an object parameter --- lib/ripple/bootstrap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/bootstrap.js b/lib/ripple/bootstrap.js index b6512fad..839f7d71 100644 --- a/lib/ripple/bootstrap.js +++ b/lib/ripple/bootstrap.js @@ -59,7 +59,7 @@ function _createFrame(src) { frame.fireHandlers = function () { handlers.forEach(function (handler) { - return handler && handler(); + return handler && handler({}); }); }; }); From abd33cab6885d86520c78d578cdae9483121ca6e Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Fri, 7 Oct 2011 15:40:26 -0400 Subject: [PATCH 179/182] Fixes persistence of signing passwords to database (now no longer persists to db). Issue #177 --- lib/ripple/ui/plugins/settings-dialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ripple/ui/plugins/settings-dialog.js b/lib/ripple/ui/plugins/settings-dialog.js index bfb68078..105e54ea 100644 --- a/lib/ripple/ui/plugins/settings-dialog.js +++ b/lib/ripple/ui/plugins/settings-dialog.js @@ -66,7 +66,7 @@ function missing(settings, action) { function _isPasswordField(id) { var match = typeof id === "string" && new RegExp("^" + id + "$", "i"); - return match && utils.some(_passwordFields, function (value, name) { + return match && utils.some(_passwordFields, function (name) { return match.test(name); }); } From 5e1f723c5d1d841deffaac5aa15364bfec0cc5aa Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Fri, 7 Oct 2011 16:46:45 -0400 Subject: [PATCH 180/182] Added F5 key to refresh content on web build. Fixes issue #168. --- lib/ripple/ui/plugins/omnibar.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/ripple/ui/plugins/omnibar.js b/lib/ripple/ui/plugins/omnibar.js index 3eeb06a2..4f1a4c2f 100644 --- a/lib/ripple/ui/plugins/omnibar.js +++ b/lib/ripple/ui/plugins/omnibar.js @@ -96,6 +96,11 @@ module.exports = { event.preventDefault(); _reload(); } + + if (key === 116) { // F5 + event.preventDefault(); + _reload(); + } }); document.getElementById("history-back").addEventListener("click", _back); From 8085dbae8042ec3b45bbfd7111fb2a702971a55e Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Mon, 10 Oct 2011 21:19:12 -0400 Subject: [PATCH 181/182] Changed build script to call jake deploy instead of jake. --- build/scripts/build.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/build/scripts/build.sh b/build/scripts/build.sh index a6037ca9..a737bf2d 100755 --- a/build/scripts/build.sh +++ b/build/scripts/build.sh @@ -23,15 +23,11 @@ rm -fr $BUILD_OUTPUT mkdir $BUILD_OUTPUT #call jake -jake > $BUILD_OUTPUT/jake.txt +jake deploy > $BUILD_OUTPUT/jake.txt export BUILD_STATUS=$? -#if jake was good then run jake tests +#if build was good then package zip if [ $BUILD_STATUS = 0 ]; then - jake test > $BUILD_OUTPUT/jaketest.txt - TEST_STATUS=$? - zip -9 -r $BUILD_OUTPUT/ripple_ui.zip $RIPPLE_BUILD - exit $TEST_STATUS fi exit $BUILD_STATUS From a58b8489544dc003681d010b071e52ff98d9316f Mon Sep 17 00:00:00 2001 From: Nino D'Aversa Date: Wed, 12 Oct 2011 09:30:54 -0400 Subject: [PATCH 182/182] Fixed screen dimension for Style9670 in device spec. Fixes Issue #200 --- lib/ripple/devices/Style9670.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ripple/devices/Style9670.js b/lib/ripple/devices/Style9670.js index c690bfa5..bad9ba4a 100644 --- a/lib/ripple/devices/Style9670.js +++ b/lib/ripple/devices/Style9670.js @@ -39,13 +39,13 @@ module.exports = { ], "screen": { - "width": 400, - "height": 360 + "width": 360, + "height": 400 }, "viewPort": { "portrait": { - "width": 400, - "height": 360, + "width": 360, + "height": 400, "paddingTop": 0, "paddingLeft": 0 }

N~cC99KeIj}h(oA&n7|-8@h|ZdTe-E%nVlsXDEMRQBzIA#4Rg-n#9GjJ$vso}Bfb zDB~IYl?BW(utN)tO^?1VZEK1z)hQI;|1lbG_JVyNHri37xLRDh3FaCvq|K9Op3YrP zXzt&}W0Wz93%{FwRlUduFjS+l#1`A7PFevC342oxYNv4Y0Uj$r6Bxc!L|<2qS>qdWt=MiTcfN|f0|;eSVA3&l5FJ!tG)os+ z957*SC$cmQWah7tN{F{zCRq*DLLd=QLN9eyb*~do$Uqban{H~n_Aex~sXFxU^Oh*B z^F*Db72G@5tO0YU5j>&_9qr`P*BnS1Ys(MD`mEM7*79EV@G^J4PwVK1I&yk1BcDxB{lVOXRQ3AeZ<;k~@9K_xS*rFv z??|3Vm{DzL7`^b)cCLBc#t=phZU>>!Ii#>j!)a<^7#J0pRLaGQI=!}8ykPO8jHWJ= zDhxlU&3RZfs7sEmqO44$_k1MyE@WLqBEDD2`bm3ohMyGZpQd8Ki#JdWJJDt)J`Eoh zhO;8KSl+7&yg9)eeF)m=e15>*2fuZ{4az^Y6^rwiHY!_l-Xhk+xND@omTrB>crxd) zx5PG#pAb27OzS$9#7A<_AN21C3u#Ag>kmbYbT*B!FIx{!^U%68;CxqPe3M`7F2!&r z+Pr3~7DiL(AA0>Ql|vF57H`!pomf=_qNDjKUQXz=%mY*4wH@555U%~mK^e@anWKC+ zA2rk69a!0Q*nZ*|gQ@^B*X`9qA^p)2%{emk$k%+(4wMrD8SOM63+5Y{@llu)dGD2a z{C@6gJ1=&*lrS)tzu52CO6{ElX3nGYv*U!Pc~*O>EA!kv`=ZE==G^J~>PJ-pgD!j1 zJL2{GD(u`;F-Md(i+OAN&)x1zU|r)b015NXL@0NQ9xjtFgIp#nHZ+ySPSuXWJ`D!m zwW@+xPH;;rkg2WQ!Nbi${4J$vlER++9_Jr=Z)a7)I`=^R7|e!ydBm){HxKddb676| zeVMV1>#laZH2SJ+|`Y3+$;yKIQ)p7Z?k(qZyuC;EF{fx z6kDOvSyg)4Jx7}nL&9~5@XT-c(k+(w^HTnythrKj;w{u9%}m>~8eNU}OcfFejod-5 zIC3&8?0Sz?2u|V$J-!(bl#q)I%5dlt4|(mH2oqLgP^#u?IIY9@QKpP!bLdv@{V@)9 zid-b2>D)a)l8BIYc-3_&2Q1+mMuLu4A3yBhgzk^KKlggNzB@Lm5_3oDDc`UIR9uq< z>xlE!RjDr#BW>F?2X`jK__Ek9n58u5W*j)`F5K_&V=Tf8migY*2@hM737-lxh_BL? zf!yM!EFT|wT4|$qY>EVXe{`RAKhfZKWlm|%l3Qk&@((sLkBFEuEH1+KG+88fc&w3;dp3;^ zr6t4A_i52U{1S}i<-s{Y@F{%#`W+n(Wjci(K_CG^?~Xzo$GSGDz^&}!mD09EC47kX zeLS8OaUX~^?EVd=bLRd*!nsj?+|0F(&A#B*1-wGx84}AK{Le>T7_5lP>ZU8R(Y_V5gE%vbnTYB8eD=dvX_FdQ=DF+3BEkSs2* z4fp5A1eu|&(Tb~acL%D*Y+ah?vLrX^WP$CsEsCmq`5D+7OFY?PE`C#?79bv@FJL`UZZHri` zW6I8LKw}`iu7_@fQ!g=AocM|&TQToe8$5`hllEPW4y(QJ^LcwO(ynV|JoUMOU%FrE z#C>6TTVM`ym4~o<5>IQGNV`+ge*KX*(irFCnV4<*{?m!oF_n&uN8d!KS#6iURdy{fU|tYceP_XrdaZ zOvr8sUb!O=wbs!na3?UGa;lHBEtJs}13I(ukSl;Ak+i=jQ?l5g z0gaDCT#xiyt;pP!1-!coJlaDZiVu8~izs*g&cq-@{AqLNEbgW4R=_$S7cYTxSkoop#RZ7QAbXc2Y$=A_T zm(cJ>LHr+|W~_TX&HpGKAIro3p*uGH(;pwFi=vhsa;C21DxnDf9{;30HCjEU0EO0p3iDrW@4xMqyGG;45WOuDn*YldI z{?E6APqM6EceiaWyrMRA4vk&H3@G_&@D~nma>jc2gcy_Vl;kL-LOtar%KWV;kmRfV z6gd$#=^J5;h?SsoM4A>61EYQo=``;+3xG69T0S}H@mee;GBBLXy9z0S)bK>iB_#n? z1i25G7!_eL-|7hS1(&UhQev6c>euth?*QJC5gFJK8Q`91P1<`eBGP?v6P!BrD#m@( zSKvVfjGrGlP=d{}ADW?E-5k8;g{7&chVNiQmz{HDv93cW3bFERmD;2fxcfhL_wtAf zh4Ru#N3Ac38-~3zg+^3jWLgZuqKZ?WJYGu!6UfciE%jcrNhwD9G-K)_@^M^oh*usM zwOQiKqjx<-nzdd2?*5tM%R`fxpzGSG!}eiQ0MKsWzr?WAqTZDd;13nB!hNNoBLX6k z;O`VueJgrm>l0BYuyd0oeIm!jDp&o`Jo=ltennZ}e9M#@{6;c~R;&u{dOqyk6R%pV zs&dBk93?GId9fGn4NS(9RcnIRRsT>;UYvP3px=|lMv2oOKnXFHkstSeZG$zlZ`=G} zb`b*6m?a1$Yfq@wF3YpX{)691tpHLiU|U&gz&mK@DepX&moI;fwp%<6MRpaFI_%&+ z|JA&O!7}%3;D5Tw5319MFF*g(#(H6CdR5U=nj7|uioGupFshIGx>g2_IZlMMyn1nP zW8}I}@pq*I(I9bX;x@7ua3gctX0C*xdK&~rl1TSJ#d>neVb>j3`*CExfqx~<5`M+4 znj|LnV~gxe%jAbK>yyrPt~0t@=(E>?))Rl$-n%uyDAzFeRaw?isu0s?k+*OOkoCQ|US91V+DnU^Y_MxID8569NtD{m3Uwv35kZ7*_Z&3n~VBO3CIG+UKtn zp^p_|D!eJo1)n#fBLJO1UQl8`PVZ?Nyg8KIw2>S^tG`B9{EB+~0bp7Vg;iRk^<4+@ z)ZNQThzLgrn_ych!{d)n%|@+kO6yhP=$mdPrDN?GkWvr|risj!tfLEWBG#QD!&}k@ za|ggBBlYGNw<{v{k~k*ZxN;ho21^Bkk!tUJ3_jegj8wH;J7!mro|`!7M6Jb3Q$5K} zd{4>j9;sZOlJmjO_=k;yV9>GLy^IOeA6*0nv0@hyZ|(6Yt#$E3Sct3`8l|H?QntG! zPlJRRX*`Q-2DWzbk=u1cZ>!WYQp=BB(lW}|>wWF(V0KlPQw=FK!ku~4+VXv1(JeSs zRS^FS-qopCbLnPYg`(^A&+(bv)E}c1cXR1>Q_OZxfztI>)5^l=Bly?pTqkHtty5MF zoA061>E$RP<&f7hww!lMZZwp3fh4+&0`$1sZe;i|+w#oY!4?oTO0>JA(GfK8Fb!#2 zv{(lLI4-dRiu6r5*juj{kwT?hOr}&(ngK5kK zukxXSJSnj~io5uLz90`AFUqL1MGO^@Xhn`oXb(afm*vd?5zu{?B!j)GnW>%_+xyb} zRn7IIToAVAs1=n2R{Md|4*=JWW;uBt0&qD)VT1E|A13C@Ah2*XYI2~L>-;uVYS**j zPrWmw1IEkx0UXAYT%O=qrSo?*3kI=JymG9z!us2 zgFc^!<3Zv9+L@c|Wxt#DK+u+^4bTOMMGL7-T9qCsSG}$s)5O=S2idc+h$Wb@vJi6z zCnBt?ekkOOLk6a8x-Met)R6znthdzq7~7QVvaHIP}wbv_H%Te5BDnR7Amg`o9RNA{qQHKpDot+=A?d3p+rS1Wl zU~u($jKz6-Y)5LLc4pKZ#rMZgd=1xiDif07sAFIw-TT#8-CX{bSc&=U^@@^blJVWG z7Ut+DQQ|&~UG`sdoz4)QZ!uPlWW!>kCVzUxoAS65SN^qKD2s0Qb0)+MWyq-Sm(Q43 zBWqbbAUy~0Kr#Zm#Jw%3##7Y>VXPRzdFK(k6o{Mke>|;(^$E@ibYW?6Xoxb0GglPu z27NbAFUJdopt7ZKY(%7nQ4m{IJF@RJLalY0_8rfHW%ByT>ciMf&a8)@(GqTJo^OE7_`NJzObj1rXo#x{~u(lh6t7p$K!`Z=v)!-SoWGhv*Q zE6+G}I7p`LkBl0rXp5+asZBN3k!(iLqJEDg3OGO`B7=DAmo&00H_~I+HwK$Z57!|e zwpwsqe(>?CAvnH<^j)THy-%RKHOx=2gxTAm_F{?DYBq+WR*2N0i?WnM#@s;!h{HVf zWUwAmMEcYL>wQYD#d$k_a7$QheiJ9;}d^PxI$XT0@Y*WsRk3lkuJE+kKJ zL!wg?!batk{Y#A6pt47~rhyqip;V)NSr2pcR<0psf#dNYHZ1kSWYo_ibg=UrzoalN zP&(^m867PjaDF1uY-TIX?N$SS8=iX~{yQvOK}_ZX$)3bs?!ty4Tp#hzpLw_SgdD(+ z%&j~dsIRrjmx8Y-9_0GXl7%I*OxK%<7Dv=-4JOFH7K4X~G{h-8@*+}GuVfdTZOVpJ z7FeG&%**g6Ta+t=+f%L^VZht@aU`9TsD8WWWhd%1+Idy1NXbcEf#B1Zv zv27P8P#}*)OuS|yt`gZ1b2y2f_|m>0Lql~CON1ma8hUw6P_ntLM4yONK11>Q5^@QljnTng;bgXTPk#NE~#s$11V3ME#F#~e< zG=HGb=U4QI_!R@rL;hW@s&B)d2)~%Qdh<~y8TF->Z}%k5p(P{d(Hui0Iornm2`~Ho#6-4#KX0C++R|)9G!R(TZ z+;mcRUCa<1c7Ckb;fx%P+LTicO9Lr${@-e&Y!@~YD;btWq2$PZR6P#hdbT5r@ON54 z+e2|UHhah`LeY{zMe2yyfb8Z5BNd2N=dhI`L1}!1nX4kXegw=FXYI&ho7uyzf(BFk zwWZ*S9HjhA+QVY)cgu0>>;g1}ax+f%GMRiDlp%`bXQ$q5N^|PRW9ZlbM6JszK_j@( zk@z3R$3JeQHdKEGstzYm-W^Ri7zR&7&{a2OgWmcR!&N8qhZ{t+QM#H4Cj1s;BiwY4 zUztRYNmQ*01#~Nf=Y*xo>$@v1PcxBxc(-Fits`A;0o~@bipbDytw6TXtR>B7@yc$& zx9gx}Fdt@F)TukyMXmK+Y}Oc?bpQQY)-@aUK`5AV1DQl4>5ALW*9;7Ss7xqi83vMm zD;y|JBen$vuyW~2gnSq_z;>yz5(r)Dac#kS*Y%h5oEFAVo0|Na+Q$UmIgDx|+ z+^lNWwnrvCB6||ql;v#}&i&IM6bAZGINvm|!GXTr1b3)-6M7Cy}5(buE+u`q)Y+PE|Hi`_!k2*AP86qD*O!ti*N*F>C9q1ql5f`cAZhdxF z5# zK_%L};YX@pZ18TGa^*H^Fq07$z`>to497vhnxP%R@J{7V99=xkbXKO-C$W?E<61X4 zWAWO)TxFw2$$6p)VVJ;Obe@w2YU?$^HY<^2Hd9ukshg8U8e@dz;T6hN0OML@)z!dl zsf!KHLH@#=4vWRF5s`+s);SR!%~hDjFSU@lk%hNlN+$SB)G;-!`O?CnA@Z%oS?92^ z9C;$RxjC*w&ZHmRA{1-q+VU>|1Ysa8?s$aj&@EQ$thJp6eb_C2IT>qj#hYki)qD8X zJOlPRio3j|P&HvvI*Qku5Osk^H4EvDLu6x49r*4TdiWv+N8<0q4na2%IBg2(Tk%M~ zK4RhZv&1kxueHDrbPAb6h7N#0(tolEt-q6@$u{GL6|NwVVb&B4t~h_t=kQI(JdmyG zH3i+MJMUYK5^Ea|1+VB6^{W({WXYsk66Kz%yw-IfLNg~Vumzvb^v4^Vy0o%y%Y{uG z_Au5UtK43NcN`Nl;YG9CW73mt8(9KV+KD%7rft(5BgDC3e1=|2#X%3fy2}GBUZ%EQ$jzV5pHL<<+$g-I7^769qp?DU<86+DwQ`pk#i>4E| z+VX)mQxc2V-~09Gri^Xt3U&M6+AO+hkO|Bf57DDjY@ESi(cA@j@fe~-?aidRAZHdg zrvzCrU(VjtzT4E!yji|!t4Sue{-Q{x-vIKev*iq@axj?;yZX7hPaI^lS(W1oj#$so zpBEH21B!y#ZqSB=RDTunHGbKtxF#Oxaxa0jZ8{W3eOv^U;IRaCPW6!<-h|bQGoi$e zJ5!V(tSnO^;xV)qldirz^uBy3&4cj~?ek_Cfe`x?S-vX(z z={69&9K~V-Z0lY0&lMzN^nW`|(Ws4jGp$96JmtFTYDnv};|2(_1!zxCAW09yqcZE@ z6{Jw^N0ATuRAS^q>!Kr@@vJ7rWJs5k_;}Rta-AYnYw6fFdlrR?5Ek=FH~v>sXu|es zO1Y3(hrItSKJo%Ru;xhyiK~vk?^67*8v6Sv<&@V*Q12cRw^y)#*`6Uct(Ht!bQPsF zoH23((y-4Ob|>8{gvt_o#P%UBX#s{)@j$2&91jvR_yAbAh<4&a+9?-c9HE5yr>0g( zY*b-#!=-Y=t2?5=wJkJ8>p8=bzv4++WrY*0@Z1p@P?T7JSK;1{-^gpMNpC_DDM(=C z5V<)HDptK66TgxM@a2It>+g?wbrT1?Qa875=`*xZb6DqBN^dI}=s{oW>=_5yHo1xc zt@G(7=izb64JgIo9NJg*ep5EqI-5LPMLB!Taba|frtNKcKSD2O$`9s`jnqJihq!X; z#5pj>(0I@u|2Cbl%W}+hAjG#`g2Yvp;XGnOyInyvWO52r!cr;5dk2R@>TI=Bk2Tjy zb+m!!J!42(&ge*JiT}-N%&pjK1b>GR!B+RZljrfE*ff3Jo+ zS-)HgCdc@2CyYZF4rlI0j2@+hUj1l6cb?-<0QqQm(h#fx(=r(9xyZhu3>EMovA^2oANV4NKQp z_0Lm=Rbf-ZrrefQ=|onB;cQ?_LGUQKKBgm3Fc7ITKjDh$kjLBzrLqZ*!hGa|$yW7P~PN<5To;zRokj&~xI6_KtqP-rTM7QFKIpYO$NNc_^sRVx8#I z^0Ta4@TmRiojs`s{=4o+(~~PVUL`>r2Sj1?T*F)2z^R$acrsYMAcB7V?e*1Y(vK8W zjexq4zr8o1YpI;GyvnOj=8W0b$Ha-dIbpRX%+7F0!BL<3{%Uu*qD*~KbD*>9@$8#S zO`HQj4^i!I>wWDCvM}V32z)N*cYsP@YmuXMW5D!pJ<2n)@`~mNBqW+(k6#md72~7sjC>iR$z^b=;-?)~ zmi^4pQJN$p^LQfugo#(IhWd#A<&~{5SAAU<82ysMWjBhAU;D}!_UoxtkZxx0%{SG| zu|7B1G{N<+N(W4kS@@kBj0mO;tA*t_8-dVz!urF})sMz+WXc+MPAQD?TK4#%d?H##RbhvcH-NG)x*-m7)0G#Y;$MTD>xFT+J&lKjT2?d_J(OH<~~2 zinlKyvEQPMeCOJ;5|`9sV=JHU54ggQwPsi&7CU7iELw7{vT+&_k!hA}18>~Pfq@AZ z3EK6>5LRLr+Q$zvoBd{e@&1$a&`m(k&p7Yq(kH2N4SR&We8N9dtE!k?p79Ja7R>^~ z8Q5?)O-x~3u#U6Wa~r2z8ND=T^`8oGhq9!7$!qblr^FXQy4pZiTg{tG_t87-P1y?r z{WoKomvtxd7hk&_|F+7BV`N_WjSQ_sQDH9x%}%z3dP|B$ofIWD-Dwf%exN8_w7xlQCB8zy`O#4 z=$6iF9GFVOhp@eCO>%x5ExahkMk~mqyBc)#>PGUAhozyo&bztDD=v1`#D~aKdA-jb z%brF*Uf1=9%Xs?^hY+NG0Hf=X{$=JX>XV%HOrqM~d^aI7G3XbmSj`JB@5IrQ?6QQk z`&(hCA2QyEmJQ7k-?2RrQSOEE_3}&Bjgm4Rt@s z?#OMyUP%2p`|WrVq3e*}`ozX^aPM}Kfbrve+P85=Co8W8O`;_d2}PY3E51q=OYT)) zr&d5a&xl>WIB%Dl3a2$~IaH{->0)I0l#EwIz@RTM(1gD}z6>C(Dw$eD~2YqtB zyo~cmVjr}bcP0JgHx7N(tr4~^_sCvf(RfKiypLTfuD4Tsj|@LqJDGjp%Bm5wKGaQj z>*)1u*~2ThKCGH-j0mNa*yf*|3cnd1Q${;|;d#)X(#kv2W7-j=%u(SF>i@&@n+UtS zM&>z`mRI=fJ7mGSrKhVsVsop%BuMhsLUWsMa5?zH7posS&)y?_Rq%8tS0_y^$ju5K zol0!Zs?gr@EFAZ83RypGcZ7XXP8tS$OaG$ZizK3b@Vv0RK5?8_W~5cKEsy0aI*Twj zlF8FSj|!^wWMhjV28z>@IE0|*qBe@t9vqK#R537#32!HBZ&X2tn(WwnlcYw%Q}F*7 z^xT*FU6NGZvUHZjcz~ylrTQ<9=E>3@PFSTGzfLj>UI3%SBK?1@uI_8b?U}h&8;(Od zb;ncLab3nt^=y*-k+%cElIErI*7kCOwAfM;=OBWnckeKHVfiKdtWRa~k60ghc9-~N z@rnKKH|1ryDY-ysdZZicjq5i{O7UET3mr|*$ORl3BF zQOEtwog)>h;1uHCQ)GFtg>d0@6|NCi@-JunEp)%b|lbw38Dwz?Qb$dxx3Fe}Z!fdZGu#S8a!VCKRHwZWL(j=G6$^6? zi7cKKA*2r4`NJ9!Q?t79(^pBZi_^sB)TxD39_moU9Wy$@7>l3P7%3L5yRWuRdN9n8BZ_Nirp_;x>El?{TM=y}AUfD)Pp3WJJakJN@AM_v zIyQUNR#R}G(=$6^3d{F5z4&U{jv(P%y<_n;;LZPOoatV6J!ku-1;snxcf@a_q)E@B)R33&Z13HOzz zlkveTK0d0dRoeuz9C#epcmL8=%z0(3(Qi|B9#8*rKpJwbV#$Emne4h{beUrv16i$8 z%e&W34{Rj^NWfw>8QnEl=26(_tmzyR@7mkglzn@QXUeeBxO$ybzIuvN^1QMLVQOa^ zmUKQ@*WQoXeqD=doeHKRI~xFsN-^bKQ}Faqq4M(SXHGWb{{5%@HNFviFyq}lSCeA+ z1@G7+LZ~iWdo9oy{0|&3;$VX_9;Cx&o(8d_DHmjn6Hj+br<-lUCJ5Z;^9O`a)6I8h z^`yr3sh4kemiE|3q^gcib!9l^HWuWo!#Zm3tp%B~CxUGn-Re$m9hE)c9{Ci9lx7ta z$94u4t&6-(uXvUfGHRy8Sf<)Gtls0p9YUxEn{RPD*Am!he`}$b!at=Pdh*{24vI7-XUTE+BA)2a`s^8657nq zMTF-0g}jo9WtbIjWUIm9T10Pe6!HwdX-^uD$vN!ir`;fstMR>MV+$I zMZ$X{N3lirT&n`QIgPo9<^(ApqP}R?k#$(VB#t69TL_X&G5D+5qPU7D72>X<+Y8g@ zL;M*(nqOZ2v#=j*gn-=W-rhz=f#F2R0z?l;S;9q|z!=}!O%V$rFHkafmv zMgGm5{725bZtj_n&a3kVm#c=oiawK-u^c?sf}FjWvs!eDx{eJCuw-;X>ktBs~4g9VjWIXd6OAat%aQ|0E| zN#;$b-3m{wNG%hd5+TCl1k(1nF^TtWfAf76o27zOv6mg?2Ghj{)z{p3RAr>Ns_aus znzLG2qq2damsnd-*O-N{919(l@)%BLL;KN736)Xna4T^?NU{!eFgXnM@LpCVcEsG! z2Me1=z=m><`bi>3z5e227lCIQk~-GMB0t{Z7c^gbGe%_2>NJ6iRmU@kEwLEd7Diz@ zC2~$XWOPgR%gB?`*gnz1|L0SKU_42v%8z$y8n#Yu*OtgnibQ7xVbdCwy%0l$r^}?Q>PJCNI%IvI}&>dD!Ft z7T-Q9Ba_knUIm<(k7uxK4G*|%oPujfLB+ke#vl4(~7HzSTzCGB6OEJrM) zJ^tiT{9owy5!rC;W98VjO!)y9Qhfmzo$$iJ^a`psWIuhn4UY_wf1@Mx3v!8 z^hJY)`3uRSC7+UsmiMU{lxca`*4?&H?)CA6dv6>~E^pNSI59kO%_Dv3Z=-2Z&FPLE z6ORI#i)Cw7SuN?ockLSJrWgm0A9#^6(dJUr5y;r(yA;Bnum07Q#p5$G zNd`aU4j9&-dq3H-nm14W>zm+#rE7b|ryj+8m|*PUHN;g9d-9qY9wk|AVbu$Pg3-}% zr_)(Ulq+?-IMma{H?5&w$Psne^ssz%RajN)u-X= zf%m>=dpzjt&AA1h9lfQK>8WwP?T3CHiCWmG7n_->QuXb#IbqF@b;Z{siP#r(_*;k?-P4s+a0)~OaJ;9{$JlWo*i2fu<%(c&1z~f_Y*aH ziN!H%J+OYoXzlf{#>blyVm_a5(Z#MbzYlxcCwNdezBF>ZIo*W;Mo^Z*l$Je3mrq3F zQcj=L{Ow`uIa?QpcFJVNFstnee=7m|EY-$z;lqFM{qvs%k9yx;ojF+h;|#{;@56hR z>a8~fB_~{*(p`3rhNQbas#I+VSOZ9myhhc#DCnIr^ey;0dyXsrB&xma!{Tund$1wt zF$rHe`K0c2`qZ(Nj){KDYEP(5`XwPG{cb6r#}_-J&Ga7;#!9R^(Q4voz&^sP(Nl{5DX68;F1!f;S z^+830mpKT{$2jTec=zSSp{qd)zYR34=z(_ZUITRs;@&?)R&Do8GCD{_3wLCDQaQo8 zF&*g(>o;&y(GY#+Ge$}LxMHt^f$ymUb!yq0h|0mCpeBwmx3lsXQjqa@Bj3DypY99L zFiAwNLqO8Ibnf$sF(;skznkS~r%SJnP~@NqI!t zN}gch^D_bn(eJ+B`Yo@v*)gliq;S@+Ci zyQwu(@H?SS3ejW2nyUvYC?V>^m|$I?OC7ROy{hTskrQU{G9i?F9&8yj$a=y0GI5;! z>rDmUs!8Wm*QH;}*K#SL2tb>lYHb#SB7^XX6pYo+(1_eUFrtMO9@t|N?PrB>^-T+s zdr=HBwn7p1LWEX$#10wkVpQK&RMOXZWnD7)1wia$tMk_v;)agAS}HTi5_w4425Ov* zKmt&vw%X|JW(DbDLW=43(6o?70SQ$gc&sQv~a^zkS{h>+Q9qZl3uwhY$g4bu!b5GOs z$Jo!I8}OiT2UH7D0qX;RiuMHexVw+k>!5U5d`h&_UcPIbuJ5b^THAEL0izh`51K-& z-DbbpIJ2#HeVJ@hUd}&G^1h?d6;>Xn9+&Wo&S|d=KxNRmjwl{@?ov!c%PJmS^RIIX zjn!aqFBNz2vLXO4V>9FWaT@eU{2MJGWX;r3?`ug-q&;HbGUp6y`A|;X8or?%)d+EH zd&R4US=ExZnUa_kDcnFpg5>^2+HrMYjN`h%stv>mTSst)XYS&T4j1hRiGS9gsVch@ zr45hNqdvacN={Gj`98zyMU(O}a+2BeP&YbnX^CogKX{Eu4EW1ufBes%%bl}9U;X7T ze>rvHcw6gzsKGcX2iN`?F2+`-{94jN0em!}8F7CNN=7+E|$AWa_k+ z1_MxTmuq~OKw@z=st4eC`u&ViyIg{GZw8X{y4B3Cl)UcdruXBkJLZUg0?i6iGM9s| zdNs$Bjr!VWwh!nHD0`>XOuSSohaPLiq+O$%dF5e(vvxOF*pj?(Dx=h-QHyyED!V`ZJ#}K^So;~shce< z@plg>>l1iAszHy+=Q-`%Vf}TSQz-!dsNu=bpA2un``rBlMr!aW z^w7|rmvLwS?vK(gw{EUio_GCXf?q5`Pxy7WN%ylvuKb5roxsfgSM$E#QsvQv;VlwS z{68?u=U+$}zJDg#ZMf|BB-zC2oZ8a0lQyE05f5cR0;@8Rixo;isSdHZ@oqg6)5=Z0sc%RN3ksq9$)^tHO zH_CwFrvf=+K-%OVn@idQO#K&<<0HAMj$x*)E(iHK%zMJmXf9coy7{61PEb1ahY|n8 z#UC`1;9lOor$+81RIA3HpE&hck!-d^dqDe91pk|f@ezF8B6uX+xigQMxe9O|gPv0N z19b&Q%jAX7m59)_d&<#jCb;+1`VIcyB%@V1PAv^Cke!Vd@X-(7b=rr&{8x#v9+!OH z4d-`DejtBz)^s}#rXsX+e5tgxs8$-Vyslwphw#Y6fIly7l9`#4sFR;1O1L3ZP#;)h z3_{;Te8g-woBH$ARjYFldcE2-xU2mn9e>aXk;4D?#)@bLOjeYk~DMxbYz9RIS) z|CD4y7Gn#`?XHha48CeBY-2g)c*F|1N8fN1!BmUV&8X^rKP%wKJ{o7VmEYQ)Es)p8 zv^*7}sYs^mOiWm#eTsV^$ambHUrt}LfbOb7SJU@KlALvG$?W2wWIAqY^F#L<9&9`F z835#1x?$DCL9`-Tu{Ua7!(_Yp5&zEKiQ1!(*J;;`A8%ZkHNXXCHdjg19eunHk#sKd zHEK5@OynYd+;`(1A%j#PL5E$K-%>px8f6NtIj0>`fI=OkCi6F zvwJRNsKr$7WE_bv+*QY1;VuVF#?AYlFmoYfYY0uwuG^1{UJzNSb2zW6)U#0&&|U6; z*0Jchw#_gIKh%G^B|cfzP41DmP-mD--+}fV4*OLb&vD47tlv{!kQ~)k1()`@-)$EI z876pZjH>KPGtrpc$@%-2!`ZH$Hh!obz&P3!u0&LNGpDj+n)4An?DZJEA?NoK(#($oIC$q*v->K#v&&*aUUO#m1SB1jw?})`kIp(< zpqg~%j7{LSWFp@wFc_C*GHT~;p!ND`1K;m=yCr$16F4aXJ&TSG5Zt2JXu94LvUxmo zpm$+>e0+#r_Wbc1qUlZ%&N%#OUT;qAFFp*|Z{FPIDOSx)I0%L3X~YFwRZqoMP5{TX z-$*Mr5&JuID0Rv(=M`?=!tZC2b;|oy&+cUCa-7Pp4B;s!ZFmQ$&!7!L0o}MTGy}jU z-%i?HUn1J;ZrikL{Gm^`{m+a7;AOA9a$-iEYY?Tr?gRC8(k!*jWOHi{({erFn&}Sv zqAxmK3B_o|qwjBHe@hpl>hgjHg7O0bPpcEE6zUAF-y*)*^#@Jz47BSp8ydgORO<*K!vDqhz{{Q34GS;%uIYCYhoG&Q(x zn-<(XP8G*X%6bD>ioHb^$kz+j<5^hV>%*+9+C-irr1JD&*hF5V2Q|;j3 zK*H`X`(?m0z;I{l8VMv)?0cQ_pf-lh9CQr~jw$^hN;8*xUbqan@L<( z#_wjwV=2~(FmScWb2(Kfrhxil)I)8+e9;p~9&P4BaJ}L-62gP7 z@qG1yZq>~T<)R_+3O{o#fXYuwfI^9gNiRqXwJ14J48n3h-6^{J^QN|U2X#Ph<9_ZP z^U~(~Zp`PuEuILTJvMUQ{)~A!LOJD4QG6M`2#Wp;b@m9+wTH5+X(WC!#?L6Z3wp|Z zzGS(3Rg^5;rI~k^8Y&8CCoaHWJ1)`2xpLa-4#H@BN0myZ_UDjQfbqhp0C8F<=aR;7G1N!mv{re$) zaRz2H3ZS}Uf)=nT>WO`cn~@RifrH>Q{&9D>qLA?a)*{||S3OMv^P~nX8_g@$cjBXD zRfRwx{>c6`CXn@5?H2rX^0!MfJM0L;x^EE@pjGNU@%9D?^6 zY(d~4ZCDiT!#bxGNT!DQqejpS6lmPbRdB0?4Y)al_CX~SnqTn-7T`mWvCxgWNF^m8 zS2J${6iRJ@_UT;6H)6c0x2XYMBn2Hu{`55W#4WtsgEw8HfcCY^kF&^e!5zs!t|JbR zjX%ywtfAhY2)a_|#yw3sU4N`yQJ@J1M5Z9GUap@RQVKfT-^++GaPQ>@MkVp`v-@&> z7%+Z7bR!g-TU!5kCPGu^s{PSv_jwG=G5&F=JR>ku;O-7k9apu~YV{=+vbi#`9%*`w zPjUub0$Q(Fe(y2Geg9Eba~$Sfh|)G~;f%;QD8dJ2 zH!0T{BOz4Pd@xMorgO37kk6#= z?lB!|QC+?KQu(50crB&YzTL(s_{@uf??qJ8o@cMWJ{l#lc+UF$Q}N7^r*|Z6@918d z*Vh)*jDsC5yO-X)%!s~M8K?W!>33Y2QrZ7a_9R!n)6;O)-^ru8;BMAlW-mGYy7#Iw zWOV#_;e5#If>}Xu@TIMU$cTxYkF%$I1~Z&P&VLeoIFwU1VsY)uG_!vk%R64-j2*RD zARHge4Vi!RF=mYDbB|WkEBac4WO$C23r}9&nYY&zbetR z^v?^Y8D$X%E_If_J5uyVwBf(nqYYNhw?8dvKk&>quPpfMgwg-r{g;BOOWfgtcl^M1 z0c&CEc=bT?d-J*fy!AvzFVBDdwfuJm!!f}4LCx1g?)c1I8|n1p)yBTfF}dG0$F~c< zf!-PZ4|i{K;)9Zm6NulFR}GWdl$bG(Ij`owB0TY(-t`nBfdh;n9wj9$zlirWzE&0t zO&&*Sd8;?Lgs5I3kTX@n2GV=2AweR|v6GyTGY%h-E>Cg6J1Ro=Wflm5pi zKI=eszK!?VsWDR4U)(xgv}WCMpWkSl^jTg*-qioQIIa?xA3T5f*v|F0?fo|A6<;=}cpJX02X+a>4l zuC(y88@oIxhBvy~wEPq(=V=l4eEH>uT$`bvEUW;9)P<7>n0Oky}3yfRADxDN;m% z*yjk$O@A|EI8g^e0NnIwvZ8~VQQ!ze7dzhpDg7~wNAf1Ur+mCy049upIh8aI?LZ>x z)M~X@lLAr4hxQM7`d9R_Xxc4+2=q%ylW7~3x9dS>}hhF^vdT+0cR&~=V~Xj`>JEAS(=AZyX^ zhjO*%3AQV6v4*o=Q|$#SUz7!xy5h~CBtnO&4g&=IV}1(&M>J{`)BH1SXa@l zP2sIKYIgQyZC~AaOb8yj$11P*s0cyw=h{F6j1mtFL03$D$+CzZ=o_9Q{+#yXv*FX@ zI2!=w4}cI~4&n=EBvFy0zgN~P*1o3)CeIxvarIlWS@WjFh2H0~XuZLxJW+2p$WwEx z?muV(7&*edxjU2?HQeLMrskVs&%0Iei03g^gADQT-Zq$|Z2&c`Kd`>=rg9WF1I@vs zdg-@&3I1*CWKZ&r&TzAuY2-VtMR;_OJd4NR^hg5^pLfMN*i1(&9$~Ht)od_2sHxpk zL>ZGs{ft;-D$Gik&GA@C23y!*R`pzq?*5j;Z{IW^c4vax;x2p}z_k7~Q=VdW8YwW; zLj=jsn48cy z&s_W~Mgl!IlpIh=?TxHUFd*xhOgArc5av87RV2bB-t~{I z0!cb27=imB3a*b)g@EVBL5X@iATKfmp~nUUSI-a|Aq{Ywif-xx&&eXX>R+a6_Zf!Z z_3xnXJG)~jHeH~nmLz($6=Cfze@a((xl1Hbsz8T>`Os!+MM|LF5>}Q`V^nxRbq2Hf zx{*d)=~|ozLDR*8j zL=j+u+gYpOXW{;B7g@0u0&)w4$@!>y=;QCF6d-yI53IHFAngRhf<2w{lNNzl3=}m2 zesZ(PaGBhN}iy+|5Qcg0M4GK`7C8$`QXrzRU09% z^6arXBn=cL&WKrLP^MzPked+X2zAM&;=Vb&C$O^s-XH1rs84mJ5GKK97)Jw45xL`L z0p)wlP?_)v4);M)6ms~yi??~%ookfcic^@%Jpm9+sLfh=_*@fH1}Sc|&+M#IA~2v| zfZhznkH(RoZ{Ywia`qUL=HP%-4AAN|)cU#?X|J6TdBsMqe_c+?^N$KgXrkAt$)fb* z?=L7qr(9Q6nIfIJ%#xa(DtF`}-9dP(*ML<4m}rV-%5~GLxM{2drk@PzUh*D*o(ZK; z;%*+$`-5h!9(Dux+_hk&jb{SOogL7C==F@q2EeL>G#(TNm*Q|8u^kDdvp}!cp!O$& zS1|?ETaoy&6^>x55$!Zq>PH@xndSkzsH&g_MiM29R9E#&5kw-lPjc+i_Y`X0A0F%f{bUjlK|0JI9t=Ce#5 zzr_>A3upbWQzrKI6eD%Jq&C<&qAkrYBwkeySYME8{cO`Itw2x7x6oJ`L)McjY`t8i zCIh)9znPqcvx;H%SrxT=>r`!`tR}b4BwGf%GV4F@Z=y(N^MUj=r559_=;8T?zz|Bf z^S_c89FEhkz3D#3%ZF|IewBA0E|l5h;b~cNkUttNjU>UIQDHIO5B3zWN6rcc9N<^h zP=(Vlue0Yte(&cw+}B1o{fk410Jrcdb)=_`XNH2Y(qYU;R8N0WD=aNg0U%jra$pK; zVkxF5ThfK`?PLhaBu3-hKb+O8Kj8 zH4K2c=+Bn42>qWnQXWI$ej_Sk-Cn;9GubtzG81??)38t5AP_>vrJ6j|>-h%@KDSUV zfNL8M{R``;u+3x{FNJ*C?Eg;=tHy|Q+kMP4moNQh;!%QCg}={!_Ad*_pR#1qTaJy^W+Sad$&@t2pCnWp;RgW!3d2_r9aEKQ#x~@TIiXtG z{6H#Ya1E7+{lBu;a4#41=px|bc%gDuJMfbD)vP5{7^C_vI6eXNhzH~5n)JdZs$e*J zDzMYePyoI|WmJ3ye9@7v_orLkojl-=Z`+G})nWg0X5Jfw5WvHl zsl7t~f3!{MksWPTPuN+c>$0*M+2~2;NC!1h19&~cXO#OblwpLn-;&=IVZ@;hDl<4& zMGFDAdo=3OSbRkD^zV7Erij#2DKu;I4@co4z&;VsK7}y@2Py0d7@~Fn-C@%5i>n@0 zHfjN^Au9es6Y0YCaco4O?&#@;OOCLT4K@Eg3bPn*ZNsPRckEI29&v#|Mx<;mbuSTz zb={X8L~&qa)atu7ioxcO^>f0I+rPeru`QZeeX@8~tB_9}c#?>qOs6WFpsCv_EalQD z4J=SYz=1@eh;;<^w9?ERBbQA8d@%v<|6w2@T?xzV;m>=!(TDav%WIyE*<1`j|7Oy7 z(J0e`sCY9V{4}8&ih#GqW2bjmg)kxJcexGaV1n`laGC;Qu3m2I8XrksrmQ2;15~(z z0qk%grW%42>?(9Wtay^DhIgY+>*(zOXpL7w)a_AL+s9YJD-%K_1q;h$SCh=prE7?~ z=A0`)4F~&S(=}`w#?S&hWYE2^e}rM#GW(!8aBj^ejQKA|7ynNV!7!Dua&Dh75-kV3 zt`rQw!_>nBC<@n~i4u{y4e`^!^%=%Dizo)gz%>M567fy}PqU7i_=t)Yr|(edtq)-U zIDmfbm*PMmBcyGc0K0WhGO*Yu(4;Wq^-W#mK$xony?=q#MFvXHT@!XQ1z^$Hi+G7T z^EwgUphtjAf}->cEPwb9xHv^7f5z&R0@QJU`MNl0`*V{qFs9!`d`yW+r$XN z^xp7nGB~Z>n%#c_B>x=jxv;;4AuFkyDjz>=#5^1;p{lC1ecpLd)e;BL?S5Mssw&N& zhHt>0fdz1&2F z2iTp=Qw!9!wrg%dD;WHb)MBJkrJ9CK_+f=jZ|2f&D-`T;Riy4qfCgVbU? zkgtRZutd10z}L5Oj&E8yTb7FrNmMf&hDQ*8QEB_Z2xlv|Q4UVINxi*Gvb&KAJ*eN6 zzkBJ_mznhDY)-d0ED;0*^-&^SLx}H83?1LdH#mi}zi|ne^&b{35l(`UPVNRW_5715ds+zXj|Ff7~!( zD8Q_X+JU_DD-Ux~W>}7PFwcnv&{!Th49hyUS?P~J!KRP68;QWGDupMcG*z4~4j4ce z3OTu0()^V)N*vK@X{7=vwdr(!7+Iwf=D_0qqo^@@{@V^0T!mSVABy!sx4;Si|pH+pALcGnsO>u9v8rHr6Lh1RT7*ZO4drIVRE2*Ls^tykp9pOiV9C%ICXF8LXu4{bC+j7* z#79(UR}uN25-*+uRu_n^Y@S&-`7KP=JLhF#oB4BPqkNL1^LTH@4)=+1aIZ47o2UHE z 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