简体   繁体   English

如何使用Swift将鼠标悬停在URL上的WkWebView中

[英]how to get mouse over URLs into WkWebView with Swift

As a follow-up to How do I get the selected text from a WKWebView from objective-C , I have a related question but using Swift. 作为我如何从Objective-C的WKWebView获取所选文本的后续 ,我有一个相关的问题,但使用Swift。

I need to obtain the URL on mouse over, in prelude to contextual menu appearance, so I can inject it into the menu item's respresentedObject - or otherwise save. 在上下文菜单出现的前奏中,我需要在鼠标悬停时获取URL,以便可以将其注入菜单项的respresentedObject-或进行保存。 The built-in action(s) for some items are not being properly handled. 某些项目的内置操作未正确处理。

I find that menu item action for 'Open Link' works fine but not for 'Open Link in New Window'; 我发现“打开链接”的菜单项操作正常,但不适用于“在新窗口中打开链接”; neither of these work via the built-in contextual menu item actions. 这些都不能通过内置的上下文菜单项操作来工作。 I wanted to support a middle button click to be the latter menu item. 我希望支持单击中键成为后一个菜单项。

So, using the original post as a base I have this - I also sub-class WkWebView, adding 所以,以原始帖子为基础,我有这个-我也将WkWebView子类化,添加

class MyWebView : WKWebView {
    var selectedText : String?
    var selectedURL : URL?
}

then in view controller 然后在视图控制器中

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
            }
        }
    }
}

In my action handler, I'm only getting the frame's URL, not what was highlighted on mouse over. 在我的动作处理程序中,我仅获取框架的URL,而不是鼠标悬停时突出显示的内容。

What I need, is to get the URL etc as shown in a web browser's status bar on mouse overs to be cached for a contextual menu item's action. 我需要的是获取鼠标悬停时Web浏览器状态栏中显示的URL等,以缓存上下文菜单项的操作。

Well, I guess that, in your javascript, you need to add a onmouseover event handler to all your links, and this event handler should send the link back to the swift world. 好吧,我想,在您的JavaScript中,您需要向所有链接添加onmouseover事件处理程序,并且该事件处理程序应将链接发送回快速的世界。

Building upon your code, I would add in the Javascript something like: 在您的代码的基础上,我将在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 ;
}

And of course, in the Swift world, you need to catch the "newUrlDetected" 当然,在Swift世界中,您需要捕获“ newUrlDetected”

controller.add(self, name: "newUrlDetected")

And in the Swift message handler, you need to switch upon the WKScriptMessage name property. 在Swift消息处理程序中,您需要打开WKScriptMessage name属性。

  • If it is "newSelectionDetected", then set webView.selectedText with the message body 如果它是“ newSelectionDetected”,则使用消息正文设置webView.selectedText
  • If it is "newUrlDetected", then set webView.selectedURL with the message body 如果它是“ newUrlDetected”,则使用消息正文设置webView.selectedURL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM