Chrome Extension: Adding Context menus

This is the final part of the 'Buzz This' Chrome Extension series, in the first post I showed you how to create a basic Chrome Extension. We then expanded on it in the 2nd post showing you how to use XHR and some advanced features of browser_actions.

In this post, I will show you how to quickly integrate Context Menus into Chrome Extensions. Why am I integrating Context Menus? Because they are a powerful hook in to your extension, and I want to be able to let users 'Buzz' about specific things on any page, for instance, if they find an interesting image, they can Buzz just that rather than the entire page. It is pretty powerful.

The code is pretty simple, and should show you how easy it is to get started.

Context menus are pretty powerful and have the ability to be present through-out the life time of a users browsing experience, as such you must declare in your manifest the intention to use Context Menus. It is a pretty simple addition to the 'permissions' array in the manifest.

{
  "name": "Post to Google Buzz",
  "version" : "1.0.0.6",
  "icons" : {
    "16" : "buzz-little.png",
    "128" : "buzz-big.png"
  },
  "background_page" : "background.html",
  "browser_action": {
      "default_icon" : "buzz-little.png",
      "default_title" : "Post to Google Buzz"
    },
  "permissions" : [
    "tabs",
    "contextMenus",
    "http://www.google.com/buzz/api/buzzThis/buzzCounter"
    ]
}

Now that we have specified the requirement to use Context Menus, the user will be alerted to the fact when they install your extension.

Simply asking for permission is not enough, you need to also add some code that will tell the browser when to display the context menu and how to display the context menu. You, the developer, can define where the context menu appears by specifying 'contexts', you have a lot of flexibility, for instance you can say the context menu will only be active on text selections, or video and image elements or links.

Lets start by editing our background.html file. We are going to simply add a method call to chrome.contextMenus.create(), which takes an object that defines our context menu – and that is pretty much it.

chrome.contextMenus.create({
    "title": "Buzz This",
    "contexts": ["page", "selection", "image", "link"],
    "onclick" : clickHandler
  });

Seriously, that is it. The Context menu will be active on the page in general, on any text selection, image (or element that has a 'src' attribute) and all links. There is a simple title 'Buzz This' that is display when anyone of those elements is context clicked. An when the user selects our 'Buzz This' menu item our 'onclick' event handler is called.

So what do we do in 'clickHandler' method? Well we handle the click obviously. In this case, I will detect what was clicked. The reason for detecting what element is the context is that the Buzz API that we are using allows you to pass in a few extra parameters such as the message (the selected text), an image (if the context was an image) or a url (if a link is the context).

var clickHandler = function(e) {
    var url = e.pageUrl;
    var buzzPostUrl = "http://www.google.com/buzz/post?";
<span class="keyword">if</span> (e.selectionText) {
    <span class="comment">// The user selected some text, put this in the message.</span>
    buzzPostUrl += <span class="string"><span class="delimiter">&quot;</span><span class="content">message=</span><span class="delimiter">&quot;</span></span> + encodeURI(e.selectionText) + <span class="string"><span class="delimiter">&quot;</span><span class="content">&amp;</span><span class="delimiter">&quot;</span></span>;
}

<span class="keyword">if</span> (e.mediaType === <span class="string"><span class="delimiter">&quot;</span><span class="content">image</span><span class="delimiter">&quot;</span></span>) {
    buzzPostUrl += <span class="string"><span class="delimiter">&quot;</span><span class="content">imageurl=</span><span class="delimiter">&quot;</span></span> + encodeURI(e.srcUrl) + <span class="string"><span class="delimiter">&quot;</span><span class="content">&amp;</span><span class="delimiter">&quot;</span></span>;
}

<span class="keyword">if</span> (e.linkUrl) {
    <span class="comment">// The user wants to buzz a link.</span>
    url = e.linkUrl;
}

buzzPostUrl += <span class="string"><span class="delimiter">&quot;</span><span class="content">url=</span><span class="delimiter">&quot;</span></span> + encodeURI(url);

<span class="comment">// Open the page up.</span>
chrome.tabs.create(
      {<span class="key"><span class="delimiter">&quot;</span><span class="content">url</span><span class="delimiter">&quot;</span></span> : buzzPostUrl });

};

It's all pretty straight forward, we can get the url of the current page where the context menu was clicked, we can also detect if there is any text has been selected (e.selectionText) and pass that in to the 'message' parameter of the Buzz API, likewise, if the e.mediaType == image, then we can add that to the imageurl parameter. Once we are happy, then we simply call the 'chrome.tabs.create' API that we used in the first post in the tutorial.

And that is it. We now have context menu's happily integrated in to our awesome extension. Unless I can think of any more subtle and useful things to include in the extension, then I think this is the last post…….. hmm, I hear the Omnibar API is released from experimental.

As always, the code is open and on http://github.com/PaulKinlan/BuzzThis have a play and see how easy it is to create Chrome Extensions. And if you do create one, let me know!!

I lead the Chrome Developer Relations team at Google.

We want people to have the best experience possible on the web without having to install a native app or produce content in a walled garden.

Our team tries to make it easier for developers to build on the web by supporting every Chrome release, creating great content to support developers on web.dev, contributing to MDN, helping to improve browser compatibility, and some of the best developer tools like Lighthouse, Workbox, Squoosh to name just a few.

I love to learn about what you are building, and how I can help with Chrome or Web development in general, so if you want to chat with me directly, please feel free to book a consultation.

I'm trialing a newsletter, you can subscribe below (thank you!)