Inline Attachment

January 3, 2012

Github recently added a new feature in which you can add images inside a ordinary textarea by simply dragging an image inside it, or pasting (only in chrome) an image. While i was working on the markdown editor for Socialog i needed a similar way to add images to a blog post. Therefore i wrote a javascript plugin which does the exact same thing. The result is a plugin which can be used with jQuery, CodeMirror or standalone, so you can easily use it in your project.

During this project i've gained experience with Grunt.js, structuring a jQuery plugin and the HTML 5 File API which i will briefly describe.

While writing out some quick requirements for the plugin i quickly noticed that there had to be a way to build my javascript files into 3 different versions. The standalone version should be compiled inside the jQuery and CodeMirror version without having to copy the code manually, and ideally there should also be a minified production version.

Meet Grunt.js, a JS command line build tool

Grunt.js has proven itself in the jQuery project and became my weapon of choice to combine and minify the required files.

Like any other build tool you need a script which tells it what to do, create a grunt.js in your project directory and setup some tasks. Here are the tasks which i use in my plugin, for simplicity i removed the codemirror version.

grunt.initConfig({

    // Grunt can read json files, here we load the package.json values inside the pkg property so it can be used inside the banner
    pkg: grunt.file.readJSON('package.json'),

    meta: {
        banner: '/*!  - v - ' +
            ' */'
    },

    // Concat action provided by UglifyJS, it automatically runs every child object
    concat: {
        normal: {
            src: ['', 'src/inline-attach.js' ],
            dest: 'dist/inline-attach.js'
        },
        jquery: {
            src: ['', 'src/inline-attach.js', 'src/jquery.inline-attach.js' ],
            dest: 'dist/jquery.inline-attach.js'
        }
    },

    // Minify action provided by UglifyJS, automatically runs every child object
    min: {
        normal: {
            src: [ '', 'dist/inline-attach.js' ],
            dest: 'dist/inline-attach.min.js',
            separator: ';'
        },
        jquery: {
            src: [ '', 'dist/jquery.inline-attach.js' ],
            dest: 'dist/jquery.inline-attach.min.js',
            separator: ';'
        }
    }
});

// Load the plugin that provides the "concat" and "min" tasks
grunt.loadNpmTasks('grunt-contrib-uglify');

// Register the default task
grunt.registerTask('default', ['concat', 'min']);

The config is defined first, it contains data like the pkg variable which loads package.json so it can be used in for example the banner. The meta.banner property contains the string which can be placed above every generated file. It can be called with the `` tag.

Secondly the tasks are loaded using grunt.loadNpmTasks('grunt-contrib-uglify')

And last the default task is defined when grunt is called without arguments, if you are familiar with Apache Ant then the equivalent is:

When everything is done you can run grunt and it will generate everything in the dist/ folder, that saves a lot of time!

jQuery plugin

Writing your code as a jQuery plugin saves you a lot of time when reusing the plugin and makes it easy for other developers to integrate your code into their own projects.

Setting up the structure is really easy and a tutorial can be found at the jQuery plugin tutorial

HTML 5 File API

Handling files with the latest HTML 5 File API provides you with a lot of new options to handle files, like handling files which are dragged from the desktop, listening to a paste event inside a textbox and showing a preview of the just pasted image, or resizing a picture before uploading it to save time and data.

The end result is an easy image attachment system in which you can paste or drop images inside a textbox and include an image without a WYSIWYG editor.

The project can be found at Github

Made with by Rovak