Monday, November 18, 2013

Canvas Clickable Regions - Demystified

Let's face it, canvas stuff is never terse and annoying. Creating buttons on a canvas is even harder. First you have to draw the button, change it's state, and other complicated things.

For instance, if the user pushes the mouse down on one clickable region, and drags it over to ANOTHER clickable region, the "click" event will still fire and (therefore) fire the second region's click event.

So what kinds of things do we actually need to figure this stuff out?

Well, for starters, let's demystify the mouse event positions.

//let's cache the event
var priorEvt;
function getMousePos(evt) {
//set and store..
priorEvt = evt = evt || priorEvt;
//get the bounding rectangle
var rect = canvas.getBoundingClientRect();
//lastly, return the x and y coordinates
if (evt)
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
return {
x: 0,
y: 0
};
}
view raw getMousePos.js hosted with ❤ by GitHub


This will give you a way to get the mouse location of any click event. So let's build our clickable region first.

function CanvasButton(img, x, y, width, height) {
//this function takes an "position" object passed by the canvas click events
//to the position function defined above
function onButton(pos) {
//it determines if the position is greater than x, less than the width
//and greater than y, less than the height
return (x <= pos.x && pos.x <= x + width) &&
(y <= pos.y && pos.y <= y + height);
}
}


Cache the canvas and draw an image...

var canvas = yourCanvasHere;
function CanvasButton(img, x, y, width, height) {
//this function takes an "event" object passed by the canvas click events
function onButton(pos) {
//it determines if the position is greater than x, less than the width
//and greater than y, less than the height
return (x <= pos.x && pos.x <= x + width) &&
(y <= pos.y && pos.y <= y + height);
}
//go ahead and replace this section with whatever you need to draw the image
if (Object.prototype.toString.call(img) === '[object String]')
img = document.getElementById(img);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, x, y, width, height);
}
view raw canvas.js hosted with ❤ by GitHub


..and the only things that are missing are the click events...

var down = false;
canvas.addEventListener("mousedown", function (evt) { //event listener
down = onButton(getMousePos(evt));
});
//handle the document mouseup to reset the "down" variable every time.
document.addEventListener("mouseup", function (evt) {
if (onButton(getMousePos(evt)) && down) {
//we got a click!
}
});


and put it all together!

var priorEvt;
function getMousePos(evt) {
priorEvt = evt = evt || priorEvt;
var rect = canvas.getBoundingClientRect();
if (evt)
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
return {
x: 0,
y: 0
};
}
function CanvasButton(img, x, y, width, height) {
//this function takes an "event" object passed by the canvas click events
function onButton(pos) {
//it determines if the position is greater than x, less than the width
//and greater than y, less than the height
return (x <= pos.x && pos.x <= x + width) &&
(y <= pos.y && pos.y <= y + height);
}
//go ahead and replace this section with whatever you need to draw the image
if (Object.prototype.toString.call(img) === '[object String]')
img = document.getElementById(img);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, x, y, width, height);
//draw region end
//the button isn't toggled by default
var down = false;
canvas.addEventListener("mousedown", function (evt) { //event listener
down = onButton(getMousePos(evt));
});
//handle the document mouseup to reset the "down" variable every time.
document.addEventListener("mouseup", function (evt) {
if (onButton(getMousePos(evt)) && down) {
//we got a click!
}
});
}
view raw CanvasButton.js hosted with ❤ by GitHub


The final product looks a bit like this, because you totally took the code and made it work for your project.. right? Get coding people!

In functional health,
Josh

Friday, November 15, 2013

Array forEach Synergy

Today I wanted to share another nice and small use case for the forEach loop for the intermediate/beginner javascript developer.

function AudioWrapper(src){//Simple audio wrapper
var audio = new Audio(), self = this;//create the audio element
audio.src = src;//set the source...
['play','stop','pause'].forEach(function(item){//play stop and pause hookup
var actualCommand = item === 'stop'?'pause':item;//when stopping, use pause instead
self[item] = function(){//set the function...
audio[actualCommand]();//call the pause or play function
if(item === 'stop')//and if stop is called...
self.currentTime(0);//go back to the start
};
});
this.currentTime = function(time){//small convenience function
return audio.currentTime=time||time===0?0:src.currentTime;//sets the current time or returns it
};
this.canPlay = function(){//just checks to see if the readyState is 4
return audio.readyState === 4;//ready state!
};
this.onReady = function(func){//Any function hooked here will be called 100% of the time
var args = [].slice.call(arguments, 1);//unless it isn't loaded
function checkReady(){//named function
if(self.canPlay())//check to see if it can be played
func.apply(self, args);//call the function...
else
setTimeout(checkReady,100);//check in a few seconds.
}
checkReady();//start up!
};
}
var x = new AudioWrapper(src);//create the Audio
x.onReady(function(playLength){//hook up a function...
x.play();
setTimeout(x.stop, playLength);
},10000);
view raw AudioWrapper.js hosted with ❤ by GitHub


