locked
I want to open context menu in webview control

    Question

  • Hi,

    I want to open a context menu in webview when a user right-clicks on any image, previously in 8.0 I was able to achieve that through

    webView.AllowedScriptNotifyUris = allowedUris;

    webView.InvokeScript("eval", new String[] { script });

    webView.ScriptNotify += webView_ImageLongClickScriptNotify;

    but since AllowedScriptNotifyUris is obsolete so cant fire oncontextmenu event for that particular page, is there any way to achieve it in 8.1?

    Thanks & regards

    JZ

    Wednesday, July 17, 2013 8:15 AM

Answers

  • Hi JZ,

    As Sam noted, this is intentional behavior. This restriction is in place to reduce the ability for arbitrary web code from taking control of your apps code.

    Unfortunately there isn't a good way to add your own context menu for arbitrary sites. We've noted this scenario for investigation for future versions of the WebView.

    --Rob

    Thursday, July 25, 2013 4:57 PM

All replies

  • In the package.appxmanifest there is a section for specifying Content URIs.  For 8.1 you can only specify https:// content URIs. 

    How are you loading your content?  Via the Navigate() method, or using Source="http://www.website.com" (which calls Navigate)  Is the content you are trying to load http, or https?



    Wednesday, July 17, 2013 3:43 PM
  • Hi JZ

    Also, if you were able to make a complete, small sample project from VS2012 availble somewhere that shows the behaviour you expected in Windows 8 and that you find behaves differently in Windows 8.1 that would be helpful.

    Thanks

    Doug

    Wednesday, July 17, 2013 4:13 PM
  • Hi,

    Thanks for the replies, 

    @ Doug : I may not able to provide you a sample but i can explain, actually what i did in sdk 8.0 was

    when the page completes loading, I invoked script

                List<Uri> allowedUris = new List<Uri>();
                allowedUris.Add(uri);
                webView.AllowedScriptNotifyUris = allowedUris;

    var imageScript = @"var imgs = document.images;
                                        for(var i=0; i<imgs.length; i++)
                                        {
                                       imgs[i].oncontextmenu = function(e) {window.external.notify('imagelongclick|' + this.src + '|' + e.clientX + '|' + e.clientY); return false;}
                                        }";

    webView.InvokeScript("eval", new String[] { imageScript  });
    webView.ScriptNotify += webView_ImageLongClickScriptNotify;

    Then in webView_ImageLongClickScriptNotify, i show the popup-menu at particular point. But now in sdk 8.1 i am unable to raise script-notify for this script due to the obsoletion of webView.AllowedScriptNotifyUris = allowedUris;

    @ Kevin : I want this behavior on every site that contains images , I just want to show context menu on any image on any page in webview

    Thanks & regards

    JZ

    Thursday, July 18, 2013 6:21 AM
  • Hi JZ

    If you were to take, say, the Windows 8.0 sample from the SDK:

    http://code.msdn.microsoft.com/windowsapps/XAML-WebView-control-sample-57f0317e

    in C# and modify it into a functioning, buildable sample showing what worked for you in 8.0 (and which does not work when run in 8.1) you are more like to get a faster response from someone.

    Thanks and regards

    Doug

    Friday, July 19, 2013 11:52 AM
  • Hey Doug, the security model for script notify has changed. To be able to call notify from in the webview, the page needs to have been delivered from one of:

    a) A https:// site, and the site needs to be listed in the app manifest

    b) NavigateToString, ms-appx-web:// or NavigateToStreamUri

    In your case I suspect its a site, so you need to make sure its callable via https, and list it in the app manifest.

    Sam

    Friday, July 19, 2013 6:24 PM
  • Hi,

    Thanks for your replies, like I said earlier, I wanted a general solution, Its not feasible for me to list sites in manifest, and after all how many site should I list.

    @ Doug, just replace the load-complete method of web-view sample's scenario 1 with this

    void WebView1_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
            {
                WebView1.Visibility = Windows.UI.Xaml.Visibility.Visible;
                BlockingRect.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                ProgressRing1.IsActive = false;
    
                List<Uri> allowedUris = new List<Uri>();
                allowedUris.Add(e.Uri);
                WebView1.AllowedScriptNotifyUris = allowedUris;
    
                var imageScript = @"var imgs = document.images;
                                        for(var i=0; i<imgs.length; i++)
                                        {
    	                                    imgs[i].oncontextmenu = function(e) {window.external.notify('imagelongclick|' + this.src + '|' + e.clientX + '|' + e.clientY); return false;}
                                        }";
                WebView1.InvokeScript("eval", new string[] { imageScript });
                WebView1.ScriptNotify += webView_ImageLongClickScriptNotify;
    
                // Tell the user that the page has loaded
                rootPage.NotifyUser("Page loaded", NotifyType.StatusMessage);
            }
    
            private async void webView_ImageLongClickScriptNotify(object sender, NotifyEventArgs e)
            {
                try
                {
                    if (e.Value.Contains("imagelongclick"))
                    {
                        string[] vals = e.Value.Split('|');
    
                        var menu = new PopupMenu();
    
                        menu.Commands.Add(new UICommand("Save", (command) =>
                        {
                            
                        }));
    
                        menu.Commands.Add(new UICommand("Copy image link", (command) =>
                        {
                            
                        }));
    
    
                        int x = int.Parse(vals[2]) + 100;
                        int y = int.Parse(vals[3]) + 400;
                        var rect = new Rect(x, y, 5, 5);
                        var chosenCommand = await menu.ShowForSelectionAsync(rect);
                    }
                }
                catch (Exception ex)
                {
                }
            }

    Thanks & regards

    JZ

    

    Monday, July 22, 2013 3:32 AM
  • Hi JZ,

    As Sam noted, this is intentional behavior. This restriction is in place to reduce the ability for arbitrary web code from taking control of your apps code.

    Unfortunately there isn't a good way to add your own context menu for arbitrary sites. We've noted this scenario for investigation for future versions of the WebView.

    --Rob

    Thursday, July 25, 2013 4:57 PM