1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | var cordova = require('cordova');
|
26 | var urlutil = require('cordova/urlutil');
|
27 |
|
28 | var browserWrap,
|
29 | popup,
|
30 | navigationButtonsDiv,
|
31 | navigationButtonsDivInner,
|
32 | backButton,
|
33 | forwardButton,
|
34 | closeButton,
|
35 | bodyOverflowStyle,
|
36 | navigationEventsCallback,
|
37 | hardwareBackCallback;
|
38 |
|
39 |
|
40 |
|
41 | var isWebViewAvailable = cordova.platformId === 'windows';
|
42 |
|
43 | function attachNavigationEvents (element, callback) {
|
44 | if (isWebViewAvailable) {
|
45 | element.addEventListener('MSWebViewNavigationStarting', function (e) {
|
46 | callback({ type: 'loadstart', url: e.uri }, { keepCallback: true });
|
47 | });
|
48 |
|
49 | element.addEventListener('MSWebViewNavigationCompleted', function (e) {
|
50 | if (e.isSuccess) {
|
51 | callback({ type: 'loadstop', url: e.uri }, { keepCallback: true });
|
52 | } else {
|
53 | callback(
|
54 | {
|
55 | type: 'loaderror',
|
56 | url: e.uri,
|
57 | code: e.webErrorStatus,
|
58 | message: 'Navigation failed with error code ' + e.webErrorStatus
|
59 | },
|
60 | { keepCallback: true }
|
61 | );
|
62 | }
|
63 | });
|
64 |
|
65 | element.addEventListener('MSWebViewUnviewableContentIdentified', function (e) {
|
66 |
|
67 |
|
68 | callback(
|
69 | { type: 'loaderror', url: e.uri, code: e.webErrorStatus, message: 'Navigation failed with error code ' + e.webErrorStatus },
|
70 | { keepCallback: true }
|
71 | );
|
72 | });
|
73 |
|
74 | element.addEventListener('MSWebViewContentLoading', function (e) {
|
75 | if (navigationButtonsDiv && popup) {
|
76 | if (popup.canGoBack) {
|
77 | backButton.removeAttribute('disabled');
|
78 | } else {
|
79 | backButton.setAttribute('disabled', 'true');
|
80 | }
|
81 |
|
82 | if (popup.canGoForward) {
|
83 | forwardButton.removeAttribute('disabled');
|
84 | } else {
|
85 | forwardButton.setAttribute('disabled', 'true');
|
86 | }
|
87 | }
|
88 | });
|
89 | } else {
|
90 | var onError = function () {
|
91 | callback({ type: 'loaderror', url: this.contentWindow.location }, { keepCallback: true });
|
92 | };
|
93 |
|
94 | element.addEventListener('unload', function () {
|
95 | callback({ type: 'loadstart', url: this.contentWindow.location }, { keepCallback: true });
|
96 | });
|
97 |
|
98 | element.addEventListener('load', function () {
|
99 | callback({ type: 'loadstop', url: this.contentWindow.location }, { keepCallback: true });
|
100 | });
|
101 |
|
102 | element.addEventListener('error', onError);
|
103 | element.addEventListener('abort', onError);
|
104 | }
|
105 | }
|
106 |
|
107 | var IAB = {
|
108 | close: function (win, lose) {
|
109 | setImmediate(function () {
|
110 | if (browserWrap) {
|
111 | if (navigationEventsCallback) {
|
112 | navigationEventsCallback({ type: 'exit' });
|
113 | }
|
114 |
|
115 | browserWrap.parentNode.removeChild(browserWrap);
|
116 |
|
117 | document.body.style.msOverflowStyle = bodyOverflowStyle;
|
118 | browserWrap = null;
|
119 | popup = null;
|
120 |
|
121 | document.removeEventListener('backbutton', hardwareBackCallback, false);
|
122 | }
|
123 | });
|
124 | },
|
125 | show: function (win, lose) {
|
126 | setImmediate(function () {
|
127 | if (browserWrap) {
|
128 | browserWrap.style.display = 'block';
|
129 | }
|
130 | });
|
131 | },
|
132 | hide: function (win, lose) {
|
133 | if (browserWrap) {
|
134 | browserWrap.style.display = 'none';
|
135 | }
|
136 | },
|
137 | open: function (win, lose, args) {
|
138 |
|
139 | setImmediate(function () {
|
140 | var strUrl = args[0];
|
141 | var target = args[1];
|
142 | var features = args[2];
|
143 | var url;
|
144 |
|
145 | navigationEventsCallback = win;
|
146 |
|
147 | if (target === '_system') {
|
148 | url = new Windows.Foundation.Uri(strUrl);
|
149 | Windows.System.Launcher.launchUriAsync(url);
|
150 | } else if (target === '_self' || !target) {
|
151 | window.location = strUrl;
|
152 | } else {
|
153 |
|
154 | if (!browserWrap) {
|
155 | var browserWrapStyle = document.createElement('link');
|
156 | browserWrapStyle.rel = 'stylesheet';
|
157 | browserWrapStyle.type = 'text/css';
|
158 | browserWrapStyle.href = urlutil.makeAbsolute('/www/css/inappbrowser.css');
|
159 |
|
160 | document.head.appendChild(browserWrapStyle);
|
161 |
|
162 | browserWrap = document.createElement('div');
|
163 | browserWrap.className = 'inAppBrowserWrap';
|
164 |
|
165 | if (features.indexOf('fullscreen=yes') > -1) {
|
166 | browserWrap.classList.add('inAppBrowserWrapFullscreen');
|
167 | }
|
168 |
|
169 |
|
170 | bodyOverflowStyle = document.body.style.msOverflowStyle;
|
171 |
|
172 | browserWrap.onclick = function () {
|
173 | setTimeout(function () {
|
174 | IAB.close(navigationEventsCallback);
|
175 | }, 0);
|
176 | };
|
177 |
|
178 | document.body.appendChild(browserWrap);
|
179 |
|
180 | document.body.style.msOverflowStyle = 'none';
|
181 | }
|
182 |
|
183 | if (features.indexOf('hidden=yes') !== -1) {
|
184 | browserWrap.style.display = 'none';
|
185 | }
|
186 |
|
187 | popup = document.createElement(isWebViewAvailable ? 'x-ms-webview' : 'iframe');
|
188 | if (popup instanceof HTMLIFrameElement) {
|
189 |
|
190 |
|
191 |
|
192 | popup.style.backgroundColor = 'white';
|
193 | }
|
194 | popup.style.borderWidth = '0px';
|
195 | popup.style.width = '100%';
|
196 | popup.style.marginBottom = '-5px';
|
197 |
|
198 | browserWrap.appendChild(popup);
|
199 |
|
200 | var closeHandler = function (e) {
|
201 | setTimeout(function () {
|
202 | IAB.close(navigationEventsCallback);
|
203 | }, 0);
|
204 | };
|
205 |
|
206 | if (features.indexOf('hardwareback=yes') > -1 || features.indexOf('hardwareback') === -1) {
|
207 | hardwareBackCallback = function () {
|
208 | if (browserWrap.style.display === 'none') {
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | throw 'Exit the app';
|
214 | }
|
215 |
|
216 | if (popup.canGoBack) {
|
217 | popup.goBack();
|
218 | } else {
|
219 | closeHandler();
|
220 | }
|
221 | };
|
222 | } else if (features.indexOf('hardwareback=no') > -1) {
|
223 | hardwareBackCallback = function () {
|
224 | if (browserWrap.style.display === 'none') {
|
225 |
|
226 | throw 'Exit the app';
|
227 | }
|
228 |
|
229 | closeHandler();
|
230 | };
|
231 | }
|
232 |
|
233 | document.addEventListener('backbutton', hardwareBackCallback, false);
|
234 |
|
235 | if (features.indexOf('location=yes') !== -1 || features.indexOf('location') === -1) {
|
236 | popup.style.height = 'calc(100% - 70px)';
|
237 |
|
238 | navigationButtonsDiv = document.createElement('div');
|
239 | navigationButtonsDiv.className = 'inappbrowser-app-bar';
|
240 | navigationButtonsDiv.onclick = function (e) {
|
241 | e.cancelBubble = true;
|
242 | };
|
243 |
|
244 | navigationButtonsDivInner = document.createElement('div');
|
245 | navigationButtonsDivInner.className = 'inappbrowser-app-bar-inner';
|
246 | navigationButtonsDivInner.onclick = function (e) {
|
247 | e.cancelBubble = true;
|
248 | };
|
249 |
|
250 | backButton = document.createElement('div');
|
251 | backButton.innerText = 'back';
|
252 | backButton.className = 'app-bar-action action-back';
|
253 | backButton.addEventListener('click', function (e) {
|
254 | if (popup.canGoBack) {
|
255 | popup.goBack();
|
256 | }
|
257 | });
|
258 |
|
259 | forwardButton = document.createElement('div');
|
260 | forwardButton.innerText = 'forward';
|
261 | forwardButton.className = 'app-bar-action action-forward';
|
262 | forwardButton.addEventListener('click', function (e) {
|
263 | if (popup.canGoForward) {
|
264 | popup.goForward();
|
265 | }
|
266 | });
|
267 |
|
268 | closeButton = document.createElement('div');
|
269 | closeButton.innerText = 'close';
|
270 | closeButton.className = 'app-bar-action action-close';
|
271 | closeButton.addEventListener('click', closeHandler);
|
272 |
|
273 | if (!isWebViewAvailable) {
|
274 |
|
275 | backButton.setAttribute('disabled', 'true');
|
276 | forwardButton.setAttribute('disabled', 'true');
|
277 | }
|
278 |
|
279 | navigationButtonsDivInner.appendChild(backButton);
|
280 | navigationButtonsDivInner.appendChild(forwardButton);
|
281 | navigationButtonsDivInner.appendChild(closeButton);
|
282 | navigationButtonsDiv.appendChild(navigationButtonsDivInner);
|
283 |
|
284 | browserWrap.appendChild(navigationButtonsDiv);
|
285 | } else {
|
286 | popup.style.height = '100%';
|
287 | }
|
288 |
|
289 |
|
290 | attachNavigationEvents(popup, navigationEventsCallback);
|
291 |
|
292 | if (isWebViewAvailable) {
|
293 | strUrl = strUrl.replace('ms-appx://', 'ms-appx-web://');
|
294 | }
|
295 | popup.src = strUrl;
|
296 | }
|
297 | });
|
298 | },
|
299 |
|
300 | injectScriptCode: function (win, fail, args) {
|
301 | setImmediate(function () {
|
302 | var code = args[0];
|
303 | var hasCallback = args[1];
|
304 |
|
305 | if (isWebViewAvailable && browserWrap && popup) {
|
306 | var op = popup.invokeScriptAsync('eval', code);
|
307 | op.oncomplete = function (e) {
|
308 | if (hasCallback) {
|
309 |
|
310 | var result = e && e.target ? [e.target.result] : [null];
|
311 | win(result);
|
312 | }
|
313 | };
|
314 | op.onerror = function () {};
|
315 | op.start();
|
316 | }
|
317 | });
|
318 | },
|
319 |
|
320 | injectScriptFile: function (win, fail, args) {
|
321 | setImmediate(function () {
|
322 | var filePath = args[0];
|
323 | var hasCallback = args[1];
|
324 |
|
325 | if (filePath) {
|
326 | filePath = urlutil.makeAbsolute(filePath);
|
327 | }
|
328 |
|
329 | if (isWebViewAvailable && browserWrap && popup) {
|
330 |
|
331 | var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
|
332 | Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) {
|
333 | Windows.Storage.FileIO.readTextAsync(file).done(function (code) {
|
334 | var op = popup.invokeScriptAsync('eval', code);
|
335 | op.oncomplete = function (e) {
|
336 | if (hasCallback) {
|
337 | var result = [e.target.result];
|
338 | win(result);
|
339 | }
|
340 | };
|
341 | op.onerror = function () {};
|
342 | op.start();
|
343 | });
|
344 | });
|
345 | }
|
346 | });
|
347 | },
|
348 |
|
349 | injectStyleCode: function (win, fail, args) {
|
350 | setImmediate(function () {
|
351 | var code = args[0];
|
352 | var hasCallback = args[1];
|
353 |
|
354 | if (isWebViewAvailable && browserWrap && popup) {
|
355 | injectCSS(popup, code, hasCallback && win);
|
356 | }
|
357 | });
|
358 | },
|
359 |
|
360 | injectStyleFile: function (win, fail, args) {
|
361 | setImmediate(function () {
|
362 | var filePath = args[0];
|
363 | var hasCallback = args[1];
|
364 |
|
365 | filePath = filePath && urlutil.makeAbsolute(filePath);
|
366 |
|
367 | if (isWebViewAvailable && browserWrap && popup) {
|
368 |
|
369 | var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
|
370 | Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri)
|
371 | .then(function (file) {
|
372 | return Windows.Storage.FileIO.readTextAsync(file);
|
373 | })
|
374 | .done(
|
375 | function (code) {
|
376 | injectCSS(popup, code, hasCallback && win);
|
377 | },
|
378 | function () {
|
379 |
|
380 | }
|
381 | );
|
382 | }
|
383 | });
|
384 | }
|
385 | };
|
386 |
|
387 | function injectCSS (webView, cssCode, callback) {
|
388 |
|
389 | var escapedCode = JSON.stringify(cssCode);
|
390 | var evalWrapper = "(function(d){var c=d.createElement('style');c.innerHTML=%s;d.head.appendChild(c);})(document)".replace(
|
391 | '%s',
|
392 | escapedCode
|
393 | );
|
394 |
|
395 | var op = webView.invokeScriptAsync('eval', evalWrapper);
|
396 | op.oncomplete = function () {
|
397 | if (callback) {
|
398 | callback([]);
|
399 | }
|
400 | };
|
401 | op.onerror = function () {};
|
402 | op.start();
|
403 | }
|
404 |
|
405 | module.exports = IAB;
|
406 |
|
407 | require('cordova/exec/proxy').add('InAppBrowser', module.exports);
|