Modify an existing page with a Chrome extension built using Angular and Yeoman Part 2
Code from screencast and tutorial is available on Github.
The screencast has more detail and explanation than this tutorial.
More page altering experiences
I stopped off on Part 1 just when things were getting good. I leveraged Yeoman and Angular to quickly get a new Chrome extension project up and running. Follow along and we will finish getting this 'Search on Bing' button injected on the Google Search page.
- Go back to the browser and in Chrome web inspector find where to put the 'Search on Bing' button.
- Modify
app/scripts/contentscript.js
to place the button in the correct spot. - Go back to the browser and in Chrome web inspector and copy the HTML of the "I'm Feeling Lucky" button.
- Paste the HTML to
app/scripts/contentscript.js
and modify as in the below highlighted code. - Go back to
chrome://extensions
and reload. - Reload Google search page.
- Make a new directory under the app directory called 'templates' and file called 'bing.html'.
- Use the code below within bing.html
- Modify
app/scripts/contentscript.js
with the below highlighted code. - Modify
app/manifest.json
to allow use of the bing.html template - Next, let's hook up the data binding that was introduced in the bing.html template.
- Go back to the browser and in Chrome web inspector find the id of the search input field.
- Modify
app/scripts/contentscript.js
with the below highlighted code. - Reload the extension and the Google search page to see the changes.
- Go back to the browser and in Chrome web inspector find the HTML responsible for the auto suggest menu.
- Modify
app/scripts/contentscript.js
to remove auto suggest. - Reload the extension and the Google search page to see the changes.
- Modify
app/templates/bing.html
and the change the data-bound input element to hidden. - Reload the extension and the Google search page to see the changes.
// omitted app.controller('MainController', function ($scope) {}); var myDirective = document.createElement('div'); myDirective.setAttribute('my-directive', ''); viewport.appendChild(myDirective); document.querySelector('.jsb center').appendChild(myDirective); app.directive('myDirective', function() { return { // omitted
// omitted
app.directive('myDirective', function() {
return {
restrict: 'EA',
replace: true,
template: '<input value="Search on Bing" name="btnB" type="submit">'
};
We are going to need to add quite a bit of HTML to this directive so instead of doing it inline let's use a template.
<form action="http://bing.com/search" method="GET"> <input type="submit" name="btnB" id="" value="Search on Bing" /> <input type="text" name="q" id="q" value="{{ search }}" /> </form>
Here a form tag has been added that submits a GET request to the
bing.com/search
url. Also, another input field was added to data bind to the Google search input field. More on that in a bit.
Angular loads templates via AJAX requests so we need to do some fancy footwork to get this to work within a Chrome extension. For more explanation, check out the screencast right around the 4th minute.
// ..omitted app.directive('myDirective', [ '$sce', function($sce) { return { restrict: 'EA', replace: true, templateUrl: $sce.trustAsResourceUrl(chrome.extension.getURL('templates/bing.html')) }; }]); // ..omitted
// omitted ], "html": [ "templates/bing.html" ], "run_at": "document_end", "all_frames": false } ], "content_security_policy": "script-src 'self'; object-src 'self'", "web_accessible_resources": [ "templates/bing.html", "bower_components/angular/*" ]
// ..omitted
app.controller('MainController', function ($scope) {});
var input = document.getElementById('lst-ib');
input.setAttribute('ng-model', 'search');
var myDirective = document.createElement('div');
// ..omitted
To be better able to see what is going on, let's get rid of Google auto suggest. Removing auto suggest is not necessary as in its final state the input[id=q] from the bing.html template will be hidden, but this allows for a quick demonstration of
Angular.element
.
// omitted
app.controller('MainController', function ($scope) {});
var autoCompleteWin = document.querySelector('.gssb_e');
angular.element(autoCompleteWin).remove();
var input = document.getElementById('lst-ib');
// omitted
Angular ships with a lightweight version of jQuery called jqLite. Angular.element is an alias for jqLite or jQuery (if jQuery is installed). Using jqLite's
.remove()
saves me 2 steps over using vanilla Javascript in which I would have had to: (1) Go up the dom to find a parent element; (2) execute a .removeChild()
from said parent element.
Note: Google Instant predictions have been turned off in this browser.
<form action="http://bing.com/search" method="GET">
<input type="submit" name="btnB" id="" value="Search on Bing" />
<input type="hidden" name="q" id="q" value="{{ search }}" />
</form>
Conclusion
In this 2-part series we modified the Google home page using a Chrome extension built with Angular and Yeoman. It is my hope that this will help jumpstart your next Chrome extension project. Again, there is more explanation and commentary on the screencast, while the code is on Github.
- Pushed on 02/20/2014 by Christian