Ce blog a déménagé et parle maintenant uniquement anglais.

This blog has moved and now only speaks English.

blog.floriancargoet.com

See you there!

/home/florian

le blog de florian cargoet : du linux, du web et du logiciel libre



New adventures

28 April, 2012 (13:36) | Non classé | Florian Cargoet

Ce blog déménage ici et se met à parler anglais !
This blog has a new home and now speaks English!
I will still write about code and I’ll add some electronics and DIY projects in the mix.

If you’re still interested, update your bookmarks and RSS/Atom feeds:

See you there!

[EN] Use PhantomJS to take screenshots of your webapp for you

6 January, 2012 (20:51) | Ext JS, Webdev | Florian Cargoet

Problem

You’ve built a web application and it’s time to write the user documentation. Your app is localized and you ship new features every three months.

In your documentation, you want screenshots of specific parts of your application: the login box, the collapsed Help panel, the main data grid…

You need to take screenshots in 4 languages.

Do you want to take them manually? You could probably define a bunch of rectangular zones and automate the process but the login box is bigger in French than in English since the text is longer. And in six months, you’ll ship a feature which will require a change in the global application layout.

Do you want to define your rectangular zones 4 times? And redefine them (4 times) whenever you resize/move a component?

Solution: component based screenshots

What if you could tell: “Take a screenshot of this div” instead of “Take a screenshot of this app and cut here, here and there”?

Even better: “Take a screenshot of this <insert your favorite UI framework> component”.

With PhantomJS, you can.

Installation

There are builds for Windows and MacOS X available on the download page, there is brew install phantomjs, there is a PPA for Ubuntu, and there are several git repositories.

I chose to compile it on my 32 bits Ubuntu computer:

sudo apt-get install libqt4-dev libqtwebkit-dev qt4-qmake
git clone git://github.com/ariya/phantomjs.git
cd phantomjs
git checkout 1.4.1
qmake-qt4
make

There is no install target in the Makefile so do whatever you usually do in this case (move/symlink the binary to /usr/bin/, add the bin/ directory in your $PATH, use the full path when invoking phantomjs…). The PhantomJS binary is bin/phantomjs.

Usage

phantomjs your_script.js [parameters]

Examples

You can find some examples on the site. Here are some of them:

Load a web page:

?View Code JAVASCRIPT
var page = new WebPage();
 
page.open(url, function (status) {
  // do something
});

Take a screenshot a a page:

?View Code JAVASCRIPT
var page = new WebPage(),
    address, output, size;
 
if (phantom.args.length < 2 || phantom.args.length > 3) {
    console.log('Usage: rasterize.js URL filename');
    phantom.exit();
} else {
    address = phantom.args[0];
    output = phantom.args[1];
    page.viewportSize = { width: 600, height: 600 };
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
        } else {
            window.setTimeout(function () {
                page.render(output);
                phantom.exit();
            }, 200);
        }
    });
}

Evaluate some JS code in the context of the web page:

?View Code JAVASCRIPT
var page = new WebPage();
page.open(url, function (status) {
    var title = page.evaluate(function () {
        return document.title;
    });
    console.log('Page title is ' + title);
});

Combine of these possibilities and you have a nice screenshotting solution!

Component screenshotting

With PhantomJS, this is really simple:

  1. Load your app
  2. Find your divs / Find your components
  3. Get their bounding boxes (top, left, width, height)
  4. Render with clipRect

Example with an ExtJS demo app:

This is a RSS feed viewer and I want screenshots of:

  • The left panel
  • The preview button
  • The whole application, with the left panel collapsed

Here it is:

?View Code JAVASCRIPT
var page    = new WebPage(),
    address = 'http://dev.sencha.com/deploy/ext-4.0.7-gpl/examples/feed-viewer/feed-viewer.html';
 
page.viewportSize = {
    width  : 800,
    height : 600
};
 
// define the components we want to capture
var components = [{
    output : 'feed-viewer-left.png',
    //ExtJS has a nice component query engine
    selector : 'feedpanel'
},{
    output : 'feed-viewer-preview-btn.png',
    selector : 'feeddetail > feedgrid > toolbar > cycle'
},{
    output : 'feed-viewer-collapsed.png',
    //executed before the rendering
    before : function(){
        var panel = Ext.ComponentQuery.query('feedpanel')[0];
        panel.animCollapse = false; // cancel animation, no need to wait before capture
        panel.collapse();
    },
    selector : 'viewport'
}];
 
page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
    } else {
        /*
         * give some time to ExtJS to
         *   - render the application
         *   - load asynchronous data
         */
        window.setTimeout(function () {
            components.forEach(function(component){
                //execute the before function
                component.before && page.evaluate(component.before);
                // get the rectangular area to capture
                /*
                 * page.evaluate() is sandboxed
                 * so that 'component' is not defined.
                 *
                 * It should be possible to pass variables in phantomjs 1.5
                 * but for now, workaround!
                 */
                eval('function workaround(){ window.componentSelector = "' + component.selector + '";}')
                page.evaluate(workaround);
 
                var rect = page.evaluate(function(){
                    // find the component
                    var comp = Ext.ComponentQuery.query(window.componentSelector)[0];
                    // get its bounding box
                    var box = comp.el.getBox();
                    // box is {x, y, width, height}
                    // we want {top, left, width, height}
                    box.top  = box.y;
                    box.left = box.x;
                    return box;
                });
                page.clipRect = rect;
                page.render(component.output);
            });
            // job done, exit
            phantom.exit();
        }, 2000);
    }
});

