Creating a Google Chrome extension with Options Page using jQuery

Develop Google Chrome Extensions is a very simple task with jQuery, in this post we will learn how to create an extension with a options page. Let’s do it!

The extension that we will build in this post is the Facebook Posts Filter, an extension developed by me.

Creating manifest.json

First, you need to create the manifest.json file, it’s the extension file configuration:

{
  "update_url":"http://clients2.google.com/service/update2/crx",
  "name": "Facebook Posts Filter",
  "description": "Hides posts on facebook according to specified keywords.",
  "version": "0.3",
  "options_page": "options.html",
  "permissions": [
    "storage"
  ],
  "page_action" :
  {
    "default_icon" : "icon-16.png",
    "default_title" : "Hides posts on facebook according to specified keywords"
  },
   "content_scripts" : [
    {
      "matches" : [
        "http://*/*",
        "https://*/*"
      ],
      "js" : ["jquery.min.js","functions.js"],
      "run_at" : "document_end",
      "all_frames" : false
    }
  ],
  "icons" : {
    "48" : "icon-48.png",
    "128" : "icon-128.png"
  },
  "manifest_version": 2
}

The file is self-explained, but, if you have any questions, can visit the documentation of manifest.json.

Note that we call two files, functions.js in line 28 and options.html in line 6.

functions.js: is the file that contains all the extension logic, this will hide posts with the keywords that the user choose.

options.html: is our configuration page, this will also include the options.js file that contains the logic to save and retrieve options.

Creating the extension logic

Now we will create the functions.js file, where it’s located all the extension logic.

function removeAccents(str) {

	accent_map = {
		'á':'a',
		'à':'a',
		'â':'a',
		'å':'a',
		'ä':'a',
		'a':'a',
		'ã':'a',
		'ç':'c',
		'é':'e',
		'è':'e',
		'ê':'e',
		'ë':'e',
		'í':'i',
		'ì':'i',
		'î':'i',
		'ï':'i',
		'ñ':'n',
		'ó':'o',
		'ò':'o',
		'ô':'o',
		'ö':'o',
		'õ':'o',
		'ú':'u',
		'ù':'u',
		'û':'u',
		'ü':'u',};

	var ret = '', s = str.toString();
	if (!s) { return ''; }
	for (var i=0; i<s.length; i++) {
		ret += accent_map[s.charAt(i)] || s.charAt(i);
	}
	return ret;
};

function hidePost(){
	$('.uiUnifiedStory, ._4ikz').each(function(i, item) {

		var texto = removeAccents($(item).text().toLowerCase());

		chrome.storage.local.get("fbfilter_keywords", function(fetchedData) {
		    var keywords = fetchedData.fbfilter_keywords.split(',');

		    $(keywords).each(function(a, palavra){

		    	palavra = removeAccents(palavra.toLowerCase());

		    	indexspace = palavra.length;
		    	if(palavra.indexOf(" ") == indexspace){
		    		palavra = palavra.substring(0, palavra.length - 1);
		    	}else if(palavra.indexOf(" ") == 0){
					palavra = palavra.slice(1);
		    	}

		    	n = texto.indexOf(palavra);

		    	if(palavra != null && palavra != ""){

		    		if(n >-1){
						$(item).remove();
					}

		    	}

		    });

		});

	});

}

hidePost();

setInterval(function(){
	hidePost();
}, 1000);

Between lines 1 and 37 we have a function to remove accents, this will help to find the keyword that the user have configured .

Between lines 39 and 74 we have the function that will remove the posts that contains any keywords.

Note in the line 44: the function chrome.storage.local.git is a asynchronous function with callback that will retrieve the user options.

After line 74 we call the function hidePost() and set an interval, which we call the function every one second.

Creating the Options page

Create a new file called options.html an insert this:

<html>
<head>
	<title>Facebook Filter</title>
	<link rel="stylesheet" type="text/css" href="options.css" />
