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