As a disclaimer, my code isn't perfect, it can be optimized, and my goal isn't give you snippets of code to steal. However, I do this to show you how to make your own javascript functions yourself. Take my code and tweak it, add some useful functions that may help you finish your project.

I hope my samples help grow and motivate you to strive and become a better programmer.

In functional health,
-Josh

Monday, November 11, 2013

Sharing: Self Invoked Object Literals

Some techniques aren't new or novel. They are just fun. This isn't really new, or novel either, but it's quite fun.

~{
func: function(){
alert("hello world!")
}
}.func();
view raw example.js hosted with ❤ by GitHub

In fact, some people would probably criticize that it is essentially the same thing as an Immediately Invoked Functional Expression. There are some key differences here though. Take a look at the following code.

var foo = {
bar: {
//put some named functions here
},
baz: function(){
return Object.create(this.bar);
}
}.baz();
view raw example-2.js hosted with ❤ by GitHub

It's starting to look like the module pattern, but it creates an object and ships it via function baz to the variable foo with bar's prototype. Alas, the this keyword shows it's confusing head again, but look closely. "this" is the object literal itself.

Finally I'll leave you with a working example.

!{
//Typical API functions should go here
//func : function(){}....
//func2 : function(options){...}
//Object creation methods...
//convenience methods here for create and expose via this
createObject: function(options){
//constructor logic here
var created = Object.create(this.fn);
var args = [].slice.call(arguments);
this.plugins.forEach(function(plugin){
plugin.apply(created, args);
});
return created;
},
fn:{//prototype methods here
},
expose:function(NameSpace, target, plugins){//initialization code.
target[NameSpace] = this;//target can be the window (exposed) or some other object
this.plugins = plugins;
delete this.expose; //remove the reference to expose
}
}.expose("LibraryNamespaceHere", {}, []);

Sometimes, the "new" keyword is overrated when making objects anyway.

In functional health,
-Josh

Friday, November 8, 2013

Defining Plugin Architecture for Constructor Libraries

Even in a hypothetical world where objects are packaged into black boxes it would seem that convention and configuration butt heads repeatedly until developers are quite frustrated with their code. In the real world it's even more difficult to package up black boxes because the language architecture design is fundamentally flawed. (I'm looking at you Javascript global namespaces!)

So, I've personally set out to develop quick easy ways to make boxes that appear to be black boxes, but are highly configurable.

Here were some of the goals I had in mind for designing my personal plugin Architecture.

  1. Had to be easy!
  2. Had to be quick!
  3. Plugin Convention over configuration
  4. Boilerplate-able
  5. Should give access to constructor options to determine where the construction of the object goes
  6. Should provide a local scope for hidden variables relative to each object.

Here's a boilerplate you can use to create something like I'm describing.

!function(window, document, undefined){
function constructorObject(options){
//do something with constructor object here
}
window["constructorObject"] = constructorObject;
}(window,document)
view raw gistfile1.js hosted with ❤ by GitHub
I've a feeling we're not in the global namespace anymore.

If some of that code looks confusing to you, I suggest looking at the concept of functional expressions. They give you a "pseudo-blackbox" that can see the global namespace.

If you are good on closures, then we move on to the next step. Actually defining the code to make plugins work. Here's what I personally use:

!function(window, document, undefined){
plugins = [];//Plugin storage object
function constructorObject(options){//object constructor
var self = this; //store itself for later
plugins.forEach(function(plugin){
plugin(self, options);//pass this instance of the constructed object to the plugin
//the options used to construct it are also passed as well
});
}
constructorObject.plugin = function(func){//function to define plugins exposed
plugins.push(func);//append the plugin
};
window["constructorObject"] = constructorObject;//expose the constructor
}(window,document)
view raw gistfile1.js hosted with ❤ by GitHub