</head>
<body>
	<div id="content">

		<h1>Facebook Posts Filter</h1>

		<p>Setup the keywords to hide posts on Facebook:</p>

		<div id="keywords">

			<div id="status">Keywords saved!</div>

			<div class="input-item">
				<label>Keywords</label>
				<input type="text" id="keywords-field" /><br />
				<small>Enter the keywords separated by commas</small>
			</div>
			<button id="save">Save</button>

		</div>

	</div>

</body>

<script src="jquery.min.js"></script>
<script src="options.js"></script>

</html>

This HTML page will call the options.js file:

// Saves options to localStorage.
function save_options() {
  var keywords = $('#keywords-field').val();

  chrome.storage.local.set({'fbfilter_keywords': keywords}, function() {

    $('#status').fadeIn(800, function(){
      setTimeout(function() {
      $('#status').fadeOut(400);
    }, 2000);
    });

  });

}

// Restores select box state to saved value from localStorage.
function restore_options() {

  chrome.storage.local.get("fbfilter_keywords", function(fetchedData) {
    console.log(fetchedData);
    var keywords = fetchedData.fbfilter_keywords;

    if (!keywords) {
      return;
    }

   $('#keywords-field').val(keywords);

  });

}

$(document).ready(function(){
  restore_options();
})

document.querySelector('#save').addEventListener('click', save_options);

With this, our extension is done! :)
You can download all code of this post here.

How to install PHP OAuth extension

In this post we will learn how to install the Php OAuth extension on Ubuntu and Mac OSX.

Installing PEAR

PEAR is necessary to install PECL, with PECL we will install OAuth extension.

If are you using Mac OSX, can see how to install PEAR in this tutorial.
If are you using ubuntu, you can install PEAR via apt-get like this:

sudo apt-get install php-pear

You will also need additional PHP modules (like PECL) that can be installed as follows:

sudo apt-get install php5-dev
sudo apt-get install libcurl3-openssl-dev

Installing HTTP and OAuth extensions

With PECL and PEAR once installed we can now install OAuth extension.
Run from your terminal:

sudo pecl install pecl_http
sudo pecl install oauth

After this, open your php.ini and add the follows:

extension=http.so;
extension=oauth.so;

If you got this error installing oauth:

pcre.h: No such file or directory

On Ubuntu, run this and try again:

apt-get install libpcre3-dev

On Mac OS, install Macports, run this and try again:

sudo port install autoconf
sudo port install pcre
sudo cp /opt/local/include/pcre.h /usr/include/

Ready! OAuth PHP Extension is installed.

Generating periodicals for e-ink Kindles (in any programming language)

Create periodicals for kindle may be painful with no documentation available on the internet. Because of this, I decided to write this post.

A simple way to create a periodical for kindle is using the .opf and .ncx files, which are nothing but XMLs with specific formatting. In this post, we will follow this way.

Generating an periodical with .opf and .ncx files

Luckily, there is a Github repository that contains the basic structure of a periodical for kindle using the .opf and .ncx files, which can be founded here.

Watch out for the fact that each article of the periodical is a .html file, so as the navigation file, the contents.html.

What you need to do is generate this files dynamically with you preferred programming language and compiles in a .mobi file with KindleGen in the command line.

Compiling periodical into a .mobi file

First, you need to download KingleGen for you operational system and extract for any location that you prefer. So, once KingleGen was extracted, you need to run this on your command line:

/location/of/kindlegen/kindlegen -c2 content.opf -o ebook.mobi

If no error is found in your files, KindleGen will generate tue ebook.mobi file!

Windows apps on Mac without pain

Installing Macports and Wine

Follow the 1-4 steps on this article to install Macports and Wine

Runnin applications without terminal

First, locate the application you’ve installed on the folder ~/.wine/c_disk/Program Files/
Then, open the AppleScript Editor and put this:

set program to "~/.wine/drive_c/'Program Files'/YOUR_APP.exe"
set wine to "/opt/local/bin/wine"
do shell script wine & " " & program

Obviously replacing YOUR_APP.exe by your app name

Select File > Save as… then select “Application”

Ready! Now you have an application to initialize your windows app without terminal.