Result

And here are the screenshots:

feed-viewer-left
feed-viewer-preview-btn
feed-viewer-collapsed

Conclusion

Now, we can automate screenshotting of specific components, even if we don’t know their position or size. Relaunch this script with your application in Spanish and voilà: 3 Spanish screenshots in 5 seconds, even if the button is bigger (or smaller, I don’t speak Spanish)!

Ideas:

  • Components to capture defined in the app itself
  • Browser extension/Bookmarlet to define the components to capture just by clicking on it
  • Use it for unit testing, with image comparison
  • Make a product of this, make profit

I hope you liked it!

[EN] Change Firebug’s own style

5 January, 2012 (15:48) | Notes, Webdev | Florian Cargoet

Problem

I recently switched to XFCE, using the NOX theme. Unfortunately, Firebug’s tabs use the same color as NOX’s background color.

grey text + grey background = invisible tabs!

This is extremely specific, nobody’s going to use it except me but I know I will need it whenever Firebug is updated.

Solution

Change Firebug!

$ mkdir myfirebug
$ cd myfirebug
$ unzip /path/to/firebug@software.joehewitt.com.xpi
$ vim skin/classic/win/firebug.css

Now, edit the color in the panelTab rule.

Zip everything and install it in Firefox.

$ cd myfirebug
$ zip -r custom-firebug@software.joehewitt.com.xpi *

[EN] My entry for the DailyJS “contest”

11 April, 2011 (23:45) | Webdev | Florian Cargoet

Last Friday, DailyJS had 5 digital subscriptions to Hacker Monthly to give away. They set up a small one-liner contest:

If you’d like to read more from Hacker Monthly, we’ve got 5 digital subscriptions to give away — worth $29 each! Just post a comment with your favourite JavaScript one-liner, and I’ll select 5 winners.

Thanks to this piece of code, I am the happy winner of one of the subscriptions:

?View Code JAVASCRIPT
(function ___(__){return function(_){return _!='?' && ___(__+_) || __+'!';};})('d')('a')('i')('l')('y')('j')('s')(' ')('r')('o')('c')('k')('s')('?')

In this article, I’ll explain what it does and how it works.
Lire la suite de "[EN] My entry for the DailyJS “contest”"

Controler deux machines avec un seul clavier/souris et x2x

18 March, 2011 (23:52) | Linux, Notes | Florian Cargoet

Sur le pc qui contrôle :

ssh -XCf hostname  x2x -west -to :0.0

Remplacer -west par la direction la plus appropriée (north, south, east)

Sur la cible : installer x2x

Et voilà, quand votre souris dépasse le « coté ouest » de l’écran, elle continue son chemin sur la 2ème machine ! Le clavier « suit » la souris, évidemment.

Jeux en bookmarklet

17 March, 2011 (00:28) | Non classé | Florian Cargoet

En vrac quelques jeux lançables via des bookmarklets et dont le principe est d’interagir avec les éléments de la page :

http://kathack.com est tout particulièrement intéressant pour son usage des transformations CSS et du z-index pour produire un bel effet 3D.

Clavier TypeMatrix Bépo

20 January, 2011 (00:26) | Linux | Florian Cargoet

Je viens d’acheter un clavier TypeMatrix 2030 avec une skin bépo. Même s’il est trop tôt pour dire si c’est un bon choix, si le bépo c’est mieux, si je tape plus vite, si c’est confortable, si la skin est résistante…, même s’il est trop tôt pour tout ça,  j’ai déjà quelques trucs techniques à partager.

Lire la suite de "Clavier TypeMatrix Bépo"

[EN] Ext.ux.KeySequenceMap

14 January, 2011 (21:37) | Ext JS | Florian Cargoet

Here is a useless extension I wrote for fun : Ext.ux.KeySequenceMap. As its name suggests, it’s based on Ext.KeyMap and it handles sequences of keys instead of unique keys.

Lire la suite de "[EN] Ext.ux.KeySequenceMap"

[FR] Ext.ux.KeySequenceMap

14 January, 2011 (21:36) | Ext JS | Florian Cargoet

Voici une extension inutile (donc indispensable) que j’ai écrite pour m’amuser : Ext.ux.KeySequenceMap. Comme son nom l’indique, cette classe hérite de Ext.KeyMap et gère des séquences de touches plutôt que des touches uniques.

Lire la suite de "[FR] Ext.ux.KeySequenceMap"

Shell : pipe foireux ?

19 June, 2010 (09:57) | Linux, Notes | Florian Cargoet

C’est peut-être quelque chose de très connu mais je viens seulement de comprendre pourquoi mon shell me dit parfois ça :

% svn diff | grep toto
zsh: command not found:  grep

WTF ? Il ne trouve pas grep ?

En fait, c’est très bête comme problème : sur un clavier français, on fait Alt.Gr.+6 pour obtenir le pipe, et si on tape un peu vite, il arrive qu’on tape l’espace qui suit avant d’avoir relâché la touche Alt.Gr. ce qui donne une espace insécable au lieu d’une espace normale (apparemment, c’est le cas pour le layout fr-latin9).

Or, par défaut, le séparateur de mots est l’espace normale donc le shell ne voit pas “grep” mais ” grep” avec une espace insécable. D’où le “command not found”