How I Made the Domai.nr Chrome Extension

How I Made the Domai.nr Chrome Extension

Tutorial Details
  • Program: Google Chrome
  • Version (if applicable): N/A
  • Difficulty: Intermediate
  • Estimated Completion Time:30 - 45 minutes

Final Product What You'll Be Creating

Writing a nifty Chrome Extension honestly isn’t as difficult as you might think. In this tutorial, I’m going to walk you through how I took an API offered by a great domain-name search service, Domai.nr, and created a Chrome extension for them, simply using their API.


Step 00: What We’ll be Creating Today

What we will be making

In this tutorial, I’ll walk you through how I made the Domai.nr Chrome Extension, using simple HTML, CSS, and jQuery. The typical workflow of this extension can be broken down like so:

  1. Click the icon
  2. Search for a domain
  3. Find one that’s available, and click it
  4. Purchase it using one of the links on the extension

So, it’s not revolutionary or ground-breaking, but when you’re looking for domains fairly frequently (as I’m sure many of you are), it does actually serve a purpose. I wanted to take this opportunity to not only show you how I made this specific extension, but also, more generally, how to make an extension for the Chrome web browser.


Step 01: What’s in a Chrome Extension

There are a few different kinds of chrome extensions, but we’ll be making a browser action extension that shows a popup when clicked. Google has a great overview of what is in each extension. Essentially, what you need to know is that each extension is a directory of files, much like a website. I’ll be discussing more about each of these files later on in the tutorial, but every extension’s directory contains the following files, and this is taken directly from Google:

  • A manifest.json file
  • One or more HTML files (unless the extension is a theme)
  • Optional: One or more Javascript files
  • Optional: Any other files your extension needs, i.e. image files

More on the JSON File

The manifest file provides mostly meta information about the extension. This is where you define things like the name, version, icon, and even permissions.


Step 02: Taking a Look at Domai.nr’s API

Domai.nr's API

Domai.nr’s API can be found here. We’re using the JSON API, which has two methods: Search and Info. It’s called the JSON API because, well, it returns JSON. Both methods respond to a GET request, so we can just concatenate whatever we need to in our request URL, and the rest will fall into place.


Step 03: Digging into the manifest.json File

Our File Structure

As you can see, a Chrome extension really isn’t much more than a basic website. The structure we’ll be using is as follows:

  • domainr.html – this is equivalent to the index.html page in most websites. I prefer to name the main HTML file the same as the extension itself – that’s just a personal preference.
  • icon.png – this 128px by 128px icon is what the user sees in the toolbar. When they click on this icon, it will fire our extension.
  • images/ – this directory holds all of the images we will be using, just like a traditional website. I contacted the creators of Domai.nr and got permission to use all of the images they have on their website, just scaled down. So, I just used Chrome’s Web Inspector and downloaded copies of them, and scaled them accordingly.
  • manifest.json – the manifest.json file, like explained above, is where we define many properties about our extension. It’s required, but is pretty simple to create.
  • script.js – this JavaScript file is where all of our jQuery is held. We will reference it in the domainr.html file, and it will control all of the logic in our extension.
  • style.css – finally, here is our stylesheet file. We’ll obviously also reference this in the domainr.html file.

Our manifest.json File

Time to dig into our code and get started! Our manifest.json file is fairly simple. To see a more detailed summary of all of the fields supported in a manifest file, check this out. You can find all of the code used in our manifest.json file below:

{
  "name"            :  "Domai.nr Search",  // the name of the extension
  "version"         :  "1.0"   			   ,   // version number
  "description"     :  "Give your domains a happy ending.", // description used in the Chrome Webstore
  "browser_action"  :  {
      "default_icon"   :  "icon.png",      // specifies the default icon
      "popup"          :  "domainr.html"   // the page to show when the icon is clicked
  },
  "permissions": [
      "http://domai.nr",   // we give the extension permission to access data on these sites.
      "http://domai.nr/*"  // we suffix it with a *, so /api is accessible
  ]
}

As you can tell by the comments, it is fairly straightforward. The permissions section is extremely important in our case. Otherwise we’ll get an XHR error because the extension can’t access domains you don’t give it permission to. Hence, the importance of the “permissions” section.


Step 04: Getting Started

For our extension, there will basically be three parts:

  • The <form> element, with an <input>, which is where the user types in the query they’re looking for. This is what this step of the tutorial will focus on.
  • A <ul> with several <li> elements inside of it, that gets populated based on their request in part 1.
  • Information regarding the option they select, based on the list items presented to them in part 2.

