如何使用 Swift 将鼠标悬停在 URL 上进入 WkWebView
how to get mouse over URLs into WkWebView with Swift
作为 的后续行动,我有一个相关问题,但使用 Swift。
我需要在鼠标悬停时获取 URL,作为上下文菜单出现的前奏,因此我可以将其注入菜单项的 respresentedObject - 或者以其他方式保存。某些项目的内置操作未得到正确处理。
我发现 'Open Link' 的菜单项操作正常,但 'Open Link in New Window' 不行;这些都不是通过内置的上下文菜单项操作来工作的。我想支持一个中间按钮点击成为后面的菜单项。
所以,使用原始 post 作为基础我有这个 - 我还子 class WkWebView,添加
class MyWebView : WKWebView {
var selectedText : String?
var selectedURL : URL?
}
然后在视图控制器中
func viewDidLoad() {
// Watch javascript selection messages
let controller = webView.configuration.userContentController
controller.add(self, name: "newSelectionDetected")
let js = """
function getSelectionAndSendMessage()
{
var txt = document.getSelection().toString() ;
window.webkit.messageHandlers.newSelectionDetected.postMessage(txt) ;
}
document.onmouseup = getSelectionAndSendMessage ;
document.onkeyup = getSelectionAndSendMessage ;
"""
let script = WKUserScript.init(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
controller.addUserScript(script)
}
// MARK: Javascript
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
Swift.print("userContentController")
// A new selected text has been received
if let urlString : String = message.body as? String
{
webView.selectedText = urlString
Swift.print("ucc: str -> \(urlString)")
}
if let url = message.frameInfo.request.url {
webView.selectedURL = url
Swift.print("ucc: url -> \(url.absoluteString)")
}
}
// MARK: callbacks
override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
// Pick off javascript items we want to ignore or handle
for title in ["Open Link", "Open Link in New Window", "Download Linked File"] {
if let item = menu.item(withTitle: title) {
if title == "Download Linked File" {
menu.removeItem(item)
}
else
if title == "Open Link"
{
item.representedObject = self.window
item.action = #selector(MyWebView.openLinkInWindow(_:))
item.target = self
}
else
{
item.action = #selector(MyWebView.openLinkNewWindow(_:))
item.target = self
}
}
}
}
在我的动作处理程序中,我只得到框架的 URL,而不是鼠标悬停时突出显示的内容。
我需要的是获取 URL 等,如鼠标悬停在 Web 浏览器的状态栏中所示,以便缓存上下文菜单项的操作。
好吧,我想,在您的 javascript 中,您需要向所有 link 添加一个 onmouseover 事件处理程序,并且此事件处理程序应该将 link 发回到 swift 世界。
根据您的代码,我会在 Javascript 中添加类似以下内容:
function sendLink()
{
window.webkit.messageHandlers.newUrlDetected.postMessage(this.href) ;
}
var allLinks = document.links;
for(var i=0; i< allLinks.length; i++)
{
allLinks[i].onmouseover = sendLink ;
}
当然,在 Swift 世界中,您需要赶上 "newUrlDetected"
controller.add(self, name: "newUrlDetected")
并且在 Swift 消息处理程序中,您需要切换 WKScriptMessage 名称 属性。
- 如果是"newSelectionDetected",则在邮件正文中设置webView.selectedText
- 如果是"newUrlDetected",则设置webView.selectedURL与消息正文
作为
我需要在鼠标悬停时获取 URL,作为上下文菜单出现的前奏,因此我可以将其注入菜单项的 respresentedObject - 或者以其他方式保存。某些项目的内置操作未得到正确处理。
我发现 'Open Link' 的菜单项操作正常,但 'Open Link in New Window' 不行;这些都不是通过内置的上下文菜单项操作来工作的。我想支持一个中间按钮点击成为后面的菜单项。
所以,使用原始 post 作为基础我有这个 - 我还子 class WkWebView,添加
class MyWebView : WKWebView {
var selectedText : String?
var selectedURL : URL?
}
然后在视图控制器中
func viewDidLoad() {
// Watch javascript selection messages
let controller = webView.configuration.userContentController
controller.add(self, name: "newSelectionDetected")
let js = """
function getSelectionAndSendMessage()
{
var txt = document.getSelection().toString() ;
window.webkit.messageHandlers.newSelectionDetected.postMessage(txt) ;
}
document.onmouseup = getSelectionAndSendMessage ;
document.onkeyup = getSelectionAndSendMessage ;
"""
let script = WKUserScript.init(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
controller.addUserScript(script)
}
// MARK: Javascript
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
Swift.print("userContentController")
// A new selected text has been received
if let urlString : String = message.body as? String
{
webView.selectedText = urlString
Swift.print("ucc: str -> \(urlString)")
}
if let url = message.frameInfo.request.url {
webView.selectedURL = url
Swift.print("ucc: url -> \(url.absoluteString)")
}
}
// MARK: callbacks
override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
// Pick off javascript items we want to ignore or handle
for title in ["Open Link", "Open Link in New Window", "Download Linked File"] {
if let item = menu.item(withTitle: title) {
if title == "Download Linked File" {
menu.removeItem(item)
}
else
if title == "Open Link"
{
item.representedObject = self.window
item.action = #selector(MyWebView.openLinkInWindow(_:))
item.target = self
}
else
{
item.action = #selector(MyWebView.openLinkNewWindow(_:))
item.target = self
}
}
}
}
在我的动作处理程序中,我只得到框架的 URL,而不是鼠标悬停时突出显示的内容。
我需要的是获取 URL 等,如鼠标悬停在 Web 浏览器的状态栏中所示,以便缓存上下文菜单项的操作。
好吧,我想,在您的 javascript 中,您需要向所有 link 添加一个 onmouseover 事件处理程序,并且此事件处理程序应该将 link 发回到 swift 世界。
根据您的代码,我会在 Javascript 中添加类似以下内容:
function sendLink()
{
window.webkit.messageHandlers.newUrlDetected.postMessage(this.href) ;
}
var allLinks = document.links;
for(var i=0; i< allLinks.length; i++)
{
allLinks[i].onmouseover = sendLink ;
}
当然,在 Swift 世界中,您需要赶上 "newUrlDetected"
controller.add(self, name: "newUrlDetected")
并且在 Swift 消息处理程序中,您需要切换 WKScriptMessage 名称 属性。
- 如果是"newSelectionDetected",则在邮件正文中设置webView.selectedText
- 如果是"newUrlDetected",则设置webView.selectedURL与消息正文