mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 21:01:34 +08:00
Merge pull request #179 from NativeScript/webview-src
Implemented #172.
This commit is contained in:
10
apps/tests/ui/web-view/test.html
Normal file
10
apps/tests/ui/web-view/test.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>MyTitle</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<span style="color:red">Test</span>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -13,9 +13,10 @@ import webViewModule = require("ui/web-view");
|
|||||||
// ### Declaring a WebView.
|
// ### Declaring a WebView.
|
||||||
//```XML
|
//```XML
|
||||||
// <Page>
|
// <Page>
|
||||||
// <WebView url="{{ someUrl }}" />
|
// <WebView src="{{ someUrl | pathToLocalFile | htmlString }}" />
|
||||||
// </Page>
|
// </Page>
|
||||||
//```
|
//```
|
||||||
|
|
||||||
// </snippet>
|
// </snippet>
|
||||||
|
|
||||||
var _createWebViewFunc = function (): webViewModule.WebView {
|
var _createWebViewFunc = function (): webViewModule.WebView {
|
||||||
@ -76,6 +77,128 @@ export var testLoadExistingUrl = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export var testLoadLocalFile = function () {
|
||||||
|
var newPage: page.Page;
|
||||||
|
var webView = _createWebViewFunc();
|
||||||
|
var pageFactory = function (): page.Page {
|
||||||
|
newPage = new page.Page();
|
||||||
|
newPage.content = webView;
|
||||||
|
return newPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.navigate(pageFactory);
|
||||||
|
|
||||||
|
var testFinished = false;
|
||||||
|
var actualHtml;
|
||||||
|
var actualTitle;
|
||||||
|
var actualError;
|
||||||
|
|
||||||
|
var expectedTitle = 'MyTitle';
|
||||||
|
var expectedHtml = '<span style="color:red">Test</span>';
|
||||||
|
|
||||||
|
// <snippet module="ui/web-view" title="WebView">
|
||||||
|
// ### Using WebView
|
||||||
|
// ``` JavaScript
|
||||||
|
webView.on(webViewModule.WebView.loadFinishedEvent, function (args: webViewModule.LoadEventData) {
|
||||||
|
// <hide>
|
||||||
|
if (webView.ios) {
|
||||||
|
actualHtml = webView.ios.stringByEvaluatingJavaScriptFromString("document.body.innerHTML").trim();
|
||||||
|
} else if (webView.android) {
|
||||||
|
actualTitle = webView.android.getTitle()
|
||||||
|
}
|
||||||
|
|
||||||
|
actualError = args.error;
|
||||||
|
testFinished = true;
|
||||||
|
// </hide>
|
||||||
|
var message;
|
||||||
|
if (!args.error) {
|
||||||
|
message = "WebView finished loading " + args.url;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = "Error loading " + args.url + ": " + args.error;
|
||||||
|
}
|
||||||
|
//console.log(message);
|
||||||
|
});
|
||||||
|
webView.src = "~/ui/web-view/test.html";
|
||||||
|
|
||||||
|
TKUnit.wait(4);
|
||||||
|
|
||||||
|
helper.goBack();
|
||||||
|
|
||||||
|
if (testFinished) {
|
||||||
|
if (webView.ios) {
|
||||||
|
TKUnit.assert(actualHtml === expectedHtml, "File ~/ui/web-view/test.html not loaded properly. Actual: " + actualHtml);
|
||||||
|
} else if (webView.android) {
|
||||||
|
TKUnit.assert(actualTitle === expectedTitle, "File ~/ui/web-view/test.html not loaded properly. Actual: " + actualTitle);
|
||||||
|
}
|
||||||
|
TKUnit.assert(actualError === undefined, actualError);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TKUnit.assert(false, "TIMEOUT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export var testLoadHTMLString = function () {
|
||||||
|
var newPage: page.Page;
|
||||||
|
var webView = _createWebViewFunc();
|
||||||
|
var pageFactory = function (): page.Page {
|
||||||
|
newPage = new page.Page();
|
||||||
|
newPage.content = webView;
|
||||||
|
return newPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.navigate(pageFactory);
|
||||||
|
|
||||||
|
var testFinished = false;
|
||||||
|
var actualHtml;
|
||||||
|
var actualTitle;
|
||||||
|
var actualError;
|
||||||
|
|
||||||
|
var expectedTitle = 'MyTitle';
|
||||||
|
var expectedHtml = '<span style="color:red">Test</span>';
|
||||||
|
|
||||||
|
// <snippet module="ui/web-view" title="WebView">
|
||||||
|
// ### Using WebView
|
||||||
|
// ``` JavaScript
|
||||||
|
webView.on(webViewModule.WebView.loadFinishedEvent, function (args: webViewModule.LoadEventData) {
|
||||||
|
// <hide>
|
||||||
|
if (webView.ios) {
|
||||||
|
actualHtml = webView.ios.stringByEvaluatingJavaScriptFromString("document.body.innerHTML").trim();
|
||||||
|
} else if (webView.android) {
|
||||||
|
actualTitle = webView.android.getTitle()
|
||||||
|
}
|
||||||
|
|
||||||
|
actualError = args.error;
|
||||||
|
testFinished = true;
|
||||||
|
// </hide>
|
||||||
|
var message;
|
||||||
|
if (!args.error) {
|
||||||
|
message = "WebView finished loading " + args.url;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = "Error loading " + args.url + ": " + args.error;
|
||||||
|
}
|
||||||
|
//console.log(message);
|
||||||
|
});
|
||||||
|
webView.src = '<!DOCTYPE html><html><head><title>MyTitle</title><meta charset="utf-8" /></head><body><span style="color:red">Test</span></body></html>';
|
||||||
|
|
||||||
|
TKUnit.wait(4);
|
||||||
|
|
||||||
|
helper.goBack();
|
||||||
|
|
||||||
|
if (testFinished) {
|
||||||
|
if (webView.ios) {
|
||||||
|
TKUnit.assert(actualHtml === expectedHtml, "HTML string not loaded properly. Actual: " + actualHtml);
|
||||||
|
} else if (webView.android) {
|
||||||
|
TKUnit.assert(actualTitle === expectedTitle, "HTML string not loaded properly. Actual: " + actualTitle);
|
||||||
|
}
|
||||||
|
TKUnit.assert(actualError === undefined, actualError);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TKUnit.assert(false, "TIMEOUT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export var testLoadInvalidUrl = function () {
|
export var testLoadInvalidUrl = function () {
|
||||||
var newPage: page.Page;
|
var newPage: page.Page;
|
||||||
var webView = _createWebViewFunc();
|
var webView = _createWebViewFunc();
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<TabViewItem.view>
|
<TabViewItem.view>
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
|
|
||||||
|
<WebView src="<html><body><span style='color:red'>Test</span></body></html>" />
|
||||||
|
|
||||||
<!--<ToolBar>
|
<!--<ToolBar>
|
||||||
<ToolBar.items>
|
<ToolBar.items>
|
||||||
<ToolBarItem>
|
<ToolBarItem>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import http = require("http");
|
import http = require("http");
|
||||||
import types = require("utils/types");
|
import utils = require("utils/utils");
|
||||||
|
|
||||||
// This is used for definition purposes only, it does not generate JavaScript for it.
|
// This is used for definition purposes only, it does not generate JavaScript for it.
|
||||||
import definition = require("image-source");
|
import definition = require("image-source");
|
||||||
|
|
||||||
var RESOURCE_PREFIX = "res://";
|
|
||||||
|
|
||||||
export function fromResource(name: string): definition.ImageSource {
|
export function fromResource(name: string): definition.ImageSource {
|
||||||
var image = new definition.ImageSource();
|
var image = new definition.ImageSource();
|
||||||
return image.loadFromResource(name) ? image : null;
|
return image.loadFromResource(name) ? image : null;
|
||||||
@ -40,18 +38,12 @@ export function fromFileOrResource(path: string): definition.ImageSource {
|
|||||||
throw new Error("Path \"" + "\" is not a valid file or resource.");
|
throw new Error("Path \"" + "\" is not a valid file or resource.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.indexOf(RESOURCE_PREFIX) === 0) {
|
if (path.indexOf(utils.RESOURCE_PREFIX) === 0) {
|
||||||
return fromResource(path.substr(RESOURCE_PREFIX.length));
|
return fromResource(path.substr(utils.RESOURCE_PREFIX.length));
|
||||||
}
|
}
|
||||||
return fromFile(path);
|
return fromFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isFileOrResourcePath(path: string): boolean {
|
export function isFileOrResourcePath(path: string): boolean {
|
||||||
if (!types.isString(path)) {
|
return utils.isFileOrResourcePath(path);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path.indexOf("~/") === 0 || // relative to AppRoot
|
|
||||||
path.indexOf("/") === 0 || // absolute path
|
|
||||||
path.indexOf(RESOURCE_PREFIX) === 0; // resource
|
|
||||||
}
|
}
|
2
image-source/image-source.d.ts
vendored
2
image-source/image-source.d.ts
vendored
@ -118,7 +118,7 @@ declare module "image-source" {
|
|||||||
export function fromFileOrResource(path: string): ImageSource;
|
export function fromFileOrResource(path: string): ImageSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the specified path points to a resource or local file.
|
* [Obsolete. Please use utils.isFileOrResourcePath instead!] Returns true if the specified path points to a resource or local file.
|
||||||
* @param path The path.
|
* @param path The path.
|
||||||
*/
|
*/
|
||||||
export function isFileOrResourcePath(path: string): boolean
|
export function isFileOrResourcePath(path: string): boolean
|
||||||
|
@ -22,11 +22,31 @@ function onUrlPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
|||||||
// register the setNativeValue callback
|
// register the setNativeValue callback
|
||||||
(<proxy.PropertyMetadata>urlProperty.metadata).onSetNativeValue = onUrlPropertyChanged;
|
(<proxy.PropertyMetadata>urlProperty.metadata).onSetNativeValue = onUrlPropertyChanged;
|
||||||
|
|
||||||
|
var srcProperty = new dependencyObservable.Property(
|
||||||
|
"src",
|
||||||
|
"WebView",
|
||||||
|
new proxy.PropertyMetadata("")
|
||||||
|
);
|
||||||
|
|
||||||
|
function onSrcPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||||
|
var webView = <WebView>data.object;
|
||||||
|
|
||||||
|
if (webView._suspendLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
webView._loadSrc(data.newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the setNativeValue callback
|
||||||
|
(<proxy.PropertyMetadata>srcProperty.metadata).onSetNativeValue = onSrcPropertyChanged;
|
||||||
|
|
||||||
export class WebView extends view.View implements definition.WebView {
|
export class WebView extends view.View implements definition.WebView {
|
||||||
public static loadStartedEvent = "loadStarted";
|
public static loadStartedEvent = "loadStarted";
|
||||||
public static loadFinishedEvent = "loadFinished";
|
public static loadFinishedEvent = "loadFinished";
|
||||||
|
|
||||||
public static urlProperty = urlProperty;
|
public static urlProperty = urlProperty;
|
||||||
|
public static srcProperty = srcProperty;
|
||||||
|
|
||||||
public _suspendLoading: boolean;
|
public _suspendLoading: boolean;
|
||||||
|
|
||||||
@ -42,6 +62,14 @@ export class WebView extends view.View implements definition.WebView {
|
|||||||
this._setValue(WebView.urlProperty, value);
|
this._setValue(WebView.urlProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get src(): string {
|
||||||
|
return this._getValue(WebView.srcProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
set src(value: string) {
|
||||||
|
this._setValue(WebView.srcProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public _onLoadFinished(url: string, error?: string) {
|
public _onLoadFinished(url: string, error?: string) {
|
||||||
|
|
||||||
this._suspendLoading = true;
|
this._suspendLoading = true;
|
||||||
@ -73,6 +101,10 @@ export class WebView extends view.View implements definition.WebView {
|
|||||||
throw new Error("This member is abstract.");
|
throw new Error("This member is abstract.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public _loadSrc(src: string) {
|
||||||
|
throw new Error("This member is abstract.");
|
||||||
|
}
|
||||||
|
|
||||||
get canGoBack(): boolean {
|
get canGoBack(): boolean {
|
||||||
throw new Error("This member is abstract.");
|
throw new Error("This member is abstract.");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import common = require("ui/web-view/web-view-common");
|
import common = require("ui/web-view/web-view-common");
|
||||||
import trace = require("trace");
|
import trace = require("trace");
|
||||||
|
import utils = require("utils/utils");
|
||||||
|
import fs = require("file-system");
|
||||||
|
|
||||||
declare var exports;
|
declare var exports;
|
||||||
require("utils/module-merge").merge(common, exports);
|
require("utils/module-merge").merge(common, exports);
|
||||||
@ -74,6 +76,31 @@ export class WebView extends common.WebView {
|
|||||||
this._android.loadUrl(url);
|
this._android.loadUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public _loadSrc(src: string) {
|
||||||
|
trace.write("WebView._loadSrc(" + src + ")", trace.categories.Debug);
|
||||||
|
|
||||||
|
this._android.stopLoading();
|
||||||
|
this._android.loadUrl("about:blank");
|
||||||
|
|
||||||
|
if (utils.isFileOrResourcePath(src)) {
|
||||||
|
|
||||||
|
if (src.indexOf("~/") === 0) {
|
||||||
|
src = fs.path.join(fs.knownFolders.currentApp().path, src.replace("~/", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = fs.File.fromPath(src);
|
||||||
|
if (file) {
|
||||||
|
file.readText().then((r) => {
|
||||||
|
this._android.loadData(r, "text/html", null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (src.indexOf("http://") === 0 || src.indexOf("https://") === 0) {
|
||||||
|
this._android.loadUrl(src);
|
||||||
|
} else {
|
||||||
|
this._android.loadData(src, "text/html", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get canGoBack(): boolean {
|
get canGoBack(): boolean {
|
||||||
return this._android.canGoBack();
|
return this._android.canGoBack();
|
||||||
}
|
}
|
||||||
|
7
ui/web-view/web-view.d.ts
vendored
7
ui/web-view/web-view.d.ts
vendored
@ -36,10 +36,15 @@ declare module "ui/web-view" {
|
|||||||
ios: UIWebView;
|
ios: UIWebView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets the url displayed by this instance.
|
* [Obsolete. Please use src instead!] Gets or sets the url displayed by this instance.
|
||||||
*/
|
*/
|
||||||
url: string;
|
url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets the url, local file path or HTML string.
|
||||||
|
*/
|
||||||
|
src: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a value indicating whether the WebView can navigate back.
|
* Gets a value indicating whether the WebView can navigate back.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import common = require("ui/web-view/web-view-common");
|
import common = require("ui/web-view/web-view-common");
|
||||||
import trace = require("trace");
|
import trace = require("trace");
|
||||||
|
import utils = require("utils/utils");
|
||||||
|
import fs = require("file-system");
|
||||||
|
|
||||||
declare var exports;
|
declare var exports;
|
||||||
require("utils/module-merge").merge(common, exports);
|
require("utils/module-merge").merge(common, exports);
|
||||||
@ -81,6 +83,32 @@ export class WebView extends common.WebView {
|
|||||||
this._ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(url)));
|
this._ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(url)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public _loadSrc(src: string) {
|
||||||
|
trace.write("WebView._loadSrc(" + src + ")", trace.categories.Debug);
|
||||||
|
|
||||||
|
if (this._ios.loading) {
|
||||||
|
this._ios.stopLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils.isFileOrResourcePath(src)) {
|
||||||
|
|
||||||
|
if (src.indexOf("~/") === 0) {
|
||||||
|
src = fs.path.join(fs.knownFolders.currentApp().path, src.replace("~/", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = fs.File.fromPath(src);
|
||||||
|
if (file) {
|
||||||
|
file.readText().then((r) => {
|
||||||
|
this._ios.loadHTMLStringBaseURL(r, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (src.indexOf("http://") === 0 || src.indexOf("https://") === 0) {
|
||||||
|
this._ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(src)));
|
||||||
|
} else {
|
||||||
|
this._ios.loadHTMLStringBaseURL(src, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get canGoBack(): boolean {
|
get canGoBack(): boolean {
|
||||||
return this._ios.canGoBack;
|
return this._ios.canGoBack;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import types = require("utils/types");
|
import types = require("utils/types");
|
||||||
|
|
||||||
|
export var RESOURCE_PREFIX = "res://";
|
||||||
|
|
||||||
export function copyFrom(source: any, target: any) {
|
export function copyFrom(source: any, target: any) {
|
||||||
if (types.isDefined(source) && types.isDefined(target)) {
|
if (types.isDefined(source) && types.isDefined(target)) {
|
||||||
var i: number;
|
var i: number;
|
||||||
@ -51,3 +53,13 @@ export module layout {
|
|||||||
return (spec & ~MODE_MASK);
|
return (spec & ~MODE_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFileOrResourcePath(path: string): boolean {
|
||||||
|
if (!types.isString(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.indexOf("~/") === 0 || // relative to AppRoot
|
||||||
|
path.indexOf("/") === 0 || // absolute path
|
||||||
|
path.indexOf(RESOURCE_PREFIX) === 0; // resource
|
||||||
|
}
|
8
utils/utils.d.ts
vendored
8
utils/utils.d.ts
vendored
@ -2,6 +2,8 @@
|
|||||||
import colorModule = require("color");
|
import colorModule = require("color");
|
||||||
import view = require("ui/core/view");
|
import view = require("ui/core/view");
|
||||||
|
|
||||||
|
export var RESOURCE_PREFIX: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility module related to layout.
|
* Utility module related to layout.
|
||||||
*/
|
*/
|
||||||
@ -132,4 +134,10 @@
|
|||||||
* An utility function that invokes garbage collection on the JavaScript side.
|
* An utility function that invokes garbage collection on the JavaScript side.
|
||||||
*/
|
*/
|
||||||
export function GC();
|
export function GC();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the specified path points to a resource or local file.
|
||||||
|
* @param path The path.
|
||||||
|
*/
|
||||||
|
export function isFileOrResourcePath(path: string): boolean
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user