calatrava 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/.rvmrc +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +202 -0
- data/Plans.md +20 -0
- data/README.md +73 -0
- data/Rakefile +26 -0
- data/bin/calatrava +6 -0
- data/calatrava.gemspec +35 -0
- data/features/cli.feature +14 -0
- data/features/project.feature +48 -0
- data/features/step_definitions/template_steps.rb +8 -0
- data/features/support/env.rb +5 -0
- data/lib/calatrava/app.rb +30 -0
- data/lib/calatrava/manifest.rb +44 -0
- data/lib/calatrava/project.rb +218 -0
- data/lib/calatrava/resources_build_phase.rb +19 -0
- data/lib/calatrava/tasks/apache.rb +44 -0
- data/lib/calatrava/tasks/artifact.rb +24 -0
- data/lib/calatrava/tasks/assets.rb +6 -0
- data/lib/calatrava/tasks/automation.rb +38 -0
- data/lib/calatrava/tasks/bootstrap.rb +10 -0
- data/lib/calatrava/tasks/build.rb +1 -0
- data/lib/calatrava/tasks/configuration.rb +41 -0
- data/lib/calatrava/tasks/droid.rb +83 -0
- data/lib/calatrava/tasks/haml.rb +71 -0
- data/lib/calatrava/tasks/ios.rb +73 -0
- data/lib/calatrava/tasks/kernel.rb +52 -0
- data/lib/calatrava/tasks/precommit.rb +22 -0
- data/lib/calatrava/tasks/release.rb +17 -0
- data/lib/calatrava/tasks/shell.rb +17 -0
- data/lib/calatrava/tasks/web.rb +82 -0
- data/lib/calatrava/tasks.rb +93 -0
- data/lib/calatrava/template.rb +44 -0
- data/lib/calatrava/templates/.rvmrc.calatrava +2 -0
- data/lib/calatrava/templates/Gemfile.calatrava +4 -0
- data/lib/calatrava/templates/Rakefile +1 -0
- data/lib/calatrava/templates/assets/lib/ICanHaz.js +542 -0
- data/lib/calatrava/templates/assets/lib/underscore.js +1059 -0
- data/lib/calatrava/templates/assets/lib/zepto.js +1355 -0
- data/lib/calatrava/templates/build_env.sh +2 -0
- data/lib/calatrava/templates/config/environments.yml +17 -0
- data/lib/calatrava/templates/config/templates/env.coffee.erb +7 -0
- data/lib/calatrava/templates/config/templates/httpd.conf.erb +33 -0
- data/lib/calatrava/templates/droid/app/bridge.coffee +130 -0
- data/lib/calatrava/templates/droid/calatrava/ant/calatrava.xml +48 -0
- data/lib/calatrava/templates/droid/calatrava/calatrava-build.xml +91 -0
- data/lib/calatrava/templates/droid/calatrava/ivy.xml +8 -0
- data/lib/calatrava/templates/droid/calatrava/ivysettings.xml +12 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/AndroidManifest.xml.calatrava +20 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/ConversionForm.java.calatrava +27 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/Title.java.calatrava +23 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/CalatravaPage.java +13 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AjaxRequestManager.java +166 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AssetRepository.java +17 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/KernelBridge.java +25 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/Launcher.java +85 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/PageRegistry.java +225 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RegisteredActivity.java +86 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RequestLoader.java +31 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RhinoService.java +212 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/shell/WebViewActivity.java +247 -0
- data/lib/calatrava/templates/droid/manifest.yml +1 -0
- data/lib/calatrava/templates/ios/Podfile.calatrava +5 -0
- data/lib/calatrava/templates/ios/manifest.yml +1 -0
- data/lib/calatrava/templates/ios/res/js/bridge.js +249 -0
- data/lib/calatrava/templates/ios/res/xibs/ProgressViewController.xib +334 -0
- data/lib/calatrava/templates/ios/res/xibs/WebViewController.xib +173 -0
- data/lib/calatrava/templates/ios/src/AppDelegate.h +8 -0
- data/lib/calatrava/templates/ios/src/AppDelegate.m +56 -0
- data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Info.plist +45 -0
- data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Prefix.pch +14 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.h +16 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.m +179 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.xib +357 -0
- data/lib/calatrava/templates/ios/src/en.lproj/InfoPlist.strings +2 -0
- data/lib/calatrava/templates/ios/src/main.m +10 -0
- data/lib/calatrava/templates/ios/test/AJAXConnectionTest.m +21 -0
- data/lib/calatrava/templates/ios/test/AppTests-Prefix.pch +8 -0
- data/lib/calatrava/templates/ios/test/CalatravaiOSTests-Info.plist +22 -0
- data/lib/calatrava/templates/ios/test/TWBridgePageRegistryTest.m +15 -0
- data/lib/calatrava/templates/ios/test/en.lproj/InfoPlist.strings +2 -0
- data/lib/calatrava/templates/kernel/.gitignore +1 -0
- data/lib/calatrava/templates/kernel/app/calatrava.coffee +8 -0
- data/lib/calatrava/templates/kernel/app/converter/controller.converter.coffee +50 -0
- data/lib/calatrava/templates/kernel/app/converter/init.converter.coffee +11 -0
- data/lib/calatrava/templates/kernel/app/pageHelper.coffee +17 -0
- data/lib/calatrava/templates/kernel/features/support/bridge.coffee +124 -0
- data/lib/calatrava/templates/kernel/features/support/spec_helper.js +49 -0
- data/lib/calatrava/templates/kernel/spec/converter/controller.converter.spec.coffee +37 -0
- data/lib/calatrava/templates/kernel/spec/environment.spec_helper.coffee +25 -0
- data/lib/calatrava/templates/kernel/spec/spec_helper.js +49 -0
- data/lib/calatrava/templates/kernel/spec/stubView.coffee +18 -0
- data/lib/calatrava/templates/kernel/watchr.rb +17 -0
- data/lib/calatrava/templates/package.json +20 -0
- data/lib/calatrava/templates/shell/layouts/single_page.haml +23 -0
- data/lib/calatrava/templates/shell/pages/converter/conversionForm.haml +12 -0
- data/lib/calatrava/templates/shell/pages/converter/page.conversionForm.coffee +42 -0
- data/lib/calatrava/templates/shell/shell.scss +1 -0
- data/lib/calatrava/templates/shell/support/shell.coffee +21 -0
- data/lib/calatrava/templates/web/apache/conf/mime.types +1357 -0
- data/lib/calatrava/templates/web/app/source/bridge.coffee +158 -0
- data/lib/calatrava/templates/web/app/source/init.coffee +14 -0
- data/lib/calatrava/templates/web/app/views/index.haml +18 -0
- data/lib/calatrava/templates/web/deploy/instance.sh +10 -0
- data/lib/calatrava/templates/web/manifest.yml +1 -0
- data/lib/calatrava/version.rb +3 -0
- data/lib/calatrava.rb +5 -0
- 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 @@
|
|
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
|
+
|