5

Is it possible to disable all user interaction with a WebView, apart from scrolling? I want the user to be able to see the page (and possibly select things), but not click links/right click/refresh/focus form fields/trigger UI DOM events (onclick etc).

I see on this question I can disable right click and selection, but that doesn't help with the form elements and navigation sending DOM events.

Community
  • 1
  • 1
Alastair Stuart
  • 4,165
  • 3
  • 36
  • 33
  • When you wish to "disable all user interaction" is it enough for the webview to simply ignore clicking a navigation link and so on? Or do you actually want the cursor not to change when hovering over the link too? If the former is fine, implement the appropriate WebView delegate methods to ignore navigation attempts. – Mike Abdullah Dec 10 '09 at 11:46
  • The problem with modern webpages is that all sorts of things can be altered with clicks, not just link following. I effectively want to disable user interaction with the page except for viewing it. – Alastair Stuart Dec 10 '09 at 17:06

3 Answers3

6

You could subclass NSWindow and set your subclass as the window of the WebView. You can then control which events are sent to the WebView by detecting what sort of control is being affected by the mouse event.

This is pretty brute force but will totally disable any mouse events, including rollovers etc:

@interface WebViewEventKillingWindow : NSWindow 
{
    IBOutlet WebView* myWebView;
}
@end

@implementation WebViewEventKillingWindow
- (void)sendEvent:(NSEvent*)event
{
    NSView* hitView;
    switch([event type])
    {
        case NSScrollWheel:
        case NSLeftMouseDown:
        case NSLeftMouseUp:
        case NSLeftMouseDragged:
        case NSMouseMoved:
        case NSRightMouseDown:
        case NSRightMouseUp:
        case NSRightMouseDragged:
            hitView = [myWebView hitTest:[event locationInWindow]];
            if([hitView isDescendantOf:myWebView] && 
                         !([hitView isKindOfClass:[NSScroller class]] || 
                             [hitView isKindOfClass:[NSScrollView class]]))
            {
                return;
            }
            break;
        default:
            break;
    }
    [super sendEvent:event];
}
@end
Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
  • Yep this is it. I left out NSScrollWheel so the user can still scroll on the page, which introduces some strange behaviour with changing the cursor, but otherwise this does just what I need. Many thanks! – Alastair Stuart Dec 10 '09 at 17:17
  • You could always just add a `[[NSCursor arrowCursor] set];` just before the `return;` statement so that as soon as the mouse moves the cursor is reset. – Rob Keniger Dec 10 '09 at 23:51
  • This works great (best answer I've seen) for everything except keyboard presses. I can still type in the Google search box and search with the return key if the WebView is on that page. I already tried adding cases for NSKeyDown and NSKeyUp. Anyone know how to tweak this? – sudo Oct 18 '13 at 17:33
0

One option (not really the best...) would be to wrap the WebView inside a ScrollView that you create yourself, and then disable all user interaction with the web view entirely. I imagine you would adjust the web view's frame so that the entire page was visible, and then make it the content view of a scroll view.

You may also be able to subclass WebView and intercept clicks to reject certain actions, but I don't have any experience with this, and I imagine it would be difficult to differentiate some actions, such as selection, from others (especially the contextual menu).

Hope that helps - good luck!

Ben Gotow
  • 14,805
  • 3
  • 42
  • 47
0

You could probably do this via javascript (iterate through all links, forms, etc) on the page and deactivate them, using -[UIWebView stringByEvaluatingJavaScriptFromString:].

Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • Unfortunately this isn't viable for me as I am following links, but through the Webkit Obj-C DOM interface not user interaction. – Alastair Stuart Dec 10 '09 at 17:05
  • well, you could set the userInteractionEnabled to false while it's loading, then, once it's loaded, run a script to disable everything and set its userinteraction to on. – Ben Gottlieb Dec 10 '09 at 20:07