(edited to give a better description of the answer I gave)
I have created a very simple browser in InterfaceBuilder consisting of a nav bar and a webview.
Everything works fine except when I try to tab between input fields is the webview, the focus goes to the nav bar.
I'm assuming I need to do something with the responder chain, but I haven't been able to figure out what.
Any advice?
Thanks,
Kelly
There is probably no one else in the world who cares about this, but I'm going to answer it in case someone needs this at some point.
As I mentioned in the comments, I am using the cappuccino framework and I was actually having 3 different problems.
Let me give you the set up here.
I was creating a cocoa app with a WebView embedded and loading a page with a cappuccino app in it. At first tabbing between fields didn't quite work for any form on any webpage.
As I said in the comments, if you are using IB, you can set the windows 'initialFirstResponder' to be the webview, and at least 'normal' forms work correctly. Cappuccino still did not.
Second was the problem where keyCode and charCode in the dom event was different from WebView in cocoa to Safari. It turns out that there is something called 'keyboard quirks' mode. If you look for _needsKeyboardEventDisambiguationQuirks in the
WebView ObjC class source
you will see that it makes an exception for safari, turning it off. It is supposed to turn it off for older versions of WebKit, but it doesn't. see webkit bug 32694
To solve this, I had to do two different things.
a) override _needsKeyboardEventDisambiguationQuirks so that it returns NO
b) if the WebView is already instantiated when you override that method, you will need to also call [[webviewinstance preferences] _postPreferencesChangesNotification] in order to get it to work.
This then makes your WebView send the DOM Events like Safari.
Finally, cappuccino was looking at the user agent string to determine how to handle some stuff. It was checking for WebKit and for Safari. I cribbed the safari user agent string and set that as a custom user agent string for the WebView.
[mywebviewinstance setCustomUserAgent: #"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"]
Finally, everything worked just like it did in safari.
Hope this helps someone!
Related
I have a Mac app that displays info in a WebView. Quite an old app now and in Objective-C which I am rapidly forgetting.
The WebView contains anchor tags to allow navigation within the pages, both by clicking on links in the page displayed, or by clicking tabs in the UI which send Javascript to the WebView. In High Sierra this no longer works although it displays no error.
It appears that I need to implement isKeyExcludedFromWebScript: but my attempts to do so have failed.
Do I need to sub-class WebView? Putting isKeyExcludedFromWebScript: and isSelectorExcludedFromWebScript: in the View Controller containing the WebView doesn't work - they never get called.
If anyone has any advice or examples, I would be most grateful.
I am afraid that the answer will be to upgrade the app to use WKWebView but I was hoping for a quick work-around until I get time to do that.
Answering my own question here as I have worked out a solution.
The problem was that I was loading an HTML string into the WebView and when I tried to use internal navigation links, it didn't have a base URL to use as a prefix and so the anchor navigation never worked.
It used to work, prior to High Sierra, so there must be something new about how WebViews operate.
The solution was to save the HTML string to a temporary file and have the WebView load that file's URL instead of loading the string directly.
This applies to both WebView and WKWebView.
I'm having difficulty in using a WebView that is being used purely to display a preview of a website - and I want to ignore all/any interactions the user may try to make with it.
I've already tried Cocoa webView - Disable all interaction to no avail; you can still easily spam-click and it will recognise the presses. (at least there's no context menu)
This one seems overkill; Disable a WebKit WebView - there must be an easier way.
In iOS I know exactly how to solve this, but as a Cocoa newcomer I am stumped - does anyone have any suggestions or better ways to achieve this? Or dump a transparent NSView on top and gobble up interactions? (tried this as well by subclassing an NSView, also to no effect)
Whole project is in IB currently, if this makes any difference.
I think you want to implement a WebPolicy Delegate and have it deny navigation events.
I'm making a WebKit-based text editor app for Mac, and I need to find a way to zoom the document in and out.
I've seen this StackOverflow article here, it suggests just scaling the view that Webkit is rendered into. The problem is, since Webkit doesn't know about it, this breaks things like drag & drop and causes Javascript to report the wrong cursor locations. Unfortunately, for some reason, the Cocoa WebKit API only supports scaling text up or down, not the whole page.
Safari and Chrome are both able to do this properly. I've gone as far as to look through the Chromium source code to figure out how it's done, but unfortunately it's using a completely different cross-platform API.
Any advice would be greatly appreciated. I'm not opposed to using private APIs, if I can figure out how to use them in a safe way.
-Keaton
The APIs for doing this aren't currently public, but they've been around for years and aren't likely to change. You can find them in WebKit's WebViewPrivate.h header. You won't find that header on your system, so you'll have to redeclare those methods yourself in a category. Something like:
#interface WebView (Zoom)
- (IBAction)zoomPageIn:(id)sender;
- (IBAction)zoomPageOut:(id)sender;
- (IBAction)resetPageZoom:(id)sender;
#end
Another option is just to set the CSS zoom property on the html element in your editor. You can do that in markup (<html style="zoom: 1.5">) or in JavaScript (document.documentElement.style.zoom = "1.5"). That doesn't require using any private APIs.
In a cocoa / Mac app I am using a WebView to load a series of YouTube videos (5). When it is loading my whole application locks up for 5 seconds or so.
Is there a way I can load it so it doesn't freeze the rest of the application?
Thanks
eg:
[[webView mainFrame] loadHTMLString:html baseURL:[NSURL URLWithString:#"http://youtube.com"]];
Unfortunately, you cannot render a WebView except on the main thread. This is a basic limitation of the class. I would begin investigating why your page takes so long to render. My hunch: Javascript or a plugin.
I usually like to start by using Safari to see if it has the same issues. You can drag an HTML file onto Safari to load it easily. If Safari shows the same problem, then you can use Safari's Develop tools to profile it. (Preferences, Advanced, Show Develop menu in menu bar.)
If Safari doesn't have a problem, that's actually good, because it means your problem is definitely solvable (if Safari can do it, you should be able to achieve the same thing). Here are some things to try out:
Instruments. Try to see what WebView is taking its time on. Focus first on "all samples" for the main thread. This is usually what leads to the app hanging.
Simplification. Try stripping things out of the webview, especially javascript, until you find the piece that's causing the problem.
Implement the WebResourceLoadDelegate methods to see what piece seems to be causing the problem. The information given by this can be misleading, since it has to do with when things are downloaded, not when they are rendered, but it can give a sense of where in the page you're hanging.
As we know , When we load frame from webpage of safari, we will invoke the delegate methods of webkit informal protocol(WebFrameLoadDelegate):
webView:didStartProvisionalLoadForFrame:
webView:didChangeLocationWithinPageForFrame:
and When we click or change the tabs of safari,which delegate methods will be invoked? Thank you very much!
"We" don't know since this is entirely up to Safari what it fancies doing. At a guess, Safari encloses a WebView for each tab in a tabless NSTabView and switches between them. But again, that's just what it chooses to do at the moment, and might change its mind at any time.
As ever to your incessant questions, Safari has no plug-in API. WebKit does, but anything outside of that defined API is unknown, dangerous, and just asking for trouble. Please don't try it.
Well it's very likely that each tab in safari is using it's own webkit control, as they don't reload when you switch between them.
So I'd have to venture a guess and say neither unless you're actually loading a page.