Chocolate !

Moving Ghost4J to GitHub gave me motivation… So, I decided to go a step further with Ghost4J !

And some weeks later: here comes Ghost4J 0.5.0 !

So what’s new ?

Many things ! Here is the full list (release notes):

  • Added antialiasing property on SimpleRenderer.
  • Added extract method on Document to allow extraction of a range of pages to a new document.
  • Added append method on Document to allow appending a document to the current one (may not be working in all cases with PostScript file, when document use different resources).
  • Added explode method on Document to build one new document for each page of the current document.
  • Upgraded xmlgraphics-commons to 1.4.
  • Upgraded jna to 3.3.0.
  • Added PaperSize class to manipulate paper sizes.
  • Added device property to PSConverter, used to determine the Ghostscript device used for conversion. By default ps2write is now used if available in Ghostscript (see https://github.com/zippy1978/ghost4j/issues/1, thanks BXCY).
  • Added SafeAppenderModifier, a modifier (new kind of component) able to append a document (any kind) to another (any kind) in a safe way (compared with the append method on Document class, that may not work when documents resources are different).
  • Added InkAnalyzer, an analyzer in charge of retrieving CMYK ink coverage (in %) of each pages of a document.
  • Added examples in org.ghost4j.example package.

What are the benefits ?

SimpleRender is now rendering nice antialiased images.

PSConverter is now more reliable as it uses Ghostscript ps2write device (when available) to generate PostScript files.

PS and PDF documents can now be mixed / splited thanks to the new extract, append and explode Document methods. SafeAppenderModifier can also be used to do the job (when PS files come from a different spool).

And last but not least : the InkAnalyzer can tell you how much of Cyan Magenta Yellow or Black (CMYK) ink will be used to print each page of a document.

Like that :

// load PS document
PSDocument document = new PSDocument();
document.load(new File("myfile.ps"));

// create analyzer
InkAnalyzer analyzer = new InkAnalyzer();

// analyze
List<AnalysisItem> coverageData = analyzer.analyze(document);

// print result
for (AnalysisItem analysisItem : coverageData) {
System.out.println(analysisItem);
}

Find it interesting ? Then checkout more examples on the Ghost4J website at http://www.ghost4j.org/highlevelapisamples.html.

And don’t forget you can contribute by forking the project on GitHub, here:  https://github.com/zippy1978/ghost4j.

Happy new year to everyone !

To start 2013, I decided to move Ghost4J from sourceforge to GitHub !

image

Why moving ?

When I started Ghost4J, 4 years ago I chose to host it on sourceforge : I already knew the platform and it felt confortable for me: SVN, FTP access for the web site… Classical tools.

At the time I didn’t know GitHub (and not even git - the scm tool) at all, and even when I got to know it, it took me some time to understand the benefits of such a platform.

Then, last month I read a very interesting article (in french : A celui qui a fait Twitter Bootstrap), in few words : how a successful open source project can swallow your life and some things you should never do with open source.

Of course, Ghost4J is not Twitter Bootstrap (and will never be), but here are some lessons this article taught (or reminded) me:

  • The open source project you started can’t (and must not) stay yours forever: if you decide to give it to a community, then the community must own the project at some point. As the founder, your role is to invite and help people to contribute. The sooner you do it, the most successful the project will become.
  • An open source project should not be centralized: of course at the beginning you do everything by yourself, but if someone is interested in helping you: you must accept it and give him the ‘keys’ to your project (access to tools, share the roadmap with him…).

Why GitHub ?

After that I realized that GitHub was the tool that could help me : with sourceforge I had to copy/paste or patch the code contributed by users by myself as GitHub provides the fork / pull request mechanism, probably the best way to integrate contributions.

GitHub is a social network… For coders, and this is very important : it is easier to get in touch with other developers, and the stars / forks give you a good mesure of involvement of others around your project, as sourceforge only gives you the number of binaries downloaded per day and a user rating mechanism that nobody uses anyway…

GitHub has also better (more recent) tools than sourceforge : git, issue tracking, general site looking (much clearer than sourceforge, even if it got better last year).

So what’s new ?

The web site for the project is now http://www.ghost4j.org (yes: I bought the domain!) and it is managed by the gh-pages feature of GitHub (and can be re-published with a single maven command !).

The site is still generated by the maven site plugin, but I decided to update the documentation and it uses the fluido skin now (form a Bootstrapped look !).

The GitHub page for the project is https://github.com/zippy1978/ghost4j.

I even set up a repository for maven artifact releases and snapshots (check the web site out for instructions).

Hi everyone,

Some weeks ago I decided to have a closer look to Sencha Touch.

The framework is quite complete as it exposes a full MVC in Javascript (where jQuery Mobile handles only rendering out of the box).

With Sencha Touch every piece of code is made of Javascript : models, controllers and even views.

However, as complete as it is, the framework does not provide any way to localize strings. By googling around it is possible to find different solutions, but if you are used to Java .properties for localization, a single file is enough.

Here is a solution I came up with…

A simple I18n utility class

That is the code :

Ext.define('MyApp.util.I18n', {
    singleton : true,

    config : {
    	defaultLanguage : 'en',
        translations : {
        	'en' : {
        		'signIn' : 'Sign in',
        		'name' : 'Name',
        		'hello' : 'Hello {0} !',
                        'enOnly' : 'English only !'
        	'fr' : {
        		'signIn' : 'Identifiez-vous',
                        'name' : 'Nom',
                        'hello' : 'Bonjour {0} !'
        	}
        }
    },

    constructor: function(config) {
        this.initConfig(config);
        this.callParent([config]);
    },
    
    translate: function (key) {
    	
    	// Get browser language
    	var browserLanguage = window.navigator.userLanguage || window.navigator.language;
    	
    	// Is it defined ? if not : use default
    	var language = this.getTranslations()[browserLanguage] === undefined ? this.getDefaultLanguage() : browserLanguage;
    	
    	// Translate
    	var translation = "[" + key + "]";
    	if (this.getTranslations()[language][key] === undefined) {
    		
    		// Key not found in language : tries default one
    		if (this.getTranslations()[this.getDefaultLanguage()][key] !== undefined) {
    			translation = this.getTranslations()[this.getDefaultLanguage()][key];
    		}
    		
    	} else {
    		
    		// Key found
    		translation = this.getTranslations()[language][key];
    	}
    	
    	// If there is more than one argument : format string
    	if (arguments.length > 1) {
    		
    	    var tokenCount = arguments.length - 2;
            for( var token = 0; token <= tokenCount; token++ )
    	    {
    	    	translation = translation.replace( new RegExp( "\\{" + token + "\\}", "gi" ), arguments[ token + 1 ] );
    	    }
    		
    	}
    	
    	return translation;
    	
    }
});

The code above is a simple Ext class. It defines a default language defaultLanguage and a map of translations translations by language code and key / string.

It also provides a translation method that is in charge of retrieving the string matching the provided key. Note that the method also supports arguments in strings.

Usage

In order to use the class, just add it to your project in the app/util with the name I18n.

Then declare it in the requires of your app.js.

Now you should be able to call it from anywhere like this :

MyApp.util.I18n.translate('my_key');

Behaviour

Given the data used in the class above, here is how the translation behaves if browser locale is set to french (fr):

MyApp.util.I18n.translate('signIn'); 
// Gives 'Identifiez-vous'

MyApp.util.I18n.translate('hello', 'Gilles'); 
// Gives 'Bonjour Gilles !'

MyApp.util.I18n.translate('enOnly'); 
// Gives 'English only !' (defaults to en, as the key is not defined for fr)

MyApp.util.I18n.translate('missing'); 
// Gives '[missing]' (the key is never defined, so it is returned into brackets)

Hope this will help !

Here is my first github generated page :)

After a simple try on jQuery plugin authoring with jquery.slicebar I decided to go further during my holidays : I wrote a scrolling plugin.

What is it for ?

The plugin, named jquery.scrollz, adds modern scrolling features on any HTML content and works well with jQuery Mobile (it was my initial purpose).

To enable the plugin on HTML content just do :

jQuery(function($) {
  $('#content').scrollz();
});

Or even simplier with jQuery Mobile : just add data-scrollz=’simple’ tag to the element you want to make scrollable !

You can also invoke it with options as described in the documentation.

The plugin is hosted on github, right here.

Checkout live examples here or here (jQuery Mobile).

The features

Version 1.0.1 (already !) includes the following features :

  • Scroll inertia
  • Scrolling area bottom detection (for infinite scrolling)
  • Pull header (for pull to refresh)
  • Touch events emulation (to make a mouse behave like a finger on desktop browsers)
  • Custom scroll thumb
  • jQuery Mobile auto-enhancement attribute

Grunt is nice !

To write this plugin I decided to go with Grunt, THE command line build tool for Javascript projects (a bit like Ant for Java).

Grunt comes as a Node.js module that can be installed with (requires Node.js):

sudo npm install -g grunt

Then you can use the grunt command from the shell to create a project boilerplate or run the build script.

Grunt comes with a jQuery plugin project template. To generate a boilerplate from it use:

grunt init:jquery

After a few interactions (questions for project configuration) a project with src, libs, tests (with Qunit) and even a README.md for easy github push is created.

By default, the generated build file can : lint (check JS syntax), concat (concatenate source files) min (minify sources) and qunit (run tests).

5 minutes where enough for this project setup ! And Grunt helped me a lot for syntax checking.

On the road map

The first release of the plugin seems to be working OK (I tested it on Chrome, Safari and FireFox). But I already have plans for the future !

So if I have time, I would like to add the bounce support, for an even closer to native app experience.

I also would like to make the scroll thumb more customizable to allow creation of more original thumbs (such as Path little moving clock).

There are also some animations I would like to enhance. And I guess I can optimize the code for speed a bit as well…

Anyway, I hope you will enjoy this plugin.

Diantre, me voilà démasqué ! (Pris avec Instagram)

Last week I spent a long time trying to find a jQuery plugin that I never found : a simple plugin, a bit like a progress bar but with multiple ‘slices’.

As often: as I could not find any, and it was simple enough to do, I decided to write my own…

I decided to name it jquery.slicebar. It is fairly basic but does the job : you just have to provide a model to the plugin (defining slices with there value, label, color and style) to get a nice rendition.

Here is an example:

jQuery(document).ready(function() {
   $('#slicebar2').slicebar({
     max : 100,
     slices : [
         {
             value: 20,
             label : 'Green plain slice',
             color : 'green',
             style : 'plain'
         },
          {
             value: 20,
             label : 'Emtpy',
             style : 'empty'
         },
         {
             value: 40,
             label : 'Orange gradient slice',
             color : 'orange',
             style : 'gradient'
         }
     ]
 });
});


And that is the result:

A live example is available here.

The project is hosted on github and you can check it out here (with documentation).

Good memories at the Montpellier Arena last week (Guns N’Roses)

J’écris très rarement en français dans ce blog, et encore moins pour parler de foot (oui, en fait je n’aime pas trop ça)…

Mais là l’occasion est trop belle : la victoire du Montpellier HSC en L1 hier m’a décidé à faire ce petit tableau, juste pour montrer que l’efficacité d’un club (ses points) par rapport à son budget, ça donne un classement très différent !

Je vous laisse juger :