This code is rather simplistic, but lets take a look a bit deeper to see the real beauty of it.

plugins.forEach(function(plugin){
plugin(self, options);//pass this instance of the constructed object to the plugin
//the options used to construct it are also passed as well
});
view raw gistfile1.js hosted with ❤ by GitHub

This little function right here is where ALL the magic happens. Let me show you an example of why this is "magic." Writing a plugin is very easy to do here.

!function(constructorObject, undefined){
constructorObject.plugin(function(self, options){
//Plugin constructor code goes here
//Now you have access to the self object and options by reference
if(typeof options !== "undefined" && options.property)//put some logic here...
self.protofunc();//call a function on itself
});
constructorObject.prototype.protofunc = function(){// in the closure space, modify it's prototype
console.log("hello world!");
}
}(constructorObject/*, additional plugin dependencies*/)
view raw gistfile1.js hosted with ❤ by GitHub

Boom! Now you can call this:

var myObject = new constructorObject;
myObject.protofunc();
view raw gistfile1.js hosted with ❤ by GitHub

As if that wasn't enough... let's go back and look at another example. A full on event emitter API.

!function(constructorObject){
constructorObject.plugin(function(self, options){
var events = {};//event parent
self.on = function(eventNameSpace, func){//add the function to the namespace
var event = events[eventNameSpace] = events[eventNameSpace]||[];//coalesce and make sure it's an array
func._function_id = func.name+Date.now();//give it some unique value for later
event.push(func);//store it
return self;//chain!
};
self.trigger = function(eventNameSpace){//activate an event namespace
var event = events[eventNameSpace]||[],
args = [].slice.call(arguments, 1);//grab everything except the namespace and pop it into an array
event.forEach(function(func){//for each event
func.apply(self, args);//apply the arguments
});
return self;//chain!
};
self.off = func(eventNameSpace, func){//remove a queued event
var event = events[eventNameSpace]||[];
for(var i = 0, _len = event.length;i<_len; i++){//for each event
var eventFunc = event[i];//grab the event
if(func._function_id === eventFunc._function_id){//compare id's
event.splice(i,1);//remove it from the queue completely
return self;//all done, don't loop any more
}
}
return self;//Chain!
})
});
}(constructorObject/*, additional plugin dependencies*/)
view raw gistfile1.js hosted with ❤ by GitHub

Take some serious time to learn what just happened here. Each one of the functions created in that script are local to the object itself, because the plugin constructor code is called only once. This allows you to enclose private variables into a black box namespace. It's completely abstracted away to the developer behind the curtain.

Please pay no attention to the variables behind the functional expression.

In functional health,
-Josh

Tuesday, November 5, 2013

Native vs Functional Loops

var topics = ['Native Loops','Functional Loops','Indications for Native Loops'];
topics.shift();
//'Native Loops'
view raw topics.js hosted with ❤ by GitHub

Native loops...

...are a functional portion of the javascript language and allow you to repeat functionality of code for a certain number of times specified by the conditions of the loop.

var array = [1,2,3,4,5,6,7,8,9,10];
for(var i = 0, _len = array.length; i < _len; i++){
//do something with array[i]
}
// new snippet
var j = 0, _len = array.length;
while(j < _len){
//do something with array[j]
j++;//increment j...
}
///etc
view raw native_loops.js hosted with ❤ by GitHub
These examples are fairly easy and trivial. If you are not proficient in javascript loops, I highly recommend learning how to construct one from scratch here.
topics.shift();
//'Functional Loops'
view raw gistfile1.txt hosted with ❤ by GitHub

Functional loops provide a different mechanism for looping over the items in an array. They also have much larger implications for memory management and coding techniques.

Example: a user wants to loop over items in an array and perform a static operation.

var array = [1,2,3,4,5,6,7,8,9,0], target = [];
array.forEach(function(item){
//do something with each `item` here
target.push(item);
});

This example is obviously bad, because the same result could be achieved by calling target = array.slice();, but look a little bit closer at the example below.

var closuredObjects = [/*put a bunch of objects that need a closure here*/];
closuredObjects.forEach(function(item){
var invisibleProperties = {};
item.get = function(key){
return invisibleProperties[key];
};
item.set = function(key, value){
invisibleProperties[key] = value;
return value;
};
});

Boom. Now you can enclose objects with functions and local variables.

