Jonathon Bolster

web developer, programmer, geek

Grabbing image data from an external source to stuff into a canvas element

I was playing with Remy Sharp's collaborative drawing example after he posted it on Twitter.

Drew a couple of pictures and realised that I'm not as handy at drawing with the mouse as I used to be - so then I figured it would be better if I just put a random picture of a unicorn in. So I whacked open Developer Tools and tried to directly draw an image on the canvas element:

var img = document.createElement("img");
img.src = "http://somewhere-off-site.com/unicorn.jpg";
ctx.drawImage(img,0,0);

Can you see the problem? Pub-quiz points if you correctly guessed 'Cross Domain Security'. It was perfectly fine to chuck the picture into the canvas without a problem cropping up. The issue happens when the code tried to call 'getDataURL' for transmission. That's the no no.

So what did I do? I cheated a little bit - browsing to the picture I wanted, getting the dataURL and copying it across to the original browser window.

Voilá:

var canvas = document.createElement("canvas");
canvas.width = 50;
canvas.height= 50;

// Random image from Google Image search for unicorn - don't judge me!
var img = document.createElement("img");
img.src = "http://media.avclub.com/images/articles/article/62/62295/GLE_302-Sc9_2191_jpg_627x325_crop_upscale_q85.jpg";

var ctx = canvas.getContext("2d");
ctx.drawImage(img,-450,100);

var dataStr = canvas.toDataURL("image/png");
window.location=dataStr;

The window URL changes to give me my data URL (which I've put as the src attribute for the image tag below:

Base 64 encoded image of a girl from glee

Last thing to do is set the encoded data as the src rather than the external image URL in the code above:

var img = document.createElement("img");
img.src = "data:image/jpeg;base64,/9j/4AAQSkZJR....";
ctx.drawImage(img,0,0);

No more security problems - but we did cheat! It's a far from perfect solution (and far from perfect coding) but it works for what I wanted to do. I wanted to manually put external image data on to a canvas element and do it manually.

Finding values of XML data from a non XML column in MSSQL

I had a little bit of an issue at work when I had to create a query that returned values that were stored in an XML column. Normally you can use the XML value method to get these. My problem was that the column I wanted had XML stored in it but wasn't actually defined as an XML type.

This requires a conversion into XML. For anyone looking at the same problem, this is what I did

SELECT 
    tbl.ColumnName
    ref.value('FirstName[1]', 'nvarchar(100)') as [FirstName],
    ref.value('LastName[1]', 'nvarchar(100)') as [LastName],
FROM myTable tbl 
CROSS APPLY (SELECT CONVERT(xml, tbl.MyNonXmlCol)) as T(X)
CROSS APPLY T.X.nodes('//AuthorDetails[1]') R(ref)

Finding and dropping a constraint using a table and column name

I had a bit of a problem in work. I had to write some SQL to drop a uniqueness constraint on a column but was unsure of the constraint name (since it was auto generated with a GUID on the end). Looking at the MSDN 'Alter table' documentation, it seems that you need the constraint name to drop it (please correct me if I'm wrong). I knew the table and the column names, so this is what I needed to work with.

So here's what I came up with and this did the job:

DECLARE @constraintName VARCHAR(50)

select @constraintName = CONSTRAINT_NAME
from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE TABLE_NAME = '[YOUR_TABLENAME]' AND COLUMN_NAME = '[YOUR_COLUMNNAME]'

IF  EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[YOUR_TABLENAME]') AND name = @constraintName)
    EXEC('ALTER TABLE [YOUR_TABLENAME] DROP CONSTRAINT ' + @constraintName)

This worked for me since I know that the column will only have one constraint. Presumably the CONSTRAINT_COLUMN_USAGE will return multiple rows if there are multiple constraints. I also did the EXEC to get past the limitation that the DROP CONSTRAINT call doesn't accept a variable.

If anyone has any comments/improvements on the above, I'd appreciate if you let me know.

How clean is your window (object)?

I recently wanted to see how polluted the global namespace of our web application was. By that, I mean I wanted to see how many unnecessary objects we were assigning to the window object.

To do this, I wanted to compare against a clean window object. A quick look on Google and I found this article: Getting a clean document or window Object in JavaScript. The basic idea is that you create a new iframe element, and you can use the contentWindow property of that to give you a nice clean window object. As the author states, you might want to do this to prevent the remapping of native methods but I just want it for a quick (i.e. hacky) way to see what objects have being put into my own 'clean' window.

What I do is create the iframe to get my clean window. Set up an object to copy across the objects from the main window object, then remove any that appear in the clean window.

Here it is in glorious, unminified code:

(function(window){
    var keys = {},
    cleanWindow,
    iframe = document.createElement("iframe");

    iframe.style.display ="none";
    iframe = document.body.appendChild(iframe);

    cleanWindow = iframe.contentWindow;
    document.body.removeChild(iframe);

    for(var keyName in window){
        keys[keyName] = window[keyName];
    }

    for(var keyName in cleanWindow) {
        delete keys[keyName]
    }

    return keys;
}(window))

This is written as self executing JavaScript and will return an object containing the objects that we worked out were added to the window.

Note: This is a very quick and dirty piece of code. Mostly it was an experiment for myself, to use the 'clean window' object. It won't tell you if a native window property was changed or anything, it only compares the keys. Just remember that.

Looking at the animations on Google's Jim Henson doodle

On opening Google today, I'm shown a couple of muppets I can control (well, I can open their mouths and spin their heads around). This is to celebrate Jim Henson's 75th birthday, but I'm interested in what makes it tick since there are a few little animations in there and I want to see what Google does.

Google Doodle for Jim Henson's 75th Birthday

Looking at the images that are loaded, they seem to be PNG sprite images. So then I went on a little (short lived) mission on how to recreate the animations myself. Honestly, there are muppet animations you can play with soon.

There is a handy little jQuery plugin called Spritely. This will take a jQuery selector object and manipulate the background image position to generate the animation. Nicely, all you have to do is supply the number of frames and it will do the rest for you.

So I open up a new jsFiddle, fill in my HTML and CSS with the containers and background images I want and then put in this little beauty:

$('div').click(function() {
    var $this = $(this);
    $this.sprite({
        fps: 9,
        no_of_frames: $this.data("num"),
        on_last_frame: function(obj) {
            obj.destroy();
        }
    });
});

Now, what I've done here is make it so that every div object will generate a sprite animation on click. This probably isn't the prettiest way to do it, but I have only just discovered Spritely so I'll look at the docs and improve. If you want to let me know in the comments, that'd be appreciated.

(Also, for the eagle eyed of you, I'm using a data attribute to store the number of frames in the animation. This was painstakingly done by opening the PNG files and counting the muppet heads. I bet I will find Spritely would do it for me after reviewing the documentation).

You've waited long enough. Go to the jsFiddle to play with the Muppet animations.

Alternatively, here are links to the sprite images I've seen. Haven't found anything for the blue guy on the left though! If you have, let me know and I'll add it.