Webkit javascript issue

Discussion in 'Mac Programming' started by geoldr, Apr 2, 2011.

  1. macrumors newbie

    Joined:
    Apr 1, 2011
    #1
    Hello guys, so in my program I load the iPhone version of the news.google.com website into a WebView. When I try to click a link, nothing happens. The reason for this is because it is a java script that asks to open a new window. I have no idea how to implement this into my code. I would like the program to open the link in my program, not a new window.
     
  2. geoldr, Apr 3, 2011
    Last edited: Apr 4, 2011

    thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #2
    I have this:

    Code:
    - (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id)listener {
        [ [ NSWorkspace sharedWorkspace ] openURL:[ request URL ] ];
    }
    
    But it doesn't actually work. I have searched for hours now, and still can't make it work. Is there a bug in webkit?
     
  3. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #3
  4. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #4
    Thank you for posting the link, I have read it and implemented the code, but it doesn't work. When the javascript is involved, it just ignores it. Is there any way to make it work with javascript?
     
  5. macrumors 603

    Joined:
    Aug 9, 2009
    #5
    Post some basic debugging information:
    1. Show the exact URL.
    2. Also show the action dictionary.

    Pretend we can't reach into your computer and add NSLog() calls that show this info, then recompile, run, and remotely see the results.


    At a basic level, asking NSWorkspace to openURL is almost certainly the wrong thing. You want YOUR program to handle the URLs, not some other application that handles the URL by default. In short, I don't think you understand what you're asking NSWorkspace to do.
     
  6. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #6
    It works for me.

    Did you implemented a WebUIDelegate? Particularly did you implement webView:createWebViewWithRequest: and, if appropriate, webViewShow:?

    Did you connect the delegate to your WebView's UIDelegate outlet?

    How did you implement webView:createWebViewWithRequest:?

    If you put a NSLog in webView:createWebViewWithRequest: do you see the log message in the debugger console?
     
  7. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #7
    So for connecting the the delegates, in IB I connected them with the control click/drag method. So they are linked.

    Then for the code what I have is:
    Code:
    .h file:
    IBOutlet WebView *web1;
    .m file:
    -(void)awakeFromNib
    {
        [web1 setUIDelegate:self];
        [web1 setPolicyDelegate:self];
        [web1 setCustomUserAgent:@"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7"];
        NSString *sentURL = @"http://news.google.com";
        [[web1 mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:sentURL]]]; 
    }
    
    - (void)web1:(WebView *)sender
    decidePolicyForNavigationAction:(NSDictionary *)actionInformation
    request:(NSURLRequest *)request
    frame:(WebFrame *)frame
    decisionListener:(id <WebPolicyDecisionListener>)listener
    {[listener ignore];
        [[NSWorkspace sharedWorkspace] openURL:[request URL]];
    }
    
     
  8. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #8
    Forget about the policy delegate, you're on the wrong path there.

    You need to implement webView:createWebViewWithRequest:. See the WebUIDelegate informal protocol reference.

    If you want to ignore that the request is for a new window: implement webView:createWebViewWithRequest: to just load the new URL in your WebView's mainFrame, and then return your WebView.

    If you want to open the link in a new window within your program: implement webView:createWebViewWithRequest: to create a new WebView, load the new URL into the new WebView's mainFrame, and then return the new webView. Additionally implement webViewShow: to create a new window that has the passed WebView added to it, and to order the new window on screen.
     
  9. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #9
    I am still having trouble understanding this, do you mind posing some code to help me out some more with this? I really appreciate all the help so far.
     
  10. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #10
    Really? Oh well...... :(

    Code:
    - (void)awakeFromNib
    {
       [web1 setUIDelegate:self];
       [web1 setCustomUserAgent:@"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7"];
       NSString *sentURL = @"http://news.google.com/";
       [[web1 mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:sentURL]]]; 
    }
    
    - (WebView *)webView:(WebView *)aSender createWebViewWithRequest:(NSURLRequest *)aRequest
    {
        NSLog(@"%s", __PRETTY_FUNCTION__);
        [[aSender mainFrame] loadRequest:aRequest];
        return aSender;
    }
    
    The links do work with this code. They open within the same window.
     
  11. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #11
    Thank you, this does work. I have a few questions. Is the reason you are calling it "webView" because we are creating a new WebView? Because my original was called web1, and when the links open, they do not load the mobile version of the websites. So is it possible to preserve my web1 with the custom user-agent?
     
  12. jiminaus, Apr 9, 2011
    Last edited: Apr 9, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #12
    I was calling the WebView object webView both generically and because that's what the name of the property in my window controller is. When I paste the code above for you, I noticed at the last moment that you've called it web1, so I replaced webView with web1 in the code.

    Where exactly in the code do mean by my calling it "webView"?

    EDIT: I just tested the code. The custom user agent is being preserved, as I would have expected, because at no point is a new WebView object created. Some sites display a mobile version, some don't; but the behaviour is identical under iOS 4.

    EDIT 2: Upon further investigation, the mobile version of news.google.com has exactly the same links the regular versions of news.google.com. It doesn't specially provide links to the mobile versions of the news items.

    If a news website is setup to detected a mobile user agent, it will redirect you to the mobile version of the news item. If the news website is not so setup, you'll get the regular version of the new item.

    For example -- I'm in Australia so these are Australian examples -- the Sydney Morning Herald automatically detected the mobile user agent and redirected me to the mobile version of the website. The Australian newspaper's website did not. I need to manually navigate to the mobile version.

    So for websites that don't automatically detect and redirect, you'll need to translate the regular URL to the mobile URL. This translation will be specific to search news website.
     
  13. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #13
    You are right about the user-agent, I just was not looking clearly at it. However, I am still confused on how this works. Because my WebView is called "web1". However if your code, its called "webView" and this works. When I change it to "web1" it does not work. What if my program had multiple WebViews, how can i distinguish the two? I hope you understand what I am asking, and I am very grateful for all the help you have given me so far.
     
  14. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #14
    Are you talking about the code below in blue?
    Code:
    - (WebView *)[color=blue]webView[/color]:(WebView *)aSender createWebViewWithRequest:(NSURLRequest *)aRequest
    
    Would you have expected the below?
    Code:
    - (WebView *)[color=red]web1[/color]:(WebView *)aSender createWebViewWithRequest:(NSURLRequest *)aRequest
    
    Would you have hoped to have the below if you also had a web2?
    Code:
    - (WebView *)[color=red]web2[/color]:(WebView *)aSender createWebViewWithRequest:(NSURLRequest *)aRequest
    
    If so, this is not how Objective-C works. The method signature keywords before the colons form the name of the message which selects the method. When you implement a delegate method, you must use exactly the same name as is documented in the delegate's reference. In this example, the name of the message is webView:createWebViewWithRequest:. If you implement web1:createWebViewWithRequest:, that's a completely different name and won't be called when a WebView send your delegate a webView:createWebViewWithRequest: message.

    If you have multiple WebViews, you have at least 2 choices. Preferably you would implements 2 view controllers each acting as a delegate of 1 WebView object. Each would implement webView:createWebViewWithRequest: as appropriate for the WebView.

    Alternatively, you would need an if structure in the 1 delegate shared by multiple WebView objects that selects the appropriate code based on who sent the delegate the message. Like so:
    Code:
    - (WebView *)webView:(WebView *)aSender createWebViewWithRequest:(NSURLRequest *)aRequest
    {
      if (aSender == web1) {
        /* Directly implement webView:createWebViewWithRequest: for web1 */
        /* or send web1:createWebViewWithRequest: to self                */
        /*     and implement that method                                 */
      }
      else if (aSender == web2) {
        /* Directly implement webView:createWebViewWithRequest: for web2 */
        /* or send web2:createWebViewWithRequest: to self                */
        /*     and implement that method                                 */
      }
      else {
        NSString *reason = 
          [NSString stringWithFormat:@"%@ not implemented for %@", 
                                     NSStringFromSelector(_cmd),
                                     sender];
        NSException *exception = 
          [NSException exceptionWithName:@"NotImplemented"
                                  reason:reason
                                userInfo:nil]; 
        @throw exception;
      }
    }
    
     
  15. thread starter macrumors newbie

    Joined:
    Apr 1, 2011
    #15
    You have no idea how much your explanation has helped me understand. Thank you very much
     

Share This Page