Building your First Chrome Extension : IMDb Lookup

栏目: IT技术 · 发布时间: 4年前

内容简介:Browser extensions are programs which can modify and enhance your browsing experience. From small UI enhancements to automations, extensions can be used and built for a wide array of use cases. In this article we will look at a step by step guide to build

Introduction

Browser extensions are programs which can modify and enhance your browsing experience. From small UI enhancements to automations, extensions can be used and built for a wide array of use cases. In this article we will look at a step by step guide to build a chrome extension.

What are we building? Well our extension will have two jobs, first will be to fetch IMDb details of any movie from the context menu (right click menu), like this :

Building your First Chrome Extension : IMDb Lookup

Second will be demonstrating interaction with web pages and hence fetching IMDb ratings on Rotten Tomatoes home page when we click on extension button and will look like this :

Building your First Chrome Extension : IMDb Lookup

Notice how all movie titles are appended with ({imdbRating}) after we click on extension icon.

The reason for the dual purpose is to demonstrate how to build background extensions (background scripts), extensions which interact with active web page (content scripts) and how to communicate between the two (message passing).

You can find the complete code here .

Setup

Every chrome extension requires a manifest.json file. Think of it as configuration file which will tell chrome how to treat this extension. Lets just create a basic manifest file with :

{
  "name": "IMDb Lookup",
  "description": "Display IMDb rating from context menu and on rotten tomatoes",
  "version": "0.1",
  "manifest_version": 2
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
    "default_icon": "icon.png"
  },
}

name and description are self descriptive and will be same on the chrome web store when you publish your app.

Background scripts are the javascript files which will be running in the background across all pages. They don't have access to current web page and hence can't access DOM for reading or manipulations but they do have access to all chrome APIs . As we need to create a new entry in the context menu of chrome, we will be using a background script.

browser_action is used to put icons in the main Google Chrome toolbar, to the right of the address bar. You will have to add some icon.png file to your working directory.

manifest_version 1 is deprecated by chrome and hence should start with 2.

With our manifest ready, lets create a background.js file to test if things are working :

//background.js
alert("Did it work?")

Running the extension

To run the extension we have built so far, go to chrome://extensions/ and toggle the Developer mode mode on. Click on Load unpacked and browse to the directory containing the extension.

Building your First Chrome Extension : IMDb Lookup

It worked !

Every time you make some changes to the code, just click on reload button on your extension card and chrome will incorporate all the changes.

Building the background extension

Our use case here is that when we highlight any text and right click, the context that appears should have a new menu saying fetch IMDb details for selected text or something and when you click on this menu you should see the IMDb details like rating and year on a popup.

To do this we will be using chrome's context menu API. First we will have to require its permission by adding it in our manifest.json by adding this :

"permissions": ["contextMenus"],

Then we can add the following to our background.js file.

//create a context menu
chrome.contextMenus.create({
	//string to display on menu
	'title': 'Search IMDB for "%s"',
	//contexts here is selection as we want to extract the highlighted text.
	'contexts': ['selection'],
	//the event handler
	'onclick': (context) => {
		const name = context.selectionText;
		alert(`Highlighted texts is : ${name}`)
	}
});

Reload your extension and test it out!

Building your First Chrome Extension : IMDb Lookup

So we are now able to get the highlighted text to our event handler and now are free to make API calls. We are going to use OMDb API for fetching IMDd details. Make the following changes to your background.js :

//create a context menu
chrome.contextMenus.create({
	//string to display on menu
	'title': 'Search IMDB for "%s"',
	//contexts here is selection as we want to extract the highlighted text.
	'contexts': ['selection'],
	//the event handler
	'onclick': async (context) => {
		const name = context.selectionText;
		const response = await fetch(`https://www.omdbapi.com/?t=${name}&apikey=e48e70b4`)
		const {
			Title,
			Year,
			Runtime,
			Genre,
			Actors,
			imdbRating
		} = await response.json()
		const newLine = "\r\n"
		let message = `Title : ${Title}`
		message += newLine
		message += `Year : ${Year}`
		message += newLine
		message += `Runtime : ${Runtime}`
		message += newLine
		message += `Genre : ${Genre}`
		message += newLine
		message += `Actors : ${Actors}`
		message += newLine
		message += `IMDb Rating : ${imdbRating}`
		alert(message)
	}
});

I am putting my own OMDb's API here so that you can follow the tutorial with least friction. However if this breaks the internet and this api key usage reaches the limit, you can claim your free api key from here .

We are making a simple GET call using fetch and then displaying the result. Lets try this out.

Building your First Chrome Extension : IMDb Lookup

Thats it. We have successfully completed the first part of the tutorial.

Interacting with webpages

