Archive for the ‘Plugins’ Category

TinyColor On npm

Wednesday, September 12th, 2012

I have published my TinyColor package to the npm repository – https://npmjs.org/package/tinycolor2. Unfortunately it is called tinycolor2 since tinycolor was already taken.

After running

npm install tinycolor2

You can use tinycolor like so:

var tinycolor = require("./tinycolor");
console.log(tinycolor("red").toHex());

See the project homepage or the README for more info.

FileReaderSync

Friday, June 1st, 2012

I have been working on updating the FileReader.js JavaScript file reading library lately to help out with a few different projects. This library has provided a quick way to get started with reading files on a few different projects, like mothereffinganimatedgif.com and Instant Sprite.

One thing I noticed was that there is a FileReaderSync API, meant for loading files synchronously.

You might wonder why on earth would you want to load a file synchronously in your browser – that seems like it could block the entire UI until the file is loaded! It turns out you can’t, at least not in the normal window context. FileReaderSync only exists inside of the context of a WebWorker:

Implementation

View a A working JS Fiddle using FileReaderSync.

I also wrote about how to load web workers without a JavaScript file, but this technique works just fine using a normal external reference.

markup

<input type='file' id='files' multiple onchange='handleFileSelect()' />

page javascript

function processFiles(files, cb) {
    var syncWorker = new Worker('worker.js');
    syncWorker.onmessage = function(e) {
        cb(e.data.result);
    };
 
    Array.prototype.forEach.call(files, function(file) {
        syncWorker.postMessage(file);
    });
}
 
function handleFileSelect() {
    var files = document.getElementById('files').files;
    processFiles(files, function(src) {
        var img = new Image();
        img.src = src;
        document.body.appendChild(img);
    });
}

worker.js

self.addEventListener('message', function(e) { 
    var data=e.data; 
    try { 
        var reader = new FileReaderSync(); 
        postMessage({ 
            result: reader.readAsDataURL(data)
        });
   } catch(e){ 
        postMessage({ 
            result:'error'
        }); 
   } 
}, false);

The jsFiddle demo is a little more complicated than this, since it handles checking for support and an inline worker.

Gotchas

Something that was a little weird is that since you can’t detect support from the main window, I need to spawn off a worker to post the message of whether it supports FileReaderSync. See a jsFiddle to detect FileReaderSync support. There may be a better way to do this, but I don’t know of it.

This can be pretty complicated, but I have been tying it all into the filereader.js plugin, to make reading with FileReaderSync just an option along with the standard FileReader

Performance

It’s hard for me to accurately measure the performance. On one hand, the FileReaderSync seems to load the images in a slower time per image (measured in milliseconds). I assume that this is due to the overhead and message passing with the worker, or possibly because it is a newer implementation.

However, on large images and videos, it definitely feels like the UI does not lock up as much when processing the files.

Purpose

