]> git.proxmox.com Git - extjs.git/blame - extjs/packages/legacy/modern/src/device/communicator/Default.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / legacy / modern / src / device / communicator / Default.js
CommitLineData
6527f429
DM
1/**\r
2 * @private\r
3 *\r
4 * This object handles communication between the WebView and Sencha's native shell.\r
5 * Currently it has two primary responsibilities:\r
6 *\r
7 * 1. Maintaining unique string ids for callback functions, together with their scope objects\r
8 * 2. Serializing given object data into HTTP GET request parameters\r
9 *\r
10 * As an example, to capture a photo from the device's camera, we use `Ext.device.Camera.capture()` like:\r
11 *\r
12 * Ext.device.Camera.capture(\r
13 * function(dataUri){\r
14 * // Do something with the base64-encoded `dataUri` string\r
15 * },\r
16 * function(errorMessage) {\r
17 *\r
18 * },\r
19 * callbackScope,\r
20 * {\r
21 * quality: 75,\r
22 * width: 500,\r
23 * height: 500\r
24 * }\r
25 * );\r
26 *\r
27 * Internally, `Ext.device.Communicator.send()` will then be invoked with the following argument:\r
28 *\r
29 * Ext.device.Communicator.send({\r
30 * command: 'Camera#capture',\r
31 * callbacks: {\r
32 * onSuccess: function() {\r
33 * // ...\r
34 * },\r
35 * onError: function() {\r
36 * // ...\r
37 * }\r
38 * },\r
39 * scope: callbackScope,\r
40 * quality: 75,\r
41 * width: 500,\r
42 * height: 500\r
43 * });\r
44 *\r
45 * Which will then be transformed into a HTTP GET request, sent to native shell's local\r
46 * HTTP server with the following parameters:\r
47 *\r
48 * ?quality=75&width=500&height=500&command=Camera%23capture&onSuccess=3&onError=5\r
49 *\r
50 * Notice that `onSuccess` and `onError` have been converted into string ids (`3` and `5`\r
51 * respectively) and maintained by `Ext.device.Communicator`.\r
52 *\r
53 * Whenever the requested operation finishes, `Ext.device.Communicator.invoke()` simply needs\r
54 * to be executed from the native shell with the corresponding ids given before. For example:\r
55 *\r
56 * Ext.device.Communicator.invoke('3', ['DATA_URI_OF_THE_CAPTURED_IMAGE_HERE']);\r
57 *\r
58 * will invoke the original `onSuccess` callback under the given scope. (`callbackScope`), with\r
59 * the first argument of 'DATA_URI_OF_THE_CAPTURED_IMAGE_HERE'\r
60 *\r
61 * Note that `Ext.device.Communicator` maintains the uniqueness of each function callback and\r
62 * its scope object. If subsequent calls to `Ext.device.Communicator.send()` have the same\r
63 * callback references, the same old ids will simply be reused, which guarantee the best possible\r
64 * performance for a large amount of repetitive calls.\r
65 */\r
66Ext.define('Ext.device.communicator.Default', {\r
67\r
68 SERVER_URL: 'http://localhost:3000', // Change this to the correct server URL\r
69\r
70 callbackDataMap: {},\r
71\r
72 callbackIdMap: {},\r
73\r
74 idSeed: 0,\r
75\r
76 globalScopeId: '0',\r
77\r
78 generateId: function() {\r
79 return String(++this.idSeed);\r
80 },\r
81\r
82 getId: function(object) {\r
83 var id = object.$callbackId;\r
84\r
85 if (!id) {\r
86 object.$callbackId = id = this.generateId();\r
87 }\r
88\r
89 return id;\r
90 },\r
91\r
92 getCallbackId: function(callback, scope) {\r
93 var idMap = this.callbackIdMap,\r
94 dataMap = this.callbackDataMap,\r
95 id, scopeId, callbackId, data;\r
96\r
97 if (!scope) {\r
98 scopeId = this.globalScopeId;\r
99 } else if (scope.isIdentifiable) {\r
100 scopeId = scope.getId();\r
101 } else {\r
102 scopeId = this.getId(scope);\r
103 }\r
104\r
105 callbackId = this.getId(callback);\r
106\r
107 if (!idMap[scopeId]) {\r
108 idMap[scopeId] = {};\r
109 }\r
110\r
111 if (!idMap[scopeId][callbackId]) {\r
112 id = this.generateId();\r
113 data = {\r
114 callback: callback,\r
115 scope: scope\r
116 };\r
117\r
118 idMap[scopeId][callbackId] = id;\r
119 dataMap[id] = data;\r
120 }\r
121\r
122 return idMap[scopeId][callbackId];\r
123 },\r
124\r
125 getCallbackData: function(id) {\r
126 return this.callbackDataMap[id];\r
127 },\r
128\r
129 invoke: function(id, args) {\r
130 var data = this.getCallbackData(id);\r
131\r
132 data.callback.apply(data.scope, args);\r
133 },\r
134\r
135 send: function(args) {\r
136 var callbacks, scope, name, callback;\r
137\r
138 if (!args) {\r
139 args = {};\r
140 } else if (args.callbacks) {\r
141 callbacks = args.callbacks;\r
142 scope = args.scope;\r
143\r
144 delete args.callbacks;\r
145 delete args.scope;\r
146\r
147 for (name in callbacks) {\r
148 if (callbacks.hasOwnProperty(name)) {\r
149 callback = callbacks[name];\r
150\r
151 if (typeof callback == 'function') {\r
152 args[name] = this.getCallbackId(callback, scope);\r
153 }\r
154 }\r
155 }\r
156 }\r
157\r
158 args.__source = document.location.href;\r
159\r
160 var result = this.doSend(args);\r
161\r
162 return (result && result.length > 0) ? JSON.parse(result) : null;\r
163 },\r
164\r
165 doSend: function(args) {\r
166 var xhr = new XMLHttpRequest();\r
167\r
168 xhr.open('GET', this.SERVER_URL + '?' + Ext.Object.toQueryString(args) + '&_dc=' + new Date().getTime(), false);\r
169\r
170 // wrap the request in a try/catch block so we can check if any errors are thrown and attempt to call any\r
171 // failure/callback functions if defined\r
172 try {\r
173 xhr.send(null);\r
174\r
175 return xhr.responseText;\r
176 } catch(e) {\r
177 if (args.failure) {\r
178 this.invoke(args.failure);\r
179 } else if (args.callback) {\r
180 this.invoke(args.callback);\r
181 }\r
182 }\r
183 }\r
184});\r