So, I think it’s fair to say that the extension gains complexity as the user progresses through those parts, or stages described above. With that being said, let’s dig into the HTML I used to structure this.

<!DOCTYPE html>  
<html lang="en">
  <head>
      <meta charset="utf-8">
      <title>Domai.nr Chrome Extension</title>
      <link rel="stylesheet" href="style.css" />
  </head>
  <body id="container">
    <div id="left">
      <form>
      <div class="input-wrapper">
        <input type="text" id="query" />
        <img id="loader" src="images/loading.gif" />
      </div>
        <input type="submit" id="button" value="Search" alt="Loading" />
    </form>
    <!-- rest of the code will follow this -->
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
  <script src="script.js"></script> 
</html>

Alright – that’s it, as far as getting the input from the user is concerned (well, on the HTML side, at least). To be a bit more descriptive, that code is what the user will see when they click on the icon to trigger the extension. It’s just an input box that we’ll style to look like domai.nr’s site has it. You’ll notice that I merely have a <form> element – no method or action has been defined. I didn’t need to use those, as jQuery’s $.getJson method takes care of that for us. This would be a great time to test out the extension, wouldn’t it?

How to Test Local Extensions

To test an extension in development that is on your local machine, simply follow these steps, and then you’ll be up and running with it in no time:

  1. Click Window and select Extensions.
  2. On the right, towards the top of the page, you’ll see a link that toggles the Developer Mode. Click that.
  3. Select Load unpacked extension..., and navigate to the directory the extension is in. Select that directory, and that’s all!

You’ll want to keep the extensions page up in a tab, though, because every time you make a change to the extension and want to test it, you’ll need to click “Reload” in the extensions page for that specific one.

We’ve got it installed locally, but let’s be honest – it’s looking pretty hideous. Let’s pretty it up so the Domai.nr guys would be proud to have an extension like this. You’ll want to download the images I use here, and place them in an /images directory inside of your extension folder, because I reference some of them eventually in the CSS (and in the HTML above, too).

