calatrava 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +202 -0
  5. data/Plans.md +20 -0
  6. data/README.md +73 -0
  7. data/Rakefile +26 -0
  8. data/bin/calatrava +6 -0
  9. data/calatrava.gemspec +35 -0
  10. data/features/cli.feature +14 -0
  11. data/features/project.feature +48 -0
  12. data/features/step_definitions/template_steps.rb +8 -0
  13. data/features/support/env.rb +5 -0
  14. data/lib/calatrava/app.rb +30 -0
  15. data/lib/calatrava/manifest.rb +44 -0
  16. data/lib/calatrava/project.rb +218 -0
  17. data/lib/calatrava/resources_build_phase.rb +19 -0
  18. data/lib/calatrava/tasks/apache.rb +44 -0
  19. data/lib/calatrava/tasks/artifact.rb +24 -0
  20. data/lib/calatrava/tasks/assets.rb +6 -0
  21. data/lib/calatrava/tasks/automation.rb +38 -0
  22. data/lib/calatrava/tasks/bootstrap.rb +10 -0
  23. data/lib/calatrava/tasks/build.rb +1 -0
  24. data/lib/calatrava/tasks/configuration.rb +41 -0
  25. data/lib/calatrava/tasks/droid.rb +83 -0
  26. data/lib/calatrava/tasks/haml.rb +71 -0
  27. data/lib/calatrava/tasks/ios.rb +73 -0
  28. data/lib/calatrava/tasks/kernel.rb +52 -0
  29. data/lib/calatrava/tasks/precommit.rb +22 -0
  30. data/lib/calatrava/tasks/release.rb +17 -0
  31. data/lib/calatrava/tasks/shell.rb +17 -0
  32. data/lib/calatrava/tasks/web.rb +82 -0
  33. data/lib/calatrava/tasks.rb +93 -0
  34. data/lib/calatrava/template.rb +44 -0
  35. data/lib/calatrava/templates/.rvmrc.calatrava +2 -0
  36. data/lib/calatrava/templates/Gemfile.calatrava +4 -0
  37. data/lib/calatrava/templates/Rakefile +1 -0
  38. data/lib/calatrava/templates/assets/lib/ICanHaz.js +542 -0
  39. data/lib/calatrava/templates/assets/lib/underscore.js +1059 -0
  40. data/lib/calatrava/templates/assets/lib/zepto.js +1355 -0
  41. data/lib/calatrava/templates/build_env.sh +2 -0
  42. data/lib/calatrava/templates/config/environments.yml +17 -0
  43. data/lib/calatrava/templates/config/templates/env.coffee.erb +7 -0
  44. data/lib/calatrava/templates/config/templates/httpd.conf.erb +33 -0
  45. data/lib/calatrava/templates/droid/app/bridge.coffee +130 -0
  46. data/lib/calatrava/templates/droid/calatrava/ant/calatrava.xml +48 -0
  47. data/lib/calatrava/templates/droid/calatrava/calatrava-build.xml +91 -0
  48. data/lib/calatrava/templates/droid/calatrava/ivy.xml +8 -0
  49. data/lib/calatrava/templates/droid/calatrava/ivysettings.xml +12 -0
  50. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/AndroidManifest.xml.calatrava +20 -0
  51. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/ConversionForm.java.calatrava +27 -0
  52. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/Title.java.calatrava +23 -0
  53. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/CalatravaPage.java +13 -0
  54. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AjaxRequestManager.java +166 -0
  55. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AssetRepository.java +17 -0
  56. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/KernelBridge.java +25 -0
  57. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/Launcher.java +85 -0
  58. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/PageRegistry.java +225 -0
  59. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RegisteredActivity.java +86 -0
  60. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RequestLoader.java +31 -0
  61. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RhinoService.java +212 -0
  62. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/shell/WebViewActivity.java +247 -0
  63. data/lib/calatrava/templates/droid/manifest.yml +1 -0
  64. data/lib/calatrava/templates/ios/Podfile.calatrava +5 -0
  65. data/lib/calatrava/templates/ios/manifest.yml +1 -0
  66. data/lib/calatrava/templates/ios/res/js/bridge.js +249 -0
  67. data/lib/calatrava/templates/ios/res/xibs/ProgressViewController.xib +334 -0
  68. data/lib/calatrava/templates/ios/res/xibs/WebViewController.xib +173 -0
  69. data/lib/calatrava/templates/ios/src/AppDelegate.h +8 -0
  70. data/lib/calatrava/templates/ios/src/AppDelegate.m +56 -0
  71. data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Info.plist +45 -0
  72. data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Prefix.pch +14 -0
  73. data/lib/calatrava/templates/ios/src/ConversionFormViewController.h +16 -0
  74. data/lib/calatrava/templates/ios/src/ConversionFormViewController.m +179 -0
  75. data/lib/calatrava/templates/ios/src/ConversionFormViewController.xib +357 -0
  76. data/lib/calatrava/templates/ios/src/en.lproj/InfoPlist.strings +2 -0
  77. data/lib/calatrava/templates/ios/src/main.m +10 -0
  78. data/lib/calatrava/templates/ios/test/AJAXConnectionTest.m +21 -0
  79. data/lib/calatrava/templates/ios/test/AppTests-Prefix.pch +8 -0
  80. data/lib/calatrava/templates/ios/test/CalatravaiOSTests-Info.plist +22 -0
  81. data/lib/calatrava/templates/ios/test/TWBridgePageRegistryTest.m +15 -0
  82. data/lib/calatrava/templates/ios/test/en.lproj/InfoPlist.strings +2 -0
  83. data/lib/calatrava/templates/kernel/.gitignore +1 -0
  84. data/lib/calatrava/templates/kernel/app/calatrava.coffee +8 -0
  85. data/lib/calatrava/templates/kernel/app/converter/controller.converter.coffee +50 -0
  86. data/lib/calatrava/templates/kernel/app/converter/init.converter.coffee +11 -0
  87. data/lib/calatrava/templates/kernel/app/pageHelper.coffee +17 -0
  88. data/lib/calatrava/templates/kernel/features/support/bridge.coffee +124 -0
  89. data/lib/calatrava/templates/kernel/features/support/spec_helper.js +49 -0
  90. data/lib/calatrava/templates/kernel/spec/converter/controller.converter.spec.coffee +37 -0
  91. data/lib/calatrava/templates/kernel/spec/environment.spec_helper.coffee +25 -0
  92. data/lib/calatrava/templates/kernel/spec/spec_helper.js +49 -0
  93. data/lib/calatrava/templates/kernel/spec/stubView.coffee +18 -0
  94. data/lib/calatrava/templates/kernel/watchr.rb +17 -0
  95. data/lib/calatrava/templates/package.json +20 -0
  96. data/lib/calatrava/templates/shell/layouts/single_page.haml +23 -0
  97. data/lib/calatrava/templates/shell/pages/converter/conversionForm.haml +12 -0
  98. data/lib/calatrava/templates/shell/pages/converter/page.conversionForm.coffee +42 -0
  99. data/lib/calatrava/templates/shell/shell.scss +1 -0
  100. data/lib/calatrava/templates/shell/support/shell.coffee +21 -0
  101. data/lib/calatrava/templates/web/apache/conf/mime.types +1357 -0
  102. data/lib/calatrava/templates/web/app/source/bridge.coffee +158 -0
  103. data/lib/calatrava/templates/web/app/source/init.coffee +14 -0
  104. data/lib/calatrava/templates/web/app/views/index.haml +18 -0
  105. data/lib/calatrava/templates/web/deploy/instance.sh +10 -0
  106. data/lib/calatrava/templates/web/manifest.yml +1 -0
  107. data/lib/calatrava/version.rb +3 -0
  108. data/lib/calatrava.rb +5 -0
  109. metadata +302 -0
