2015-03-02 8 views
11

Ich verwende eine WKWebView in einer Mac OS X-Anwendung. Ich möchte das Kontextmenü außer Kraft setzen, das erscheint, wenn der Benutzer Steuerung + klickt oder rechtsklickt in WKWebView, aber ich kann keinen Weg finden, dies zu erreichen.Wie kann das Kontextmenü in WKWebView auf dem Mac geändert oder außer Kraft gesetzt werden?

Es sollte beachtet werden, dass sich das Kontextmenü abhängig vom Status von WKWebView ändert und welches Element sich unter der Maus befindet, wenn das Kontextmenü aufgerufen wird. Zum Beispiel hat das Kontextmenü nur einen einzelnen "Neu laden" -Eintrag, wenn sich die Maus über einem "leeren" Teil des Inhalts befindet, während ein Rechtsklick auf einen Link die Optionen "Link öffnen", "Link in neuem Fenster öffnen" und bald. Es wäre hilfreich, diese verschiedenen Menüs nach Möglichkeit genau zu steuern.

Die ältere WebUIDelegate bietet die - webView:contextMenuItemsForElement:defaultMenuItems: Methode, mit der Sie das Kontextmenü für WebView Instanzen anpassen können; Ich bin im Wesentlichen auf der Suche nach dem Analog zu dieser Methode für WKWebView, oder eine Möglichkeit, die Funktionalität zu duplizieren.

Antwort

15

Sie können dies tun, indem Sie das Ereignis contextmenu in Ihrem Javascript abfangen, das Ereignis über einen scriptMessageHandler an Ihren OSX-Container zurückmelden und dann ein Menü von OSX öffnen. Sie können den Kontext durch das Feld "body" der Skriptnachricht zurückgeben, um ein entsprechendes Menü anzuzeigen, oder Sie können für jedes ein anderes Handler verwenden.

einrichten Callback-Handler in Objective C:

WKUserContentController *contentController = [[WKUserContentController alloc]init]; 
[contentController addScriptMessageHandler:self name:@"callbackHandler"]; 
config.userContentController = contentController; 
self.mainWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:config]; 

Javascript-Code mit Jquery:

$(nodeId).on("contextmenu", function (evt) { 
    window.webkit.messageHandlers.callbackHandler.postMessage({body: "..."}); 
    evt.preventDefault(); 
}); 

, um es von Objective C reagieren:

-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 
{ 
    if ([message.name isEqualToString:@"callbackHandler"]) { 
     [self popupMenu:message.body]; 
    } 
} 

-(void)popupMenu:(NSString *)context { 
    NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@"Context Menu"]; 
    [theMenu insertItemWithTitle:@"Beep" action:@selector(beep:) keyEquivalent:@"" atIndex:0]; 
    [theMenu insertItemWithTitle:@"Honk" action:@selector(honk:) keyEquivalent:@"" atIndex:1]; 
    [theMenu popUpMenuPositioningItem:theMenu.itemArray[0] atLocation:NSPointFromCGPoint(CGPointMake(0,0)) inView:self.view]; 
} 

-(void)beep:(id)val { 
    NSLog(@"got beep %@", val); 
} 

-(void)honk:(id)val { 
    NSLog(@"got honk %@", val); 
} 
+0

Würde dies für iOS "WKWebView" funktionieren? – adib

+1

Auf iOS "WKWebView" wird der 'contextmenu' -Handler nicht lange gedrückt. – adib

4

Sie Kontextmenü abfangen Elemente der WKWebView-Klasse, indem Sie sie ableiten und die Methode "willOpenMenu" implementieren dies:

class MyWebView: WKWebView { 

    override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) { 
     for menuItem in menu.items { 
      if menuItem.identifier?.rawValue == "WKMenuItemIdentifierDownloadImage" || 
       menuItem.identifier?.rawValue == "WKMenuItemIdentifierDownloadLinkedFile" { 
       menuItem.action = #selector(menuClick(_:)) 
       menuItem.target = self 
      } 
     } 
    } 

    @objc func menuClick(_ sender: AnyObject) { 
     if let menuItem = sender as? NSMenuItem { 
      Swift.print("Menu \(menuItem.title) clicked") 
     } 
    } 
} 

diesen Stattdessen können Sie auch einfach blenden Sie die Menüpunkte mit menuItem.isHidden = true

den gewählten Menüpunkt Erkennen ist eine Sache, aber zu wissen, was der Benutzer tatsächlich in der WKWebView Steuerelement geklickt ist die nächste Herausforderung :)

Es ist wahrscheinlich auch möglich, dem menu.items Array neue Menüelemente hinzuzufügen. Ich habe das selbst nicht getestet.