Lets look at our next use case, i.e. displaying IMBd rating next to movie titles on homepage of Rotten Tomatoes . We wont be able to do this inside our background.js file as it doesn't have access to active webpage and hence its DOM. To do this we will have to write content scripts . Content scripts are files that run in the context of web pages. They will have access to DOM and can read and manipulate it. Add the following to your manifest.json

"content_scripts": [{
    "matches": [
      "https://www.rottentomatoes.com/*"
    ],
    "js": ["content.js"]
  }],

This piece of configuration tells chrome to load content.js file into the webpage whenever the current webpage's URL matches https://www.rottentomatoes.com/* . As a result of this we will have access to webpage's DOM inside our content.js file.

Create a content.js file, add the following lines and lets test our setup.

//content.js
alert("Did it work?")

Lets check if this works.

Building your First Chrome Extension : IMDb Lookup

It did work. The alert will only come when we are at rotten tomato website and not on any other website.

Building the content script

As we need to manipulate DOM, we might as well use jQuery . While not necessary at all, its a good idea to know how to use libraries inside chrome extensions. To do this download a version of jQuery from the jQuery CDN and put it in your extension’s directory. To load it, add it to manifest.json before content.js . Your final manifest.json should look like this:

{
  "name": "IMDb Lookup",
  "description": "Display IMDb rating from context menu and on rotten tomatoes",
  "version": "0.1",
  "manifest_version": 2,
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
    "default_icon": "icon.png"
  },
  "permissions": ["contextMenus"],
  "content_scripts": [{
    "matches": [
      "https://www.rottentomatoes.com/*"
    ],
    "js": ["jquery-2.2.4.min.js", "content.js"]
  }]
}

Now we can do the following in our content.js

const fetchRatings = () => {
    $(".media-lists__td-title").map(async function () {
        const name = this.innerText;
        const response = await fetch(`https://www.omdbapi.com/?t=${name}&apikey=e48e70b4`)
        const data = await response.json()
        this.innerText = `${name} (${data.imdbRating})`
    })
}

fetchRatings();

It some jQuery magic and the same OMDb API call to fetch rating. Lets test this out.

Building your First Chrome Extension : IMDb Lookup

Voila! We are now able to see IMDb rating on Rotten Tomatoes.

But wait, this is not what we wanted. The DOM was supposed to be manipulated only when we click on our extension's icon on the toolbar and NOT by default.

We have a problem now. Clicking on extension's icon is a Chrome event and hence our content.js wont have access to it and hence wont be able to trigger the fetchRatings functions. Our background.js file will have access to the chrome event but it doesn't have access to DOM and hence cant manipulate it.

If we can find some way to trigger content.js from background.js we will be able to achieve the desired behavior.

Message Passing

Message Passing is way of communicating between background scripts and content scripts. It allows us to fire events from background scripts and apply event listeners on content scripts and vice versa.

We first fire an event whenever our extension's icon is clicked on tool bar. We will use chrome's Browser Action API to listen to clicks and then fire our event. Add the following in background.js :

// Called when the user clicks on extension icon
chrome.browserAction.onClicked.addListener(function (tab) {
	chrome.tabs.query({
		active: true,
		currentWindow: true
	}, function (tabs) {
		const activeTab = tabs[0];
		// Send a message to the active tab
		chrome.tabs.sendMessage(activeTab.id, {
			"message": "start_fetching_ratings"
		});
	});
});

We listening to browserAction.onClicked and then firing a payload to active tab where our content.js is running. Lets add an event listener to our content.js

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        if (request.message === "start_fetching_ratings") {
            alert("Message Received!")
        }
    }
);

Reload the extension and test it out.

Building your First Chrome Extension : IMDb Lookup

Message received ! So we have found way to pass on trigger from background to foreground. The final flow becomes chrome event> backgorund.js > content.js . Finally we can incorporate our logic inside the event handler so our final content.js becomes :

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        if (request.message === "start_fetching_ratings") {
            fetchRatings()
        }
    }
);
const fetchRatings = () => {
    $(".media-lists__td-title").map(async function () {
        const name = this.innerText;
        const response = await fetch(`https://www.omdbapi.com/?t=${name}&apikey=e48e70b4`)
        const data = await response.json()
        this.innerText = `${name} (${data.imdbRating})`
    })
}

Lets test our final product.

Building your First Chrome Extension : IMDb Lookup

This is it. We have built the extension we wanted.

Conclusion

Browser extensions are extremely powerful and can change the way we browse internet. Some really successfully companies today started out as an extension. In this article we learnt how to build a pure background extension, how to build a pure foreground extension and how to build hybrid extension by communicating between the two. The complete code can be found here .


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First 设计模式(中文版)

Head First 设计模式(中文版)

弗里曼 / O'Reilly Taiwan公司 / 中国电力出版社 / 2007-9 / 98.00元

《Head First设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、Abstract Factory、Factory Method、Singleton,Command、Adapter、Facade、TemplateMethod、I......一起来看看 《Head First 设计模式(中文版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码