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.

2

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:

  1. Add an icon next to the deal with bar.
  2. Run on each and every web page that the consumer opens.
  3. 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:

image06-preview-opt
  • 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.”

image04-preview-opt6

You will have to now see the extension’s icon subsequent to the deal with bar.

image05-preview-opt

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.

image07-preview-opt

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:

image00-preview-opt

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.

image03-preview-opt7

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?

image02-preview-opt

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.

image08-preview-opt10

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. 1 https://markticle.com/
  2. 2 http://www.smashingmagazine.com/wp-content material/uploads/2014/eleven/image01-massive-opt.jpg
  3. three http://nodejs.org/
  4. four http://yeoman.io/studying/index.html
  5. 5 http://extensionizr.com/
  6. 6 http://www.smashingmagazine.com/wp-content material/uploads/2014/11/image04-massive-opt-500×180.jpg
  7. 7 http://www.smashingmagazine.com/wp-content material/uploads/2014/eleven/image03-massive-opt.jpg
  8. 8 http://www.w3schools.com/html/html5_webstorage.asp
  9. 9 https://chrome.google.com/webstore/developer/dashboard
  10. 10 http://www.smashingmagazine.com/wp-content/uploads/2014/eleven/image08-huge-choose.jpg
  11. eleven https://markticle.com/

The publish making a “retailer For Later” Chrome Extension With brand new internet instruments appeared first on Smashing journal.

Smashing magazine

(195)