@@ -0,0 +1,247 @@
1
+ package com.calatrava.shell;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+ import android.content.IntentFilter;
7
+ import android.graphics.Color;
8
+ import android.util.Log;
9
+ import android.webkit.JsResult;
10
+ import android.webkit.WebChromeClient;
11
+ import android.webkit.WebView;
12
+ import android.webkit.WebViewClient;
13
+
14
+ import com.calatrava.bridge.RegisteredActivity;
15
+ import com.calatrava.bridge.RhinoService;
16
+ import com.calatrava.bridge.PageRegistry;
17
+
18
+ import java.util.HashMap;
19
+ import java.util.List;
20
+ import java.util.Map;
21
+ import java.util.concurrent.Callable;
22
+ import java.util.concurrent.FutureTask;
23
+ import java.util.concurrent.Semaphore;
24
+
25
+ public abstract class WebViewActivity extends RegisteredActivity {
26
+ private String TAG = WebViewActivity.class.getSimpleName();
27
+
28
+ private JSContainer jsContainer;
29
+ private WebView webView;
30
+ private boolean pageReady = false;
31
+ private RhinoService rhino;
32
+
33
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
34
+ @Override
35
+ public void onReceive(Context context, Intent intent) {
36
+ if ("com.calatrava.dialog".equals(intent.getAction())) {
37
+ String name = intent.getExtras().getString("name");
38
+ webView.loadUrl("javascript:window." + getPageName() + "View.showDialog('" + name + "');");
39
+ }
40
+ }
41
+ };
42
+
43
+ @Override
44
+ protected void onRhinoConnected(RhinoService rhino) {
45
+ this.rhino = rhino;
46
+ jsContainer = new JSContainer(rhino, getPageName());
47
+ loadPage();
48
+ }
49
+
50
+ @Override
51
+ protected void onResume() {
52
+ super.onResume();
53
+
54
+ onPageLoadCompleted();
55
+
56
+ if (rhino != null) {
57
+ pageHasOpened();
58
+ }
59
+ registerReceiver(receiver, new IntentFilter("com.calatrava.dialog"));
60
+ }
61
+
62
+ @Override
63
+ protected void onPause() {
64
+ super.onPause();
65
+
66
+ PageRegistry.sharedRegistry().pageOffscreen(getPageName());
67
+ unregisterReceiver(receiver);
68
+ }
69
+
70
+ @Override
71
+ public void onDestroy() {
72
+ super.onDestroy();
73
+
74
+ PageRegistry.sharedRegistry().unregisterPage(getPageName());
75
+ }
76
+
77
+ public String getFieldValue(final String field) {
78
+ assert (getFields().contains(field));
79
+
80
+ Log.d(TAG, "Get value for field: " + field + " on page '" + getPageName() + "'");
81
+
82
+ FutureTask<String> fieldValue = new FutureTask<String>(new Callable<String>() {
83
+ public String call() throws Exception {
84
+ webView.loadUrl("javascript:container.provideValueFor('" + field + "', window." + getPageName() + "View.get('" + field + "'));");
85
+ return jsContainer.retrieveValueFor(field);
86
+ }
87
+ });
88
+
89
+ runOnUiThread(fieldValue);
90
+
91
+ String value;
92
+ try {
93
+ value = fieldValue.get();
94
+ } catch (Exception e) {
95
+ e.printStackTrace();
96
+ // TODO: Signal failure to the UI thread
97
+ return "";
98
+ }
99
+
100
+ Log.d(TAG, "(getFieldValue) : Got the field [" + field + "] value = " + value);
101
+ return value;
102
+ }
103
+
104
+ public void render(final String json) {
105
+ runOnUiThread(new Runnable() {
106
+ public void run() {
107
+ jsContainer.setJsObject(json);
108
+ Log.d(TAG, "render page: " + getPageName());
109
+
110
+ webView.loadUrl("javascript:container.onRenderComplete(window." + getPageName() + "View.render(JSON.parse(container.getJsObject())));");
111
+ }
112
+ });
113
+ }
114
+
115
+ protected abstract String getPageName();
116
+
117
+ protected abstract List<String> getEvents();
118
+
119
+ protected abstract List<String> getFields();
120
+
121
+ protected int getBackgroundColor(){
122
+ return Color.TRANSPARENT;
123
+ }
124
+
125
+ protected void loadPage() {
126
+ PageRegistry.sharedRegistry().registerPage(getPageName(), this);
127
+
128
+ webView = new WebView(this);
129
+ setContentView(webView);
130
+
131
+ webView.getSettings().setJavaScriptEnabled(true);
132
+ webView.getSettings().setDomStorageEnabled(true);
133
+ webView.setScrollBarStyle(webView.SCROLLBARS_OUTSIDE_OVERLAY);
134
+ webView.setScrollbarFadingEnabled(true);
135
+ webView.setBackgroundColor(0xffffffff);
136
+ webView.addJavascriptInterface(jsContainer, "container");
137
+
138
+ webView.setWebViewClient(new WebViewClient() {
139
+ @Override
140
+ public void onPageFinished(WebView view, String url) {
141
+ super.onPageFinished(view, url);
142
+ Log.d(TAG, "Webview finished loading a URL");
143
+
144
+ pageReady = true;
145
+ onPageLoadCompleted();
146
+ }
147
+ });
148
+
149
+ webView.setWebChromeClient(new WebChromeClient() {
150
+ @Override
151
+ public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
152
+ Log.d(TAG, "Received JS alert: '" + message + "'");
153
+ return false;
154
+ }
155
+ });
156
+
157
+ webView.loadUrl("file:///android_asset/hybrid/views/" + getPageName() + ".html");
158
+ pageHasOpened();
159
+ }
160
+
161
+ private void pageHasOpened() {
162
+ rhino.triggerEvent(getPageName(), "pageOpened", new String[] {});
163
+ }
164
+
165
+ private void onPageLoadCompleted() {
166
+ if (jsContainer != null && pageReady) {
167
+ jsContainer.onRenderComplete(null);
168
+
169
+ for (String field : getFields()) {
170
+ jsContainer.hasField(field);
171
+ }
172
+
173
+ PageRegistry.sharedRegistry().pageOnscreen(getPageName());
174
+ }
175
+ }
176
+
177
+ public class JSContainer {
178
+ private String TAG = JSContainer.class.getSimpleName();
179
+
180
+ private Map<String, String> lastValue = new HashMap<String, String>();
181
+ private Map<String, Semaphore> valueAvailable = new HashMap<String, Semaphore>();
182
+ private RhinoService rhino;
183
+ private String pageName;
184
+ private String jsObject;
185
+
186
+ public JSContainer(RhinoService rhino, String pageName) {
187
+ this.rhino = rhino;
188
+ this.pageName = pageName;
189
+ }
190
+
191
+ public void setJsObject(String jsObject) {
192
+ this.jsObject = jsObject;
193
+ }
194
+
195
+ public String getJsObject() {
196
+ return jsObject;
197
+ }
198
+
199
+ public void hasField(String field) {
200
+ valueAvailable.put(field, new Semaphore(0));
201
+ }
202
+
203
+ public void provideValueFor(String field, String value) {
204
+ Log.d(TAG, "Got value '" + value + "' for field '" + field + "'");
205
+ lastValue.put(field, value);
206
+ valueAvailable.get(field).release();
207
+ }
208
+
209
+ public String retrieveValueFor(String field) {
210
+ try {
211
+ valueAvailable.get(field).acquire();
212
+ } catch (InterruptedException e) {
213
+ return retrieveValueFor(field);
214
+ }
215
+
216
+ String value = lastValue.remove(field);
217
+ Log.d(TAG, "Reading value '" + value + "' for field '" + field + "'");
218
+ return value;
219
+ }
220
+
221
+ public void handleEvent(String event, String... extraArgs) {
222
+ Log.d(TAG, "User clicked");
223
+ Log.d(TAG, "Current thread is " + Thread.currentThread().getId());
224
+
225
+ if (extraArgs != null) {
226
+ Log.d(TAG, "extraArgs = " + extraArgs.length);
227
+ for (String arg : extraArgs) {
228
+ Log.d(TAG, "arg = '" + arg + "'");
229
+ }
230
+ } else {
231
+ Log.d(TAG, "extraArgs were null!");
232
+ }
233
+ rhino.triggerEvent(pageName, event, extraArgs);
234
+ }
235
+
236
+ public void onRenderComplete(Object ignored) {
237
+ runOnUiThread(new Runnable() {
238
+ public void run() {
239
+ for (String event : getEvents()) {
240
+ Log.d(TAG, "About to bind event '" + event + "'");
241
+ webView.loadUrl("javascript:window." + getPageName() + "View.bind('" + event + "', function() { container.handleEvent('" + event + "', _.toArray(arguments)); });");
242
+ }
243
+ }
244
+ });
245
+ }
246
+ }
247
+ }
@@ -0,0 +1 @@
1
+ - converter
@@ -0,0 +1,5 @@
1
+ platform :ios, '5.0'
2
+
3
+ xcodeproj '{{ project_name}}.xcodeproj'
4
+
5
+ pod 'calatrava', :git => 'https://github.com/calatrava/calatrava-ios'
@@ -0,0 +1 @@
1
+ - converter
@@ -0,0 +1,249 @@
1
+ var tw = tw || {};
2
+ tw.bridge = tw.bridge || {};
3
+
4
+ // json.js does stupid things to the Object prototype
5
+ Object.prototype.toJSONString = "";
6
+ Object.prototype.parseJSON = "";
7
+
8
+ function generateRandomString(){
9
+ var str = '';
10
+ var i;
11
+ for (i = 0; i < 32; ++i) {
12
+ var r = Math.floor(Math.random() * 16);
13
+ str = str + r.toString(16);
14
+ }
15
+ return str.toUpperCase();
16
+ }
17
+
18
+ function bridgeDispatch(proxyId) {
19
+ var extraArgs = _.map(_.toArray(arguments).slice(1), function(obj) { return obj.valueOf(); });
20
+ var proxyPage = tw.bridge.pages.pageByProxyId(proxyId);
21
+ proxyPage.dispatch.apply(proxyPage, extraArgs);
22
+ }
23
+
24
+ function bridgeSuccessfulResponse(requestId, response) {
25
+ tw.bridge.requests.successfulResponse(requestId, response);
26
+ }
27
+
28
+ function bridgeFailureResponse(requestId, errorCode, response) {
29
+ tw.bridge.requests.failureResponse(requestId, errorCode, response);
30
+ }
31
+
32
+ function bridgeFireTimer(timerId) {
33
+ tw.bridge.timers.fireTimer(timerId);
34
+ }
35
+
36
+ function bridgeInvokeCallback(widgetName) {
37
+ var extraArgs = _.map(_.toArray(arguments).slice(1), function(obj) { return obj.valueOf(); });
38
+ tw.bridge.widgets.callback(widgetName).apply(this, extraArgs);
39
+ }
40
+
41
+ tw.bridge.changePage = function(target) {
42
+ tw.bridge.runtime.changePage(target);
43
+ return target;
44
+ };
45
+
46
+ tw.bridge.widgets = (function() {
47
+ var callbacks;
48
+ callbacks = {};
49
+ return {
50
+ display: function(name, options, callback) {
51
+ TWBridgePageRegistry.sharedRegistry.displayWidget_withOptions(name, options);
52
+ return callbacks[name] = callback;
53
+ },
54
+ callback: function(name) {
55
+ return callbacks[name];
56
+ }
57
+ };
58
+ })();
59
+
60
+ tw.bridge.alert = function(message) {
61
+ TWBridgePageRegistry.sharedRegistry.alert(message);
62
+ };
63
+
64
+ tw.bridge.openUrl = function(url) {
65
+ tw.bridge.runtime.openUrl(url);
66
+ };
67
+
68
+ tw.bridge.trackEvent = function(event) {
69
+ };
70
+
71
+ tw.bridge.log = function(message) {
72
+ tw.bridge.runtime.log(message);
73
+ };
74
+
75
+ tw.bridge.request = function(options) {
76
+ if (options.contentType) {
77
+ options.customHeaders = options.customHeaders || {};
78
+ options.customHeaders['Content-Type'] = options.contentType;
79
+ }
80
+ tw.bridge.requests.issue(
81
+ options.url,
82
+ options.method,
83
+ options.body,
84
+ options.success,
85
+ options.failure,
86
+ options.customHeaders);
87
+ };
88
+
89
+ tw.bridge.pageObject = function(pageName) {
90
+ var proxyId = generateRandomString(),
91
+ handlerRegistry = {};
92
+
93
+ tw.bridge.runtime.registerProxyForPage(proxyId, pageName);
94
+
95
+ function bind(event, handler) {
96
+ handlerRegistry[event] = handler;
97
+ tw.bridge.runtime.attachProxyEventHandler(proxyId, event);
98
+ }
99
+
100
+ function dispatch(event) {
101
+ args = _.toArray(arguments).slice(1);
102
+ if (handlerRegistry[event]) {
103
+ handlerRegistry[event].apply(this, args);
104
+ }
105
+ }
106
+
107
+ function get(field) {
108
+ return tw.bridge.runtime.valueOfProxyField(proxyId, field);
109
+ }
110
+
111
+ function cleanValues(jsObject) {
112
+ _.each(_.keys(jsObject), function(key) {
113
+ if (jsObject[key] === null || jsObject[key] === undefined) {
114
+ delete jsObject[key];
115
+ } else if (jsObject[key] === false) {
116
+ jsObject[key] = 0;
117
+ } else {
118
+ tw.bridge.log("key = '" + key + "'; value = '" + jsObject[key] + "'");
119
+ if (jsObject[key] instanceof Object) {
120
+ cleanValues(jsObject[key]);
121
+ }
122
+ }
123
+ });
124
+ }
125
+
126
+ function render(viewObject) {
127
+ // Clean off properties that cause problems when marshalling
128
+ if (viewObject.hasOwnProperty('toJSONString')) {
129
+ viewObject.toJSONString = null;
130
+ }
131
+
132
+ // Delete any keys that have a null value to avoid the Obj-C JSON
133
+ // serialization failure
134
+ if (viewObject != undefined) {
135
+ cleanValues(viewObject);
136
+ }
137
+ if (viewObject.hasOwnProperty('parseJSON')) {
138
+ viewObject.parseJSON = null;
139
+ }
140
+
141
+ tw.bridge.runtime.renderProxy(viewObject, proxyId);
142
+ }
143
+
144
+ return {
145
+ proxyId: proxyId,
146
+ bind: bind,
147
+ dispatch: dispatch,
148
+ get: get,
149
+ render: render
150
+ };
151
+ };
152
+
153
+ tw.bridge.pages = (function() {
154
+ var pagesByName = {},
155
+ pagesByProxyId = {};
156
+
157
+ function pageNamed(pageName) {
158
+ if (!pagesByName[pageName]) {
159
+ var page = tw.bridge.pageObject(pageName);
160
+ pagesByName[pageName] = page;
161
+ pagesByProxyId[page.proxyId] = page;
162
+ }
163
+ return pagesByName[pageName];
164
+ }
165
+
166
+ function pageByProxyId(proxyId) {
167
+ return pagesByProxyId[proxyId];
168
+ }
169
+
170
+ return {
171
+ pageNamed: pageNamed,
172
+ pageByProxyId: pageByProxyId
173
+ };
174
+ }());
175
+
176
+ tw.bridge.requests = (function() {
177
+ var successHandlersById = {},
178
+ failureHandlersById = {};
179
+
180
+ function issue(url, method, body, success, failure, customHeaders) {
181
+ var requestId = generateRandomString();
182
+ bodyStr = body;
183
+
184
+ if (bodyStr && bodyStr.constructor !== String) {
185
+ bodyStr = JSON.stringify(body);
186
+ }
187
+
188
+ successHandlersById[requestId] = success;
189
+ failureHandlersById[requestId] = failure;
190
+ tw.bridge.runtime.issueRequest({
191
+ requestId: requestId,
192
+ url: url,
193
+ method: method,
194
+ body: bodyStr,
195
+ headers: customHeaders
196
+ });
197
+ }
198
+
199
+ function successfulResponse(requestId, response) {
200
+ successHandlersById[requestId](response);
201
+ clearHandlers(requestId);
202
+ }
203
+
204
+ function failureResponse(requestId, errorCode, response) {
205
+ failureHandlersById[requestId](errorCode, response);
206
+ clearHandlers(requestId);
207
+ }
208
+
209
+ function clearHandlers(requestId) {
210
+ successHandlersById[requestId] = null;
211
+ failureHandlersById[requestId] = null;
212
+ }
213
+
214
+ return {
215
+ successfulResponse: successfulResponse,
216
+ failureResponse: failureResponse,
217
+ issue: issue
218
+ };
219
+ }());
220
+
221
+ tw.bridge.timers = (function () {
222
+ callbacks = {};
223
+
224
+ return {
225
+ start: function(timeout, callback) {
226
+ var timerId = generateRandomString();
227
+ callbacks[timerId] = callback;
228
+ tw.bridge.runtime.startTimerWithTimeout(timerId, timeout);
229
+ return timerId;
230
+ },
231
+ fireTimer: function(timerId) {
232
+ if (callbacks[timerId]) {
233
+ callbacks[timerId]();
234
+ }
235
+ },
236
+ clearTimer: function(timerId) {
237
+ delete callbacks[timerId];
238
+ }
239
+ };
240
+ }());
241
+
242
+ tw.bridge.dialog = (function() {
243
+ return {
244
+ display: function(name) {
245
+ TWBridgePageRegistry.sharedRegistry.displayDialog(name)
246
+ }
247
+ };
248
+ }());
249
+