body{overflow-x:hidden;font: normal 14px/18px helvetica, arial, sans-serif; color: #414240;}
  .input-wrapper{overflow: hidden; display: block; position: relative;}
    #query{height: 19px; float:left; display: inline-block; border: 3px solid #A9ADA8; width:220px; padding: 6px 12px 5px 12px; font: normal 14px/18px helvetica, arial, sans-serif; color: #414240; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; border-radius: 18px; }
    #query:focus{outline: none;}
    #loader{width:16px; height:16px; position: absolute; right:18px; top: 10px; visibility: hidden;}
  #button{display: none;}
Step 1 is Completed

Okay – we’ve got the first part all coded up and looking good. In the next section, we’ll focus on taking the user’s query and pulling some data from Domai.nr’s API.


Step 05: Show the User Some Domains!

In this section, we’ll take what the user typed in the <input>, and query it against Domai.nr’s API. Based on those results, we’ll display a list of all the results returned, as well as an icon indicating the status of that domain. So, let’s jump right in!

Before we get into some of the jQuery behind the extension, I think this would be a good time to bring up how to inspect an extension, just like a regular website. Instead of right-clicking somewhere on the page and selecting “Inspect Element”, you’ll simply right-click on the extension, and select “Inspect popup”. That’s all there is to it!

This section is a bit more interactive, so it’s the starting point for our Javascript. I’ll be using jQuery for simplicity’s sake.

$(document).ready(function(){
  $("#query").focus();  // focuses the input when the extension is triggered
  var url     = "http://domai.nr/api/json/search?q=",  // base URL for search request
      infoURL = "http://domai.nr/api/json/info?q=",    // base URL for info request
      query;  // will use this later
  $("form").submit(function(){
    if ($("#query").val() != ""){
      // execute the code below if the user typed something in...
      $("body").width(250);
      $("#loader").css("visibility", "visible");
      $("#results-list li").remove();  // removes any previous results, if there are any...
      $("#search-query").remove();  // more on this in a few lines...
      $(".extension a").remove();
      $("#results-info").hide();  // hides the larger panel if it's shown...
      query = $("#query").val();
      // ... code below ...

In the chunk above, we do a number of things:

  • First, we focus the input box by default
  • Next, we set some variables (as per the Domai.nr API)
  • Then, on the form submit, we do the following:
    • Check to make sure the query is not blank
    • Assuming that passes, we then set the body width, and show an AJAX loader icon
    • We then clear out the previous (if there is one) list of domains, and remove the previous search query from the view
    • Finally, we remove some information that we’ll get to more below

So, it’s a good start. Some of the code above won’t make sense because it’s not in our HTML yet. It will be shortly, just go with it for now.

      // ... code above ...
      $.getJSON(url + query, null, function(json){
        $('<p id="search-query">' + json.query + '</p>').insertBefore("#results");
        $.each(json.results, function(i, result){
          if (result.availability === "available")
            $("#results-list").append('<li class="available"><a href="#"><span class="bg">&nbsp;</span><span class="domain">' + result.domain + '</span><span class="path">' + result.path + '</span></a><img class="loader-sub" src="images/loading-blue.gif" style="visibility:hidden;" /></li>');
          else if (result.availability === "maybe")
            $("#results-list").append('<li class="maybe"><a href="#"><span class="bg">&nbsp;</span><span class="domain">' + result.domain + '</span><span class="path">' + result.path + '</span></a><img class="loader-sub" src="images/loading-blue.gif" style="visibility:hidden;" /></li>');
          else
            $("#results-list").append('<li class="nothing"><a href="#"><span class="bg">&nbsp;</span><span class="domain">' + result.domain + '</span><span class="path">' + result.path + '</span></a><img class="loader-sub" src="images/loading-blue.gif" style="visibility:hidden;" /></li>');
        }); // end $.each
        $("#loader").css('visibility', 'hidden');
      });  // end $.getJSON
      $(this).find('#query').focus();
      return false;
    } else {
      // will describe these later...
      $(".extension a").first().remove();
      $(".registrars ul li").remove();
      $("body").width(250);
    }
  });  // end of .submit
  // ...and more to come in the next section!
});

That section above, while only a few dozen lines, gets quite a bit done:

  • We utilize jQuery’s getJSON method, and use it against the Domai.nr’s API.
  • Within that function, we simply iterate over all of the results it returns.
  • On each result, we check its availability status, and return the correct <li> based on that conditional.
  • Once we’ve gone through all of the results, we hide the AJAX loader.
  • That else statement in there – that’s used when the query is blank. It just resets a few things that may not be blank, or may need to be reset to their default state.

And we’re not quite ready to test it just yet. You’ll see that in the jQuery code above, we’re targeting a list element with an id of results-list that’s not yet in the DOM. So, let’s go ahead and add that just after the <form> element in domainr.html.

<!-- other code above -->
  <div id="results">
    <ul id="results-list">
      <!-- this gets populated -->  
    </ul>
  </div>
</div> <!-- end #left -->

And now it’s time to test. Don’t get your hopes up though, becase it’s going to look pretty ugly…

Search Method now working properly

Assuming all’s well, you should now see a list of all the domains related to a query the user types in (like above). While it is indeed pretty ugly-looking, we have our extension now correctly hooked into the Domai.nr API’s search method, and are retreiving the results correctly. Congrats!

Before we move on to the final section of the tutorial, though, we’ve got some cleaning up to do. We need to display the icon that shows whether the domain is available, maybe available, or taken, and also just clean up the look of the list. Some simple CSS will take care of that with no problem.

ul{display: block; clear:both; margin:0; padding:0;}
  ul li{font-size:15px; color:#333333; display: block; width:100%; line-height:24px; margin-left:10px; width:100%; position:relative;}
  ul li .bg{width:15px; height:15px; display: block; float:left;}
  ul .available .bg{background: url("images/available.png")  0 7px no-repeat; width: 15px; height:19px; display: block; float:left; margin-left:10px;}
  ul .nothing .bg{width: 15px; height:19px; display: block; float:left; margin-left:10px;}
  ul .maybe .bg{background: url("images/maybe.png") 0 7px no-repeat; width: 15px; height:19px; display: block; float: left; margin-left:10px;}
    ul li a{color:#2870B0; text-decoration: none; width:100%; display: block;}
    .loader-sub{position:absolute; right: 38px; top:4px;}
    ul li a:hover{background: url("images/grey.png") no-repeat left top; cursor: pointer;}
    #results-info a:hover{background: none; text-decoration: underline; cursor: pointer;}
    #results-info h3{margin-top: 11px; text-align: center; display: block; width: 340px;}
      #results-info .available{color:#23B000 !important; text-shadow: rgba(100%, 100%, 100%, 1.0) 0 1px 2px; font-size: 24px;}
    ul li a.active{background: url("images/blue.png") no-repeat left top; color:#ffffff;}
Search Method now working properly

Great – now it’s looking all nice and clean – just like the real Domai.nr site! Finally, it’s time to get to the good stuff.


Step 06: They’ve Selected a Domain

This last section changes the extension’s UI the most, but if we break it down into steps, it really isn’t too bad at all.

Okay – let’s think this through. First, when the user clicks on a doamain, we want the popup to get wider, and display information regarding that specific domain. No problem at all. However, we’ll need to add a bit more structure to our code to get it just right.

<div id="results-info">
  <p id="availability"><!-- Text depends on whether the domain is available or not --></p>
  <div class="register-stuff">
    <ul class="sections">
      <li class="registrars">
        <h4>Register at:</h4>
        <ul>
          <!-- populated with all of the available registrars -->
        </ul>
      </li>
      
      
      <li class="tld">
        <h4>
            TLD:<span class="extension"></span>
        </h4>
        <ul>
          <!-- the hrefs here are generated dynamically by the jQuery -->
          <li><a href="#" target="_blank" id="wikipedia">Wikipedia</a></li>
          <li><a href="#" target="_blank" title="Internet Assigned Numbers Authority" id="iana">IANA</a></li>
        </ul>
      </li>
      
      
      <li class="right">
        <h4>Tools:</h4>
        <ul>
          <!-- like above, the links here are generated dynamically -->
          <li class="www"><a href="#" target="_blank" rel="nofollow" data-track-event="Clicked WWW Link">Visit Site (www)</a></li>
          <li class="whois last"><a href="#" target="_blank" rel="nofollow" data-track-event="Clicked WHOIS Link">WHOIS</a></li>
        </ul>
      </li>
    </ul>
  </div>
</div>

<div id="footer">
  <p>Powered by <a href="http://www.domai.nr" target="_blank" alt="Domai.nr">Domai.nr</a>.</p>
</div>

So, the comments should be explanatory enough for that HTML structure, however, we won’t really notice much until we give our extension some more interactivity. Now that we’ve got the structure down, let’s go ahead and do that by adding some jQuery.

$("#results-list a").live('click', function(){  // 'live' is required, because the elements populate the DOM after the user searches for something; not onLoad.
       
   $(this).siblings('.loader-sub').css('visibility', 'visible');  // hide the secondary loader
   $(".extension a").first().remove();  // remove the previous extension (link next to 'TLD').
   $(".registrars ul li").remove();  // hide the previous egistrar's <li&gt; elements.
   $.getJSON(infoURL + $(this).find('.domain').text(), null, function(json){ // ...do some JSON magic again.
     // the $.getJSON line above searches for the currently selected domain
     $("#wikipedia").attr('href', (json.tld['wikipedia_url']));  // adds the correct wikipedia link
     $("#iana").attr('href', (json.tld['iana_url']));  // adds the correct iana link
     $(".whois a").attr('href', (json.whois_url));  // adds the correct whois link
     $(".www a").attr('href', 'http://' + (json.domain));  // adds the correct URL
     $(".extension").append('<a href="http://www.domai.nr/' + (json.domain.split('.')[1]) + '" target="_blank">' + (json.domain.split('.')[1]) + '</a>').show(); // this line adds the correct domain extension to be next to the "TLD" part.

     $('.loader-sub').css('visibility', 'hidden'); // hide the domain-specific loader, because all of the information has been loaded.

    // and the code below goes here...
    

That code above loaded in all of the information we need for the Wikipedia URL, IANA URL, Whois information, site link, and extension information. Below, we’ll look into how I loaded the registrar information, among other things!

   
    // the code above...

    if (json.registrars.length < 1){  // if there are no registrars available
      $(".registrars ul").append('<li>(not available)</li>');
      $("#availability h3").text('Not Available. :(');  // sad face.
    } 
    
    else { // there are registrars available
       for (var i = 0; i <= 5; i++){ // load the first five
           $(".registrars ul").append('<li><a href="' + json.registrars[i].register_url + '" target="_blank">' + json.registrars[i].name + '</a></li>');
       } 

       // show the "More..." link
       $(".registrars ul").append("<li><a href='#' id='load-more'>More...</a></li>");
    }

     // when the user clicks on "more"...
     $("#load-more").click(function(){
       $(this).remove();
       for (var i = 6; i <= json.registrars.length - 1; i++){
         $(".registrars ul").append('<li><a href="' + json.registrars[i].register_url + '" target="_blank">' + json.registrars[i].name + '</a></li>');
       } 
     });
     return false;
   });
   
   
   $('body').width(800);  // make the dropdown bigger.
   $('#results-list a').removeClass('active');  // remove the siblings' possibility of being .active
   $(this).addClass('active');  // give the clicked item .active
   $("#results-info").show();   // show the cool results stuff
   if ($(this).parent().hasClass('available')){  // ...and some conditionals, based on availability
     $("#availability").html("<h3 class='available'>Available!</h3>");
   } else if ($(this).parent().hasClass('maybe')){
     $("#availability").html("<h3 class='possibly'>Possibly Available</h3>");
   } else {
     $("#availability").html("<h3 class='taken'>This domain is <span>taken</span>.</h3>");
   }
   
   // populate the Register at link
   $("#results-info").show();
   return false;  // don't link to anything in the dropdown list
 });
The information is loading now!

Fantastic! The information is now loading, but it’s looking pretty messed up. No worries, just add the following CSS to make it look all pretty and bring an end to today’s exercise.

#left{float:left; width:250px; padding-bottom: 10px;}
  #results-info{float:right; width:510px; display: none;}
    .register-stuff{overflow: hidden;}
    .right{float:right;}
    .extension{float:right; font-size:13px; margin-right: 70px;}
    #load-more{color:#6C9DC9; font-size:12px; line-height: 18px;}
    abbr{float:left;}
    #results-info h4{margin-bottom: 9px; font-size: 16px; font-weight: bold; vertical-align: top; margin-top: 0;}
    #results-info .sections > li{position: relative; float: left; width: 140px; border-left: 1px solid #A9ADA8; padding-left: 9px; margin-right: 10px;}
      #results-info .sections li ul li{margin-left:0; line-height: 20px;}
        #results-info .sections li ul li a{font-size:13px; display: inline;}
  #footer{overflow: hidden; font-size: 11px; color: #666; height:20px; clear:both; margin-right:15px;}
    #footer p{margin:0; padding:0; text-align:right;}
      #footer p a{color:#666;}
      #footer p a:hover{color:#333333;}
And we're all done with the Domai.nr Chrome Extension!

All Done!

And there you have it! Congratulations, you just made a nifty Chrome extension using a great service’s API! I built this out while I was in an airport waiting for a layover; that helps to prove how simple and quick making one of these can be. Honestly, a Chrome extension is no more difficult than a regular web page. If you have any questions at all, please leave them in the comments below!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://alexklimok.com Alex

    Very awesome tutorial! Appreciate the effort! I haven’t come across many of these, but domain related is definitely up my alley :) Keep it up!

  • http://synfyre.net/ n1tr0b

    Very epic mate! I’m going to run down all over again. It seems like I’m an idiot in JSON. lol, Kudos!

  • http://www.developerscode.com/ Developerscode

    Gr8 info…Thanks for sharing….

  • http://www.a2area.it lxn

    Very useful! Thanks for sharing!

  • http://tareq.wedevs.com Tareq

    Really cool tutorial. Seems like I’ve to take a look to build new chrome extensions :D

  • Florian

    Awesome tutorial! I’ve always thought of making a chrome extension, but never found a good tutorial.

  • http://www.maribol.ro/ Maribol

    Nice extension. I like it! :)

  • Jhon

    jQuery for making browser extensions? really? :/ Don’t we use it just for cross-browser compatibility?

    • John
    • http://twitter.com/c_t_montgomery Connor Montgomery
      Author

      Hey Jhon,

      While I understand your comment, and jQuery definitely does not need to be used here, I found it the easiest and simplest way to go about making the extension.

      Thanks,
      Connor

  • Ryan

    Great tutorial, very great tool to learn with and to use with clients. Great work mate keep it up.

  • http://www.islamiceventfinder.com Islamic Event Finder

    Well explained…would have been much cooler if there was a mention on how to get the extension up on Chrome store. I know it won’t be a big deal but felt that’s the only piece missing; but well done!

    • http://twitter.com/c_t_montgomery Connor Montgomery
      Author

      Great suggestion! I definitely could have gone into detail on how to get it up. Thankfully, though, I can save you some searching time: http://code.google.com/chrome/webstore/docs/publish.html

      That’s Google’s resource for developers on how to get extensions and apps up on the web store. It’s pretty self-explanatory and simple to follow along!

  • http://www.taur.in Lawrence Taur

    why hasnt anyone bothered to design them in a way where it is compatible with Rockmelt. its based on Chrome and has extensions too. but a different or limited width for its pop up. hence most extensions look horrible on them.

    • http://twitter.com/c_t_montgomery Connor Montgomery
      Author

      Hey Laurence,

      That’s a very valid point. I wrote this extension for myself a few weeks back, and since Chrome is my primary browser, I decided to make it for that browser in particular.

      I’ll look into refactoring a fork of it for Rockmelt when I have some free time. Or, if you’d like to, the project is up on GitHub, and you can fork it and customize it yourself.

      Thanks for reading! Let me know if I can help at all, and I’m looking forward to testing this thing out on Rockmelt.

  • http://instructmydesign.blogspot.com/ Dinesh Verma

    Never thought developing chrome extensions would be this easy.

  • http://rommelxcastro@gmail.com Rommel Castro A.

    awesome tut!

  • Bruno

    Great tut.

    I would like to see more Chrome/Firefox extensions tutorials in nettuts. There aren´t many good tutorials about this.

  • http://srikanth.me Srikanth AD

    Just curious,

    Under Step 4, two tags after the tag? never seen that before.

  • http://srikanth.me Srikanth AD

    * re-posting the comment as a couple of tags were stripped off

    Under step-4 in the article, there are two ‘script’ tags after the ‘body’ tag? is that valid ? I have never seen that before.

    • http://twitter.com/c_t_montgomery Connor Montgomery
      Author

      Hey Srikanth,

      Thanks for noticing that, and nice catch! It was indeed a typo from the original plugin I developed. However, it is still working fine on Chrome 13.0 (on a Macbook Pro running Lion). I haven’t heard of any issues with it, so I’m assuming that, while it may not be technically ‘valid’, it is fully functional and working correctly.

      Just to be clear to those reading this – the ‘script’ tags are typically above the ending body tag.

      Thanks for reading, Srikanth!

  • saurabh khirwal

    hey guyz don’t know what have i done wrong….but even if i copy the code you gave exactly…i get this :
    http://i.imgur.com/UnXdO.png

    • http://twitter.com/c_t_montgomery Connor Montgomery
      Author

      Hey Saurabh,

      I’m sorry to hear that! I tested it, and it’s working fine for me. Do you mind creating a jsfiddle (jsfiddle.com)? From there, you can email that to me (c at cnnr dot me), and I’d be glad to help you out.

      Thanks for reading! I’m sorry you’re having some difficulty.

  • Vince

    Yeh Thanks for the great tutorial
    I always imagined an extension would be a lot more complicated to create.
    But if it’s this simple all i need now is a good idea.

    Thanks again

  • Rohith

    Never thought that developing an chrome extension be this easy..
    Thanks for great tutorial..

  • John

    Hey Connor can you show us please the code that returns that JSON?

    I am also developing a chrome extension by myself and I didn’t manage to return that JSON properly.

    I got the error : XMLHttpRequest cannot load . Origin is not allowed by Access-Control-Allow-Origin , but than I have added a callback parameter(making it a JSONP request?) to my GETJSON request and it was solved , but I saw that you didn’t use a callback parameter.

    And then I got the errors :
    Resource interpreted as Script but transferred with MIME type text/html.
    engine.php:2Uncaught SyntaxError: Unexpected token <.

    I am frustrated\confused :S can you help me out here?

    • http://www.cnnr.me Connor Montgomery

      Hi John,

      You can find the JSON responses here: http://cl.ly/0z3l051l0r2z1R2L0L2l. As far as the XHR request denied, make sure you’re doing a few things: first, make sure you’re allowing the site’s data to be accessed via the manifest.json’s permissions (http://code.google.com/chrome/extensions/manifest.html#permissions). Secondly, use the developer tools’ Network tab to see what request and response are being given. This is an awesome tool (specifically that tab) for figuring stuff out like that.

      Feel free to email me if you have any questions!

      Best,
      Connor

  • http://alterationsandadditions.com house additions

    It’s really a great and helpful piece of information. I’m satisfied that you shared this useful info with us. Please keep us informed like this. Thanks for sharing.

  • http://edse83.me/connor/domainr.html Daniel

    Hi, I downloaded the code as is from GitHub, I have not been able to make it work, for some reason it does not work when trying a search http://edse83.me/connor/domainr.html. How can I make it work on a server rather than a Chrome Extension.

    Regards

  • http://praveenpuglia.wordpress.com Praveen

    Hey there!. Nice and quick tutorial! Really cleared a lot of things on my side.. I have a query though.. What changes do i need to make to modify DOM elements using an extension?. How do i get access to the current page’s dom via my extension?

  • Mukesh Jat

    Chrome is No more supporting the manifest. You should upgrade it to manifest.json version 2.

    http://mkj.co.in