This tutorial is based on Chrome Extension Manifest Version 2.
We'll do this in 3 phases.
Phase 1: Simply integrate our Pinterest Clone into our Chrome Extension.
Phase 2: Upgrade our Pinterest Clone to allow for uploading of images from a URL.
Phase 3: Save all Pin data in local storage and have our board display all Pins in storage.
Phase 1: Integration
Let's go over our file structure.
We'll start with the manifest.json.
{
"name": "Pinterest Chrome Extension",
"description": "Pinterest Chrome Extension",
"version": "0.1.0",
"manifest_version": 2,
"icons": {
"16": "./images/icon-16x16.png",
"32": "./images/icon-32x32.png",
"48": "./images/icon-48x48.png",
"128": "./images/icon-128x128.png"
},
"background": {
"scripts": ["./scripts/background.js"]
},
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"storage",
"unlimitedStorage",
"https://*/*png",
"https://*/*jpg",
"https://*/*jpeg",
"https://*/*gif"
]
}
Things to note:
We need a background script to coordinate our entire extension.
We need tabs permission so we can save website URLs.
We need storage and unlimitedStorage permissions so we can save Pin data (including the image data).
We need domain/host permissions ending in image extensions to allow our extension to download images.
Our popup.html will be a simple page that offers the user the option of adding a new Pin based on the current site they're visiting or opening up their Pin board and added a Pin manually.
To get our actual Pinterest Board integrated into the extension, we simply open a new tab in the user's browser with our Pinterest Board
So when the user clicks on a button in our popup.html, we execute a popup_script.js script that tells our background.js to open our board or add a Pin.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'add_pin') {
new_pin_data = { ...request.payload };
chrome.tabs.create({
active: true,
url: './board.html'
}, tab => recent_tab = tab.id);
} else if (request.message === 'my_board') {
chrome.tabs.create({
active: true,
url: './board.html'
});
}
}
Phase 2: Upgrade
Let's add the ability to save an image from a URL.
When the user clicks on our "Save from site" button, we'll open up an input and take a URL.
We'll use a fetch to get the image and process it the same way as when we choose an image from our local hard-drive.
<!-- board.html -->
<div class="save_from_site">
<span style="pointer-events: none;">Save From Site</span>
<input placeholder="Past a URL to an image" type="text" name="save_from_site_input"
id="save_from_site_input">
<div class="upload_image_url">Upload</div>
<div class="cancel_image_url">Cancel</div>
</div>
// board.js
if (event.target === save_from_site) {
// hide the 'save from site' button
// show the input for taking a url
// show the upload button
// show the cancel button
} else if (event.target === upload_image_url) {
// fetch the image from the url
// parse the image as a blob
// read the image into our Pinterest board
} else if (event.target === cancel_image_url) {
// show the 'save from site' button
// hide the input for taking a url
// hide the upload button
// hide the cancel button
}
Phase 3: Storage
Let's use Chrome's 'localstorage' API.
Saving data to the user's HDD is very simple. We'll save the information as an array of objects.
With two calls using the 'storage' API, we can get previously saved Pins:
chrome.storage.local.get('pins', data => {});
Add a new Pin to the dataset.
const new_pins = data.pins ? [...data.pins, new_pin_data] : [new_pin_data];
and save the updated Pins.
chrome.storage.local.set({ pins: new_pins });
We can then give the Pinterest board the saved Pins when requested.
// board.js
chrome.runtime.sendMessage({
message: 'get_pins'
}, response => {
if (response.message === 'success') {
response.payload.forEach(pin_data => {
create_pin(pin_data);
});
}
});
// background.js
...
} else if (request.message === 'get_pins') {
chrome.storage.local.get('pins', data => {
if (chrome.runtime.lastError) {
sendResponse({ message: 'fail' });
return;
}
sendResponse({
message: 'success',
payload: data.pins ? data.pins : []
});
});
return true;
}
There is much more nuance to this project.
You can get the source files here and you can follow the video tutorial down below.
Comments