I feel like maybe part of the point of this API is when you want to some heavy lifting with the file after it is loaded but still inside the worker, which isn’t currently supported in FileReader.js. I could imagine ways this use case could be supported though (maybe by passing in a process() function as a string that the worker could call?

Check out the FileReader.js demo and see if you can tell a difference! I’d love to get any kinks worked out and get some feedback – I have been thinking of setting up a js-file-boilerplate project on Github to tie together a bunch of this functionality in a sample project.

Load Web Workers Without A JavaScript File

Friday, May 25th, 2012

Ever want to load a JavaScript Web Worker without specifying an external JavaScript file? There are a couple of different ways to do this by creating a blob and object URL – I wrapped this functionality up into a little plugin to share.

Here is the code. Or checkout out a working jsfiddle demo

// makeWorker is a little wrapper for generating web workers from strings
function makeWorker(script) {
    var URL = window.URL || window.webkitURL;
    var Blob = window.Blob;
    var Worker = window.Worker;
 
    if (!URL || !Blob || !Worker || !script) {
        return null;
    }
 
    var blob = new Blob([script]);
    var worker = new Worker(URL.createObjectURL(blob));
    return worker;
}
 
<div id='log'></div>
 
<script type='text/worker' id='worker-script'>
    self.addEventListener('message', function(e) { 
        postMessage(e.data / 2); 
    },false);
</script>‚Äč
 
<script type='text/javascript'>
 
// Load a worker from a string, and manually initialize the worker
var inlineWorkerText = 
    "self.addEventListener('message', function(e) { postMessage(e.data * 2); } ,false);"
;
var inlineWorker = makeWorker(inlineWorkerText);
inlineWorker.onmessage = function(e) {
    document.getElementById('log').innerHTML += '<br />Inline: ' + e.data;
};
 
 
// Load a worker from a script of type=text/worker, and use the getWorker helper
var scriptTagWorker = makeWorker(
    document.getElementById('worker-script').textContent
);
 
scriptTagWorker.onmessage = function(e) {
        document.getElementById('log').innerHTML += '<br />Script Tag: ' + e.data;
};
 
inlineWorker.postMessage(1);
inlineWorker.postMessage(2);
inlineWorker.postMessage(100);
scriptTagWorker.postMessage(1);
scriptTagWorker.postMessage(2);
scriptTagWorker.postMessage(100);
 
</script>

Drag Out Images and Canvas With Filenames

Thursday, May 10th, 2012

It can be annoying that when you drag out images of a browser window, they are named png.png (or something equally useless). I was playing around with fixing this – it is a little inconvenience in my CSS Sprite Generator that would be nice to have working (naming the file based on their input). Here is what I came up with (no library dependancies):

function dragoutImages() {
 
    if (!document.addEventListener) {
        return;
    }
 
    document.addEventListener("dragstart", function(e) {
        var element = e.target;
        var src;
 
        if (element.tagName === "IMG" && element.src.indexOf("data:") === 0) {
            src = element.src;
        }
 
        if (element.tagName === "CANVAS") {
            try {
                src = element.toDataURL();
            }
            catch(e) {  }
        }
 
        if (src) {
            var name = element.getAttribute("alt") || "download";
            var mime = src.split(";")[0].split("data:")[1];
            var ext = mime.split("/")[1] || "png";
            var download = mime + ":" + name + "." + ext + ":" + src;
 
            e.dataTransfer.setData("DownloadURL", download);   
        }
    }, false);
}

You just need to specify the alt attribute on the image or canvas to specify your name (along with the draggable attribute on canvas elements) and the script should handle the rest.

Browser Support

I am not 100% sure on browser support. This used to be Chrome only according to this HTML5rocks article, but maybe other browsers have picked it up by now. It is a neat little addition when available though.

Demos

See the full demo: drag out images with custom file name. This shows the ability to drag out both image and canvas tags.

On this page, you should be able to drag out the following colorpicker screenshot, which will be called spectrum.png.

spectrum

Expanding Textareas jQuery Plugin

Thursday, April 19th, 2012

Ever want a textarea to expand based on the size of the input that someone types? I made a jQuery plugin to handle expanding textareas! The basic technique is based off of a cool article called Expanding Text Areas Made Elegant. Check out the Expanding Textareas Demo and play with the Expanding Textareas Source Code.

I think it’s a pretty cool plugin that is a lot nicer than using the standard hacks for keeping textarea heights up to date. And it works really well with proportional widths, custom fonts, and min/max heights!

Here is a screenshot (which also links to the demo):


Expanding Textareas jQuery plugin

UI Anglepicker

Tuesday, April 3rd, 2012

I created a jQuery UI Widget for picking angles.

Demo: JavaScript Angle Picker Demo
Source Code: https://github.com/bgrins/ui.anglepicker

Big thanks to Original JavaScript and CSS based on: https://github.com/mrflix/LayerStyles

Inverse Rectangle Intersection In JavaScript

Monday, February 27th, 2012

Given a parent rectangle and a collection of children rectangles on a 2D plane, how do you find a collection of non-overlapping rectangles that cover the inverse of the original set?

For instance, given the container rectangle along with the set [A, B] -> we want an output similar to [1, 2, 3, 4, 5].

         +----------------------------------------------------------------+
         |                                                                |
         |                                                                |
         |       +------------------+        +--------------------+       |
         |       |                  |        |                    |       |
         |       |                  |        |                    |       |
         |       |        A         |        |        B           |       |
         |       |                  |        |                    |       |
         |       |                  |        |                    |       |
         |       |                  |        |                    |       |
         |       +------------------+        +--------------------+       |
         |                                                                |
         |                                                                |
         |                                                                |
         |                                                                |
         |                                                                |
         +----------------------------------------------------------------+


         +----------------------------------------------------------------+
         |                                                                |
         |                               1                                |
         +-------+------------------+--------+--------------------+-------+
         |       |                  |        |                    |       |
         |       |                  |        |                    |       |
         |   2   |                  |   3    |                    |       |
         |       |                  |        |                    |   4   |
         |       |                  |        |                    |       |
         |       |                  |        |                    |       |
         +-------+------------------+--------+--------------------+-------+
         |                                                                |
         |                                                                |
         |                              5                                 |
         |                                                                |
         |                                                                |
         +----------------------------------------------------------------+

Solution

Enter the inverse-intersection JavaScript project. It is a kind of micro library. No dependancies, just the math required to solve this problem!

You can grab the JavaScript file from Github.

AjaxQ jQuery Plugin

Saturday, February 25th, 2012

At Foliotek, we have a lot of components we have built (and are in the process of building) for our various projects.

We are open sourcing some of these, and the first one is the AjaxQ jQuery Plugin. The purpose of this plugin is for managing sequential ajax requests.

It is designed to follow the $.ajax, $.get, and $.post interfaces and return values, only taking one extra parameter (the queue name). Here is a brief sample of the functionality:

$.ajaxq ("MyQueue", {
        url: 'http://jsfiddle.net/echo/jsonp/',
        type: 'post',
        dataType: "jsonp"
});
 
$.postq ("MyQueue", 'path/to/your/resource', onsuccess);
 
$.getq ("MyQueue", 'path/to/another/resource', onsuccess);

In this case, each request would only run once the other finished. See the AjaxQ demo to see it in action with multiple queues.

All the source code is available on Github, available under the MIT License. I hope to have more projects to report on in the future!

JavaScript Color Parsing – TinyColor

Monday, January 9th, 2012

I threw together a color parsing library to help make my JavaScript colorpicker as small and accurate as possible. It is called TinyColor. One of the main goals is a small footprint – it clocks in at 8.98KB (3.41KB gzipped).

I have written in more detail about this on my TinyColor page. In it, I talk about the Color conversion, input recognition, color manipulation, scheme (combination) generation, and more.

JavaScript Canvas.DrawWindow implementation

Friday, July 29th, 2011

I have implemented DrawWindow (HTML rendering) functionality in Canvas. It is essentially rendering HTML inside of the canvas tag without modifying the original DOM. This took a lot of trial and error, but it is working pretty well now. The code is online here: https://github.com/bgrins/DrawWindow, and a really minimal project page is here: DrawWindow demo.

I recently found a very good implementation of this same functionality, called html2canvas, that was just released. That implementation includes nice demos and a test console, so it is worth checking out. That version is quite a bit more polished, so when I work on mine more, I will have to check out some of the great work here: https://github.com/niklasvh/html2canvas.

This functionality is necessary for web design type applications that require a colorpicker based on the current DOM, or for feedback type applications that require sending screenshots. Great to see this being built out!