Skip to content
This repository has been archived by the owner on Sep 25, 2021. It is now read-only.

target="_blank" on href elements has no effect #51

Closed
lgrimes opened this issue Jul 29, 2016 · 10 comments
Closed

target="_blank" on href elements has no effect #51

lgrimes opened this issue Jul 29, 2016 · 10 comments

Comments

@lgrimes
Copy link

lgrimes commented Jul 29, 2016

Description
We have standard href link which is meant to take the user out of the app and to http://facebook.com/shared/sharer.php.

<a class="Share-link m-facebook" href="http://www.facebook.com/sharer/sharer.php?u=ourdomain&amp;title=blah blah" target="_blank"></a>

As we are using the same on our web app, we want the link to take the user to a new window, rather than reloading the current one (hence target="_blank"). This is working completely fine. With this on the tag, the iOS app receives no callback of any kind that a link has been clicked. Nothing from the WKWebView delegate methods is triggered. openExternalURL in the Session is never called.

If however, we remove target="_blank" then the link will open in an external safari window as expected. Our work around has been to pass a flag when the page is loaded from a native webview that will not apply the target tag to the element.

Is this expected functionality?

@huacnlee
Copy link

huacnlee commented Aug 2, 2016

I have same issue.

@zachwaugh
Copy link
Contributor

@lgrimes @huacnlee any links with target=_blank should hit the WKNavigationDelegate where they can be handled. By default, the Turbolinks.Session will set itself as the WKNavigationDelegate and handle any link clicks for the main frame and open them externally. It sounds like either you are implementing sessionDidLoadWebview() which will cause the default navigation delegate not to be set, or the link click isn't occurring in the main frame.

As a test, I'd try setting your own code to be the WKNavigationDelegate for the web view and implement func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> ()) and logging to ensure that delegate method is being hit.

@huacnlee
Copy link

huacnlee commented Aug 3, 2016

My case:

extension TurbolinksSessionLib: SessionDelegate {
    func sessionDidLoadWebView(session: Session) {
        // [breakpoint] looks like there may have no call 
        session.webView.navigationDelegate = self
    }
}

extension TurbolinksSessionLib: WKNavigationDelegate {
    func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> ()) {
        let url = navigationAction.request.URL
        if (url?.host != NSURL(string: ROOT_URL)?.host) {
            let safariViewController = SFSafariViewController(URL: url!)
            topNavigationController?.presentViewController(safariViewController, animated: true, completion: nil)
        } else {
            actionToPath((url?.path)!, withAction: .Advance)
        }
        decisionHandler(.Cancel)
    }
}

I had try to add breakpoint on sessionDidLoadWebView, but in sometimes, it does't hit.

@lgrimes
Copy link
Author

lgrimes commented Aug 3, 2016

In extension of SessionDelegate, i am only overriding didProposeVisitToURL, didFailRequestForVisitable and sessionDidFinishRequest. So I'm not extending sessionDidLoadWebview at all.

Im setting the session in my ViewController like such:

  private final let webViewProcessPool = WKProcessPool()

  lazy final var webViewConfiguration: WKWebViewConfiguration = {
    let contentController = WKUserContentController.init()
    let configuration = WKWebViewConfiguration()
    configuration.userContentController = contentController
    configuration.processPool = self.webViewProcessPool
    return configuration
  }()

  lazy var session: Session = {
    let session = Session(webViewConfiguration: self.webViewConfiguration)
    return session
  }()

  override func viewDidLoad() {
    super.viewDidLoad()
    session.delegate = self
    presentVisitableForSession(session, URL: url, action: .Replace)
  }

Ive also set some breakpoints in decidePolicyForNavigationAction and when clicking anything with target="_blank" this is not being called. However all other links, redirects and page loads work fine. If i remove this, it opens into a new window (external safari) as you would expect.

@jdiepenmaat
Copy link

Same issue here.

@dinomite
Copy link

Any new ideas here? I've got a very simple application with a SessionDelegate overriding the minimum just as @lgrimes described, with the addition of openExternalURL, as I'd like to open external URLs in a SFSafariViewController as described in the README. I too am finding that that overridden method isn't being called and, indeed the decidePolicyForNavigationAction doesn't seem to get called either if I set my own NavigationDelegate.

@dinomite
Copy link

Update! Fixed it thanks to finding this question about how to handle target=_blank. I created a UIDelegate:

extension AppController: WKUIDelegate {
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        if navigationAction.targetFrame == nil {
            webView.load(navigationAction.request)
        }

        return nil
    }
}

And assigned it to the Session's WKWebView:

    let session = Session(webViewConfiguration: self.webViewConfiguration)
    session.delegate = self
    session.webView.uiDelegate = self

@chamnap
Copy link

chamnap commented Oct 19, 2016

I'm having the same issue. I already tried out on the demo application, and it has the same problem. Removing target=blank, it will open in an external safari window.

@chamnap
Copy link

chamnap commented Oct 19, 2016

@zachwaugh, I check out the code. This method, #isMainFrameNavigation, https://github.com/turbolinks/turbolinks-ios/blob/master/Turbolinks/Session.swift#L309 returns false, where navigationAction.targetFrame is nil.

From the apple documentation, https://developer.apple.com/reference/webkit/wknavigationaction/1401918-targetframe, it returns nil because it is new window navigation.

@zachwaugh
Copy link
Contributor

Thanks for digging in @chamnap! That was the issue, our default check was too restrictive. I just pushed a change that opens all links that Turbolinks doesn't handle directly to open in Safari. That should make the WKUIDelegate implementation above unnecessary.

My apologies for not fixing this sooner, I was testing in our app, which had custom handling in place for the WKNavigationDelegate and target=_blank links worked correctly there. The demo app uses the default navigation delegate handler where target blank links did not work.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants