making a “keep For Later” Chrome Extension With brand new net tools
growing an extension for the Chrome browser is an effective way to take a small and helpful idea and distribute it to thousands and thousands of people in the course of the Chrome net retailer. this text walks you through the development means of a Chrome extension with brand new internet tools and libraries.
all of it begins with an idea. Mine was once fashioned while studying a captivating (and long) article about new entrance-end applied sciences. I was focusing on reading the article when all of sudden my spouse known as me to kick out a negative child pigeon that received caught on our balcony. after I ultimately bought back to the article, it was too late — I had to go to work.
To make a long story short, i assumed it would be good to create a Chrome extension that lets you mark your studying progress in articles as a way to proceed reading them later — anyplace.
“Markticle1” is the title I selected for this extension. I’ll share right here the technologies that I used to increase it. After studying this text, you’ll have a ready-to-use “save for Later”-like Chrome extension.
Prior knowledge
We’re going to make use of just a few entrance-finish applied sciences. whereas that you may examine some of them on the fly, knowledge of others is required (marked in daring):
- jQuery
- AngularJS
- Node.js
- Grunt
- Bower
- Yeoman
Scaffolding
Let’s begin with some infrastructure work.
Assuming you’re familiar with npmthree (Node.js’ package manager), we’re going to use the Yeoman generator to create a normal extension for Chrome.
be aware: in the event you nonetheless don’t have Yeoman put in for your desktop, start by following the “Getting startedfour” tutorial.
Open a brand new command line or terminal window, and write the following command:
npm set up -g generator-chrome-extension
this may install Yeoman’s generator for Chrome extensions to your machine.
Create a new folder in your file gadget:
mkdir my-extension
after which run the next command to generate the entire files that you simply’ll wish to begin growing your extension:
yo chrome-extension
After running this command, the generator will ask you which ones options to include in the extension.
In our case, Markticle should do a number of issues:
- Add an icon next to the deal with bar.
- Run on each and every web page that the consumer opens.
- Run some code within the heritage to connect the current page to the extension to be able to retailer data.
For the first function, we’ll select “browser” as a UI motion. To permit the extension to run on every net page, we’ll take a look at the “content scripts” box. finally, to allow historical past strategies to run, we’ll use a heritage.js
file.
note: another way to create a Chrome extension is to make use of the net generator Extensionizr5. Extensionizr is a useful gizmo that helps you create basic Chrome extensions. It has multiple configuration choices, all of which may also be enabled with checkboxes. finally, you’ll get a zipper file that includes all of the recordsdata you’ll need to start working on the extension. The downside is that you’ll need to configure Grunt and Bower manually.
Folder Tree
Let’s look at the generated information and folders we’ve bought now.
app
take a look at
bower.json
bundle.json
Gruntfile.js
Gruntfile.js
is where we’ll configure Grunt tasks for serving, constructing, testing and packaging our extension.
The package deal.json
and bower.json
recordsdata are Node.js and Bower JSON information that define our extension’s dependencies on third-birthday celebration plugins and libraries.
The test
folder will include the entire unit and end-to-finish exams for the extension. ultimately, the app
folder is essentially the most attention-grabbing as a result of it’s where the core of our extension will dwell.
After reordering one of the vital folders and files, here’s what our app
folder will appear to be:
icons
icon-sixteen.png
icon-19.png
icon-38.png
icon-128.png
photography
views
scripts
inject.js
heritage.js
types
primary.css
_locales
en
messages.json
index.html
manifest.json
an important file right here is appear.json
. it is actually the heart of the extension, and it specifies a number of things, together with the next:
- the positioning of each file utilized by the extension,
- which icon to present because the “motion” button,
- the permissions that your extension needs,
- the name of the extension.
here’s an example of what the occur.json
file must look like:
"identify": "Markticle", "version": "1.0.zero", "manifest_version": 2, "icons": "sixteen": "icons/icon-16.png", "38": "icons/icon-38.png", "128": "icons/icon-128.png" , "default_locale": "en", "heritage": "scripts": [ "scripts/helpers/storage.helper.js", "scripts/background.js" ] , "browser_action": "default_icon": "icons/icon-19.png", "default_popup": "index.html"
First Flight
we now have a normal extension that does nothing. nonetheless, just to verify everything is in place and dealing properly, let’s test the extension in runtime.
Open Chrome and write this within the tackle bar:
chrome://extensions
This web page displays details about all the extensions at the moment installed to your browser.
within the high-proper nook, you’ll see an approach to permit “Developer mode.” click on it.
Now, click the “Load unpacked extension” button, browse to the site of the extension you created, make a choice the app
folder, and click on “make a choice.”
You will have to now see the extension’s icon subsequent to the deal with bar.
installing Dependencies
prior to running the app, we want to install some Node.js plugin dependencies. We’ll achieve this via running the next command:
npm install
the very last thing we wish to do ahead of diving into the code is about up the dependencies of the 0.33-birthday celebration libraries we’re going to use. We do that in the bower.json
file:
"identify": "Markticle", "version": "1.zero.0", "dependencies": "angular": "1.2.6", "jquery": "2.zero.three", "normalize.scss": "3.0.zero" , "devDependencies":
I chose three libraries for this project: AngularJS, jQuery and Normalize.css. to install these, run this command:
bower set up
building
Now that we’re prepared to start out construction, let’s split our work into two elements.
the first phase will be the popup window that opens when the person clicks the extension’s icon. Markticle’s popup will present the record of bookmarks (i.e. internet sites) that the person has saved.
The 2nd section connects the user’s movements to the extension itself. each and every time the person takes a specific motion on a web page, the extension must shop the URL and title of the current tab (so that we all know what to show in the popup).
the first phase is lovely easy. We’ll use basic AngularJS code to enhance it.
Let’s start by means of adding the next file structure to the app/scripts
folder.
scripts
controllers
major.controller.js
directives
primary.directive.js
helpers
storage.helper.js
services
storage.provider.js
app.js
inject.js
heritage.js
in the app.js
file, we’ll add the following code, that allows you to outline our app’s major module:
angular.module('markticle', []);
Now, let’s add some normal code to the index.html
file:
<!DOCTYPE HTML> <html> <head> <link href="types/major.css" rel="stylesheet"> </head> <physique ng-app="markticle"> <div id="main_wrapper">pattern</div> <script src="bower_components/jquery/jquery.min.js"> <script src="bower_components/angular/angular.min.js"> <script src="scripts/app.js"> <script src="scripts/controllers/main.controller.js"> <script src="scripts/directives/primary.directive.js"> </body> </html>
What we’ve performed here is very easy:
- outline a worldwide AngularJS module named
markticle
, - add a single div component with sample textual content,
- embody the checklist of script recordsdata that we’re going to make use of.
Now, let’s extend the div part that we created.
<div identification="main_wrapper" ng-controller="MainController"> <header> <h1>My Marks</h1> </header> <part identification="my_marks"></part> </div>
again, nothing special right here — we’ve simply arrange an AngularJS controller named MainController
and added some header
and section
tags for the upcoming content.
in the app/scripts/controllers/major.controller.js
file, let’s create a brand new AngularJS controller:
angular.module('markticle').controller('MainController', perform($ scope) $ scope.marks = []; );
This controller at the moment doesn’t do so much apart from outline an array, named marks
, that’s attached to the controller’s scope. This array will embody the user’s saved items.
just for fun, let’s add two items to this array:
$ scope.marks = [ title: 'Smashing magazine', url: 'http://www.smashingmagazine.com/' , title: 'Markticle', url: 'https://markticle.com' ];
Now, in the index.html
file, let’s loop through them with the ng-repeat
directive:
<part identification="my_marks"> <ul> <li ng-repeat="mark in marks"> <a goal="_blank" ng-href="mark.url">mark.title </li> </ul> </part>
click on the extension’s icon to open the popup and notice the outcome!
After including some normal CSS to the primary.css
file, here’s what we’ve come up with:
Now for the second part.
in the 2d phase, we’ll join user interactions to our extension.
Let’s start by means of adding a brand new property to our happen.js
file:
… "background": …, "content_scripts": [ "matches": ["http://*/*", "https://*/*"], "js": ["bower_components/jquery/jquery.min.js", "scripts/inject.js"] ], …
right here, we’ve added a property named content_scripts
, which has its personal two homes:
suits
this is an array that defines wherein web pages to inject the script — in our case, all internet sites.js
that is an array of scripts as a way to be injected into each and every internet page with the aid of the extension.
Let’s open the inject.js
script and add some normal code to it:
$ (document).ready(perform() var createMarkticleButton = operate() var styles = 'place: fixed; z-index: 9999; bottom: 20px; left: 20px;'; $ ('body').append(''); ; $ (document).on('click on', '#markticle_button', perform() var title = record.title; var url = window.vicinity.href; console.log(title + ': ' + url); ); createMarkticleButton(); );
This script does two issues once the web page is prepared. First, it adds a general button using the createMarkticleButton()
method. Then, it provides an event listener that writes the URL and title of the present page to Chrome’s console each time the consumer clicks the button.
to test this, go to chrome://extensions
, find your extension, and click the “Reload” button. Then, open any website, click the Markticle button, and look at the console in Chrome Developer tools.
Storing information
To retailer information within the extension (without needing to use a server-facet answer), we now have a couple of options. My favorite is HTML5 localStorage8.
Let’s return to our scripts
folder and create a localStorage service. First, edit app/scripts/helpers/storage.helper.js
:
var markticleStorageService = perform() var lsName = 'marks'; var knowledge = localStorage.getItem(lsName) ? JSON.parse(localStorage.getItem(lsName)) : []; return get: operate() return data; , add: operate(merchandise) this.take away(item.url); data.push(merchandise); this.retailer(); , cast off: function(url) var idx = null; for(var i = 0; i < information.size; i++) if(information[i].url === url) idx = i; destroy; if(idx !== null) knowledge.splice(idx, 1); this.retailer(); , save: perform() localStorage.setItem(lsName, JSON.stringify(knowledge)); ; ;
With this, we’re first keeping a information
array with the current knowledge that we’re pulling from localStorage. Then, we’re revealing a couple of the right way to manipulate the info, reminiscent of get()
, add()
and dispose of()
.
After growing this classification, let’s also add it as an AngularJS service in app/scripts/services/storage.service.js
:
angular.module('markticle').carrier('StorageService', markticleStorageService);
word: Don’t omit to consult with both scripts in index.html
.
the reason we’ve split it into two scripts is because we’re going to reuse the markticleStorageService
classification in history.js
, the place we won’t get admission to AngularJS.
Returning to our MainController
, let’s be certain that we’re injecting the storage provider within the app:
angular.module('markticle').controller('MainController', operate($ scope, StorageService) $ scope.marks = […]; );
finally, let’s join the StorageService
data to our app and introduce one way so as to be used in the UI.
angular.module('markticle').controller('MainController', function($ scope, StorageService) $ scope.marks = StorageService.get(); $ scope.removeMark = function(url) StorageService.remove(url); $ scope.marks = StorageService.get(); if(!$ scope.$ $ section) $ scope.$ practice(); ; );
again to the index.html
file. Let’s add an approach to take away objects through connecting the view to the controller’s take away()
manner:
<li ng-repeat="mark in marks"> <a ng-href="mark.url">mark.title</a> <span type="eliminate" ng-click="removeMark(mark.url)">cast off</span> </li>
So, each and every time the user clicks the “do away with” button, it will call the remove()
way from the controller, with the web page’s URL as a parameter. Then, the controller will go to StorageService
and dispose of the article from the info array and store the brand new knowledge array to the localStrorage property.
background course of
Our extension now knows how one can get and cast off knowledge from the localStorage service. It’s time to allow the person so as to add and store items.
Open app/scripts/historical past.js
, and add the next code:
chrome.extension.onMessage.addListener(perform(request, sender, sendResponse) if(request) var storageService = new markticleStorageService(); if(request.action === 'add') storageService.add(request.data); );
right here, we’re including a listener for the onMessage
experience. in the callback operate, we’re growing a new instance for markticleStorageService
and getting a request
object. This object is what we’re going to ship with the chrome.extension.sendMessage
adventure that’s precipitated from the inject.js
script. It comprises two homes:
action
that is the kind of action that we would like the history course of to perform.information
this is the item of the information that we wish to add.
In our case, the type of motion is add
, and the object is a variation of a single item. as an instance:
title: 'Markticle', url: 'https://markticle.com'
Let’s go back to the inject.js
script and fasten it to the background.js
script:
$ (record).on('click on', '#markticle_button', operate() var title = record.title; var url = window.location.href; chrome.extension.sendMessage( action : 'add', information: title: title, url: url ); alert('Marked!'); );
Now, go to any website and click the “Mark me!” button. Open the popup again and notice the brand new item you’ve simply brought. lovely cool, right?
construct
We’ve created a cool “save for Later” Chrome extension of types. before releasing it to the Chrome retailer, let’s speak concerning the build course of for a Chrome extension.
A build process for this kind of app can have a number of objectives (or “duties,” to make use of Grunt’s naming convention):
- take a look at (in case you’re writing unit exams for the extension),
- minify,
- concatenate,
- increment the version number within the manifest file,
- compress into a zipper file.
in the event you’re using Yeoman’s generator, which you can perform all of these tasks mechanically through operating this command:
grunt build
this will likely create a brand new dist
folder, where you are going to in finding the minified and concatenated recordsdata, and any other folder named bundle
, where you’ll discover a ZIP file named with the current version of your extension, able to be deployed.
set up
All that’s left to do is deploy the extension.
Go to your “Developer Dashboard9” in the Chrome internet retailer, and click the “Add new item” button.
Browse to the ZIP file we created and upload it. Fill in the entire required information, and then click the “put up changes” button.
observe: if you wish to replace the extension, as an alternative of creating a brand new merchandise, click on the “Edit” button subsequent to the extension. Then, click on the “add up to date bundle” button and repeat the remaining steps.
Conclusion
As you can see, growing a Chrome extension has never been easier!
in case you use Node.js and Grunt for his or her time-saving features, AngularJS as a development framework and the Chrome internet retailer for distribution, all you want is a good suggestion.
i am hoping you’ve loved studying this text. If it used to be too long to learn in a single sitting, imagine the use of Markticle11.
(il, al)
Footnotes
- 1 https://markticle.com/
- 2 http://www.smashingmagazine.com/wp-content material/uploads/2014/eleven/image01-massive-opt.jpg
- three http://nodejs.org/
- four http://yeoman.io/studying/index.html
- 5 http://extensionizr.com/
- 6 http://www.smashingmagazine.com/wp-content material/uploads/2014/11/image04-massive-opt-500×180.jpg
- 7 http://www.smashingmagazine.com/wp-content material/uploads/2014/eleven/image03-massive-opt.jpg
- 8 http://www.w3schools.com/html/html5_webstorage.asp
- 9 https://chrome.google.com/webstore/developer/dashboard
- 10 http://www.smashingmagazine.com/wp-content/uploads/2014/eleven/image08-huge-choose.jpg
- eleven https://markticle.com/
The publish making a “retailer For Later” Chrome Extension With brand new internet instruments appeared first on Smashing journal.
(204)