topics.shift();
//'Indications for Native Loops'
view raw topics.js hosted with ❤ by GitHub

So now that we have our toolset, let's make a few rules on when certain loops are needed.

Native loops

  • When a functional context is not needed
  • Concatenating strings
  • Looping through strings
  • Anywhere that performance matters greatly

To put it simply, if the code requires speed and performance, chances are a for loop may be indicated. Especially for simple operations.

Lastly, the indications for functional loops...

Functional loops

  • When a closure is needed(I.E. Variables need to be obscured)
  • Chaining Maps (see example below)
  • When the calling function needs to be called multiple times in other places in the code (using a named function)
  • When Performance probably doesn't matter (and trust me, javascript is pretty fast)
  • When file size DOES matter
function multiplyByTwo(item){return item*2;}
function addTwo(item){return item+2;}
function applyTransform(){
return Array.prototype.map.call(arguments, addTwo)
.map(multiplyByTwo)
.map(addTwo);
}

The code looks more fun, and is more expressive. It's less terse, but that's the price you pay for a functional language expression

In functional health

-Josh

Monday, November 4, 2013

Handlebars Templating?

var topics = ['Easy Handlebars Templating'];
topics.shift();
//'Easy Handlebars Templating'
view raw gistfile1.js hosted with ❤ by GitHub

I have been writing small posts lately, so it's probably best if I just cut to the chase.

Handlebars has been tried and true for templating.
Also, I'm in no way advocating for the use of these samples, but I think they speak for themselves. You don't always need a library because you are making an intranet application, or your users use modern browsers. You can code the language yourself!
String.prototype.template = function(templateObject){
return this.replace(/\{\{([a-zA-Z\_0-9\.]*?)\}\}/g, function(match){
var temp = templateObject;
match.slice(2,-2).split('.').forEach(function(item){
temp = temp[item];
});
return temp;
});
};
view raw gistfile1.js hosted with ❤ by GitHub

And one for objects...
Object.prototype.template = function(templateStr){
var that = this;
return templateStr.replace(/\{\{([a-zA-Z\_0-9\.]*?)\}\}/g, function(match){
match.slice(2,-2).split('.').forEach(function(item){
that = that[item];
});
return that;
});
};
view raw gistfile1.js hosted with ❤ by GitHub

"But Josh! I don't want to edit the prototype!"
Fine! Here you go.
function HandleBar(templateStr, templateObject){
var that = templateObject;
return templateStr.replace(/\{\{([a-zA-Z\_0-9\.]*?)\}\}/g, function(match){
match.slice(2,-2).split('.').forEach(function(item){
that = that[item];
});
return that;
});
};
view raw gistfile1.js hosted with ❤ by GitHub

I encourage you to at least understand what is going on in this code before you steal it, and certainly be able to implement it yourself.

Having fun with Function.prototype.call

var topics = ["idea","examples","post some code"];
//["idea","examples","post some code"]
topics.shift();
//"idea"
view raw gistfile1.js hosted with ❤ by GitHub

In javascript, using the .call() method allows you to specify the context of whatever object you pass to it. This allows you to call a string method from an array context, and vice versa.

topics.shift();
//"examples"
view raw gistfile1.js hosted with ❤ by GitHub

Check out the following script...

var arrayObject = ["What", "is", "going", 0,"on", 111,"..", "here"];
String.prototype.slice.call(arrayObject);
//"What,is,going,0,on,111,..,here"
String.prototype.concat.call(arrayObject);
//"What,is,going,0,on,111,..,here"
String.prototype.substring.call(arrayObject,1,10)
//"hat,is,go"
String.prototype.indexOf.call(arrayObject, "n,111")
//17
var stringObject = "Hello";
Array.prototype.forEach.call(stringObject, function(item){console.log(item)})
//H
//e
//l
//l
//o
Array.prototype.map.call(stringObject, function(item){
if( item >= "A" && item <= "Z")
return"U";
return "L"
})
//["U", "L", "L", "L", "L"]
//Upper and lowercase map for the string!
view raw gistfile1.js hosted with ❤ by GitHub

In all honesty, it may not be a good idea to use these methods, because they aren't supported on these objects, but check out what happens!

topics.shift();
//"post some code"
view raw gistfile1.js hosted with ❤ by GitHub

Go nuts and try out some other methods and post them in the comments to see what you come up with.