可编辑的 WKWebView
Editable WKWebView
我在 WKWebView 中显示 .html 和 .xml 文件。
我正在连接所有数据并在 WKWevView
中显示以下字符串
sourceWebView.loadHTMLString(sourceHtmlStr, baseURL: nil)
在加载内容后,我使用下面的方法使我的 webview 可编辑,即
webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){}
singleWebView.evaluateJavaScript("document.body.setAttribute('contentEditable','true')") { (anyObj: Any?, error: Error?) in
if anyObj != nil{
print("AnyObj in jave script : \(anyObj!)")
}
if error != nil{
print("Error in Java script : \(error!)")
}
}
以上代码使 WKWebView 成为可编辑的。但我不确定如何保存编辑后的值。
我按照 Link 并使用了下面的代码
我在 .js 文件中有以下代码
var richeditor = {};
var editor = document.getElementById("editor");
richeditor.insertText = function(text) {
editor.innerHTML = text;
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}
editor.addEventListener("input", function() {
window.webkit.messageHandlers.textDidChange.postMessage(editor.innerHTML);
}, false)
document.addEventListener("selectionchange", function() {
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}, false);
在 WindowDidLoad 中:
guard let scriptPath = Bundle.main.path(forResource: "RichTextEditor", ofType: "js"),
let scriptContent = try? String(contentsOfFile: scriptPath, encoding: String.Encoding.utf8)
else {
print("Unable to find javscript for text editor")
return
}
singleWebView.configuration.userContentController.addUserScript(WKUserScript(source: scriptContent, injectionTime: .atDocumentEnd, forMainFrameOnly: true))
let configuration = singleWebView.configuration
[ShowPreviewWindowContoller.textDidChange, ShowPreviewWindowContoller.heightDidChange].forEach {
configuration.userContentController.add(WeakScriptMessageHandler(delegate: self), name: [=13=])
}
并添加了以下方法:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case ShowPreviewWindowContoller.textDidChange:
guard let body = message.body as? String else { return }
delegate?.textDidChange(text: body)
case ShowPreviewWindowContoller.heightDidChange:
guard let height = message.body as? CGFloat else { return }
self.height = height > ShowPreviewWindowContoller.defaultHeight ? height + 30 : ShowPreviewWindowContoller.defaultHeight
delegate?.heightDidChange()
default:
break
}
}
这种实现方式是不保存编辑后的数据。
这里还要注意的是我在 html 字符串中没有“editor”元素。
我不太确定 html 字符串有哪些元素,因为文件不是常量,元素可以是任何东西。
抱歉这个问题太长了。
请让我知道如何实施。
编辑 WKWebView,将编辑好的文本保存回来。
另外我会有很多像下面这样的字符串,我需要确保我替换成准确的元素
<trans-unit id="0000000006" datatype="x-text/xml" restype="string">
<target>Some Text here</target>
</trans-unit>
<trans-unit id="0000000007" datatype="x-text/xml" restype="string">
<target>Some Text here</target>
</trans-unit>
我正在使用下面的 HTML 字符串,请注意我确实无法控制 html,我显示用户选择的内容。
编辑:添加修改后的html字符串
<!doctype html>\n
<html>
\n
<head>
\n
<meta charset=\"UTF-8\">
\n<meta name=\"description\" content=\"AppleCare Training authored this course. If you use this course outside the AppleCare Training site, give credit to its author.\">\n<!-- If you are using an interaction to mark the page complete or if it is an AA page, change mark_complete to false -->\n
<meta name=\"template_version\" content=\"01.05.2015\">
\n
<meta name=\"page\" content=\" \" mark_complete=\"false\">
\n
<link href=\"https://idesk.corp.apple.com/training/ce/_common/css/sgt.css\" media=\"screen, projection\" rel=\"stylesheet\" type=\"text/css\"/>
\n<script>\n\tvar url = window.location.href;\n\tvar filename = \"\";\n\tvar is_local = url.substr(0,4);\n\tif(is_local==\"file\" || window.location.hostname === \"localhost\"){\n\t\t//Local Common Folder Location\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/ready.js\">\x3C/script>\');\n\t}else{\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/ready.js\">\x3C/script>\');\n\t}\n</script>\n\n
<title>
<target id=2>Key Terms and Concepts</target>
</title>
\n
</head>
\n\n
<body class=\"aa\">
\n\n\t\t\t<!-- BEGIN PAGE CONTENT -->\n\t
<div id=\"maincontent\">
\n
<div id=\"learningcontentdiv\">
\n
<div id=\"morelearningcontentdiv\"></div>
\n
</div>
\n\t\t\t
<div id=\"content\">
\n
<div id=\"close_aa_term\">
<target id=4>×</target>
</div>
\n
<h2>
<target id=6>Key Terms and Concepts</target>
</h2>
\n
<p>
<target id=8>You should already be familiar with all the terms in this module.</target>
\t
</p>
\n\t
</div>
\n
</div>
\n\n<!-- END PAGE CONTENT -->\n
</body>
\n
</html>
尝试使用此示例代码按预期工作。
class ViewController: UIViewController, WKScriptMessageHandler {
var htmlString = """
<!doctype html>\n
<html>
\n
<head>
\n
<meta charset=\"UTF-8\">
\n<meta name=\"description\" content=\"AppleCare Training authored this course. If you use this course outside the AppleCare Training site, give credit to its author.\">\n<!-- If you are using an interaction to mark the page complete or if it is an AA page, change mark_complete to false -->\n
<meta name=\"template_version\" content=\"01.05.2015\">
\n
<meta name=\"page\" content=\" \" mark_complete=\"false\">
\n
<link href=\"https://idesk.corp.apple.com/training/ce/_common/css/sgt.css\" media=\"screen, projection\" rel=\"stylesheet\" type=\"text/css\"/>
\n<script>\n\tvar url = window.location.href;\n\tvar filename = \"\";\n\tvar is_local = url.substr(0,4);\n\tif(is_local==\"file\" || window.location.hostname === \"localhost\"){\n\t\t//Local Common Folder Location\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/ready.js\">\x3C/script>\');\n\t}else{\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/ready.js\">\x3C/script>\');\n\t}\n</script>\n\n
<title>
<target id=2>Key Terms and Concepts</target>
</title>
\n
</head>
\n\n
<body class=\"aa\">
\n\n\t\t\t<!-- BEGIN PAGE CONTENT -->\n\t
<div id=\"maincontent\">
\n
<div id=\"learningcontentdiv\">
\n
<div id=\"morelearningcontentdiv\"></div>
\n
</div>
\n\t\t\t
<div id=\"content\">
\n
<div id=\"close_aa_term\">
<target id=4>×</target>
</div>
\n
<h2>
<target id=6>Key Terms and Concepts</target>
</h2>
\n
<p>
<target id=8>You should already be familiar with all the terms in this module.</target>
\t
</p>
\n\t
</div>
\n
</div>
\n\n<!-- END PAGE CONTENT -->\n
</body>
\n
</html>
"""
var javaScript = """
var richeditor = {};
var editor = document.body;
function getActiveDiv() {
var sel = window.getSelection();
var range = sel.getRangeAt(0);
var node = document.createElement('span');
range.insertNode(node);
range = range.cloneRange();
range.selectNodeContents(node);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
var activeDiv = node.parentNode;
node.parentNode.removeChild(node);
return activeDiv;
}
richeditor.insertText = function(text) {
editor.innerHTML = text;
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}
editor.addEventListener("input", function() {
var activeElement = getActiveDiv()
window.webkit.messageHandlers.textDidChange.postMessage("activeElement ID = "+ activeElement.id + " and TEXT = " + activeElement.innerHTML);
}, false)
document.addEventListener("selectionchange", function() {
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}, false);
"""
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
config.userContentController.add(self, name: "heightDidChange")
config.userContentController.add(self, name: "textDidChange")
config.userContentController.addUserScript(WKUserScript(source: javaScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true))
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 400, height: 400), configuration: config)
view.addSubview(webView)
webView.loadHTMLString(htmlString, baseURL: nil)
webView.navigationDelegate = self
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print(message.name)
let body = message.body
print(body)
}
}
extension ViewController : WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){
webView.evaluateJavaScript("document.body.setAttribute('contentEditable','true')") { (anyObj: Any?, error: Error?) in
if anyObj != nil{
print("AnyObj in jave script : \(anyObj!)")
}
if error != nil{
print("Error in Java script : \(error!)")
}
}
}
}
我在 WKWebView 中显示 .html 和 .xml 文件。 我正在连接所有数据并在 WKWevView
中显示以下字符串sourceWebView.loadHTMLString(sourceHtmlStr, baseURL: nil)
在加载内容后,我使用下面的方法使我的 webview 可编辑,即
webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){}
singleWebView.evaluateJavaScript("document.body.setAttribute('contentEditable','true')") { (anyObj: Any?, error: Error?) in
if anyObj != nil{
print("AnyObj in jave script : \(anyObj!)")
}
if error != nil{
print("Error in Java script : \(error!)")
}
}
以上代码使 WKWebView 成为可编辑的。但我不确定如何保存编辑后的值。 我按照 Link 并使用了下面的代码
我在 .js 文件中有以下代码
var richeditor = {};
var editor = document.getElementById("editor");
richeditor.insertText = function(text) {
editor.innerHTML = text;
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}
editor.addEventListener("input", function() {
window.webkit.messageHandlers.textDidChange.postMessage(editor.innerHTML);
}, false)
document.addEventListener("selectionchange", function() {
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}, false);
在 WindowDidLoad 中:
guard let scriptPath = Bundle.main.path(forResource: "RichTextEditor", ofType: "js"),
let scriptContent = try? String(contentsOfFile: scriptPath, encoding: String.Encoding.utf8)
else {
print("Unable to find javscript for text editor")
return
}
singleWebView.configuration.userContentController.addUserScript(WKUserScript(source: scriptContent, injectionTime: .atDocumentEnd, forMainFrameOnly: true))
let configuration = singleWebView.configuration
[ShowPreviewWindowContoller.textDidChange, ShowPreviewWindowContoller.heightDidChange].forEach {
configuration.userContentController.add(WeakScriptMessageHandler(delegate: self), name: [=13=])
}
并添加了以下方法:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case ShowPreviewWindowContoller.textDidChange:
guard let body = message.body as? String else { return }
delegate?.textDidChange(text: body)
case ShowPreviewWindowContoller.heightDidChange:
guard let height = message.body as? CGFloat else { return }
self.height = height > ShowPreviewWindowContoller.defaultHeight ? height + 30 : ShowPreviewWindowContoller.defaultHeight
delegate?.heightDidChange()
default:
break
}
}
这种实现方式是不保存编辑后的数据。
这里还要注意的是我在 html 字符串中没有“editor”元素。 我不太确定 html 字符串有哪些元素,因为文件不是常量,元素可以是任何东西。
抱歉这个问题太长了。 请让我知道如何实施。 编辑 WKWebView,将编辑好的文本保存回来。 另外我会有很多像下面这样的字符串,我需要确保我替换成准确的元素
<trans-unit id="0000000006" datatype="x-text/xml" restype="string">
<target>Some Text here</target>
</trans-unit>
<trans-unit id="0000000007" datatype="x-text/xml" restype="string">
<target>Some Text here</target>
</trans-unit>
我正在使用下面的 HTML 字符串,请注意我确实无法控制 html,我显示用户选择的内容。
编辑:添加修改后的html字符串
<!doctype html>\n
<html>
\n
<head>
\n
<meta charset=\"UTF-8\">
\n<meta name=\"description\" content=\"AppleCare Training authored this course. If you use this course outside the AppleCare Training site, give credit to its author.\">\n<!-- If you are using an interaction to mark the page complete or if it is an AA page, change mark_complete to false -->\n
<meta name=\"template_version\" content=\"01.05.2015\">
\n
<meta name=\"page\" content=\" \" mark_complete=\"false\">
\n
<link href=\"https://idesk.corp.apple.com/training/ce/_common/css/sgt.css\" media=\"screen, projection\" rel=\"stylesheet\" type=\"text/css\"/>
\n<script>\n\tvar url = window.location.href;\n\tvar filename = \"\";\n\tvar is_local = url.substr(0,4);\n\tif(is_local==\"file\" || window.location.hostname === \"localhost\"){\n\t\t//Local Common Folder Location\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/ready.js\">\x3C/script>\');\n\t}else{\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/ready.js\">\x3C/script>\');\n\t}\n</script>\n\n
<title>
<target id=2>Key Terms and Concepts</target>
</title>
\n
</head>
\n\n
<body class=\"aa\">
\n\n\t\t\t<!-- BEGIN PAGE CONTENT -->\n\t
<div id=\"maincontent\">
\n
<div id=\"learningcontentdiv\">
\n
<div id=\"morelearningcontentdiv\"></div>
\n
</div>
\n\t\t\t
<div id=\"content\">
\n
<div id=\"close_aa_term\">
<target id=4>×</target>
</div>
\n
<h2>
<target id=6>Key Terms and Concepts</target>
</h2>
\n
<p>
<target id=8>You should already be familiar with all the terms in this module.</target>
\t
</p>
\n\t
</div>
\n
</div>
\n\n<!-- END PAGE CONTENT -->\n
</body>
\n
</html>
尝试使用此示例代码按预期工作。
class ViewController: UIViewController, WKScriptMessageHandler {
var htmlString = """
<!doctype html>\n
<html>
\n
<head>
\n
<meta charset=\"UTF-8\">
\n<meta name=\"description\" content=\"AppleCare Training authored this course. If you use this course outside the AppleCare Training site, give credit to its author.\">\n<!-- If you are using an interaction to mark the page complete or if it is an AA page, change mark_complete to false -->\n
<meta name=\"template_version\" content=\"01.05.2015\">
\n
<meta name=\"page\" content=\" \" mark_complete=\"false\">
\n
<link href=\"https://idesk.corp.apple.com/training/ce/_common/css/sgt.css\" media=\"screen, projection\" rel=\"stylesheet\" type=\"text/css\"/>
\n<script>\n\tvar url = window.location.href;\n\tvar filename = \"\";\n\tvar is_local = url.substr(0,4);\n\tif(is_local==\"file\" || window.location.hostname === \"localhost\"){\n\t\t//Local Common Folder Location\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"http://localhost/_common/js/ready.js\">\x3C/script>\');\n\t}else{\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/jquery.js\">\x3C/script>\');\n\t\tdocument.write(\'\x3Cscript type=\"text/javascript\" src=\"/training/ce/_common/js/ready.js\">\x3C/script>\');\n\t}\n</script>\n\n
<title>
<target id=2>Key Terms and Concepts</target>
</title>
\n
</head>
\n\n
<body class=\"aa\">
\n\n\t\t\t<!-- BEGIN PAGE CONTENT -->\n\t
<div id=\"maincontent\">
\n
<div id=\"learningcontentdiv\">
\n
<div id=\"morelearningcontentdiv\"></div>
\n
</div>
\n\t\t\t
<div id=\"content\">
\n
<div id=\"close_aa_term\">
<target id=4>×</target>
</div>
\n
<h2>
<target id=6>Key Terms and Concepts</target>
</h2>
\n
<p>
<target id=8>You should already be familiar with all the terms in this module.</target>
\t
</p>
\n\t
</div>
\n
</div>
\n\n<!-- END PAGE CONTENT -->\n
</body>
\n
</html>
"""
var javaScript = """
var richeditor = {};
var editor = document.body;
function getActiveDiv() {
var sel = window.getSelection();
var range = sel.getRangeAt(0);
var node = document.createElement('span');
range.insertNode(node);
range = range.cloneRange();
range.selectNodeContents(node);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
var activeDiv = node.parentNode;
node.parentNode.removeChild(node);
return activeDiv;
}
richeditor.insertText = function(text) {
editor.innerHTML = text;
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}
editor.addEventListener("input", function() {
var activeElement = getActiveDiv()
window.webkit.messageHandlers.textDidChange.postMessage("activeElement ID = "+ activeElement.id + " and TEXT = " + activeElement.innerHTML);
}, false)
document.addEventListener("selectionchange", function() {
window.webkit.messageHandlers.heightDidChange.postMessage(document.body.offsetHeight);
}, false);
"""
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
config.userContentController.add(self, name: "heightDidChange")
config.userContentController.add(self, name: "textDidChange")
config.userContentController.addUserScript(WKUserScript(source: javaScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true))
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 400, height: 400), configuration: config)
view.addSubview(webView)
webView.loadHTMLString(htmlString, baseURL: nil)
webView.navigationDelegate = self
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print(message.name)
let body = message.body
print(body)
}
}
extension ViewController : WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){
webView.evaluateJavaScript("document.body.setAttribute('contentEditable','true')") { (anyObj: Any?, error: Error?) in
if anyObj != nil{
print("AnyObj in jave script : \(anyObj!)")
}
if error != nil{
print("Error in Java script : \(error!)")
}
}
}
}