Category Archives: JavaScript

Decorator Pattern in JavaScript

02 Jan 2018

Every once in a while I review different patterns to see if any that I don’t use might come in handy for any work that might be ongoing, that was previously done or to just try my hand at one of them so that I’ve got it in my toolbox for whenever I may need it. Recently I was reviewing at the apply and call methods and found myself reviewing a “decorator” pattern that used apply. I decided to dive into the pattern and am repeating the learning here…

First, lets start with a class called “MyClass”. It contains a hello property and a method called talk. The method prints a message to the screen using the property’s value as part of the message.

What I would like to do is to decorate a “MyClass” instance so that a different message is printed to the console without changing the class itself. To begin I have the class defined below, created an instance of it called “myInstance”, and have called its talk method to get “hello world” logged to the console:

var MyClass = function(){
    this.hello = 'world';
    this.talk = function(){
        console.log('hello ' + this.hello);
    }
}

var myInstance = new MyClass();
    myInstance.talk();  // prints "hello world"

The above code prints “hello world” to the console. What we will do to this example is print something else to the console without modifying the class. We will “decorate” the “myInstance” object so that a different message is printed to the console when talk is called.

See the following:

'use strict';

var MyClass = function(){
    this.hello = 'world';
    this.talk = function(){
        console.log('hello ' + this.hello);
    }
}

var myInstance = new MyClass();

var decorator = {
    hello:'universe',
    decorate:function(func){
        var that = this;
        return function(){
            return func.apply(that,[]);
        }
    }
}

// the undecorated MyClass instance
myInstance.talk(); // prints "hello world"

// here we decorate "myInstance"
decorator.decorate(myInstance.talk)(); // "hello universe" prints instead

// the undecorated MyClass instance
myInstance.talk(); // still prints "hello world"

Lets look at the “decorator” object. Note that it holds the string “universe” within the hello property. What we want to happen is for the decorator.hello property’s value (“universe”) to override the value of myInstance.hello (“world”) so that the desired “hello universe” message is logged to the console. And, do it in such a way as to NOT modify MyClass.

We can do this by using the apply method to pass along the decorator‘s context into myInstance.talk to temporarily replace the context and thus change the value of myInstance.hello from “world” to “universe”. It does this by passing the “that” reference, which is scoped to the wrapping function (decorator.decorate) where it is then mapped to “this”, a reference to the parent object (decorator), where the hello property can be found.

You don’t have to hold the desired over-riding property within the decorator, you could pass along an object as the desired context as well.

var myClass = function(){
    this.hello = 'world';
    this.talk = function(){
        console.log('hello ' + this.hello);
    }
}

var myInstance = new myClass();

var newData = {hello:'universe'};

function decorate(func){
    return function(){
        return func.apply(newData,[]);
    }
}

myInstance.talk(); // prints "hello world"

decorate(myInstance.talk)(); // prints "hello universe"

myInstance.talk(); // prints "hello world"

A word about these lines:

decorator.decorate(myInstance.talk)(); // prints "hello universe"
// and 
decorate(myInstance.talk)(); // prints "hello universe"

Note the addition of the grouping operator at the end – the extra set of parens – as we are returning a function we must execute it which the parens does for us.

We could have just as easily spent some time to write things out like this:

var d1 = decorator.decorate(myInstance.talk);
    d1(); // prints "hello universe"
// and 
var d2 = decorate(myInstance.talk);
    d2(); // prints "hello universe"

… at the expense of a few more characters and a little memory.

Lastly, the apply method takes 2 arguments, the first being the context and the second is an array of attributes. The second is optional and we’re not utilizing it but I’m in the habit of passing along an empty array to remind myself that an array (or array-like object) is an acceptable value for this second argument. At the expense of getting away from the decorator pattern and into how apply works lets take a look at an example where we pass an array of properties to the decorated function.

'use strict';

var myClass = function(){
    this.hello = 'world';
    this.talk = function(sky,grass,brick,dog){
        if (arguments.length !== 0){
            console.log('the sky,grass,brick,dog);
        } else {
            console.log('hello ' + this.hello);
        }
    }
}

var myInstance = new myClass();

var newData = {hello:'universe'};

function decorate(func){
    return function(){
        return func.apply(newData,['blue','green','red','brown']);
    }
}

myInstance.talk(); // prints "hello world"

decorate(myInstance.talk)(); // prints "hello universe blue green red brown"

myInstance.talk(); // prints "hello world"

You can see that the the positions of the strings in the array match up with the expected arguments of “sky,grass,brick,dog” and so are easy to log to the console.

Throttling Delegated Events in jQuery

12 May 2017

If you’ve read any of my posts you might have seen the pattern I like to use for using event delegation. That pattern, in its simplest form, looks like this:

$(document).ready({
   $('body').on('click','div',changeSomething);

   function changeSomething(e){
      // do something
   }
});

For me this is super useful – I can dynamically add elements to the DOM and not need to worry about attaching event listeners to specific UI elements. Well, as you can see I have the click event mapped to div elements. This works fine for something as simple as this:

<div>hello world</div>
<div>the sky is blue</div>

If I click on one of the above divs my changeSomething event will fire. If that’s what I wanted to happen then this is working perfectly. But what happens when we introduce more complicated layout with nested div‘s?

<div>
  <div>hello world</div>
  <div>the sky is blue</div>;
</div>

Each time I click on within either string of text **2** events are fired and my function will be fired twice. Consider this layout:

<div>
  <div>
    <p>hello world</p>
    <div class="button">I'm a button</div>
  </div>
  <div>
    <p>the sky is blue</p>
    <div class="button">I'm another button</div>
  </div>
</div>

If I clicked the “button” divs you will see that **3** events are fired for each click. Why would this be?

First, lets understand how event delegation works.

Event delegation relies on event bubbling. Event bubbling is the behavior that describes how events “bubble up” through the DOM. That is, they start at the DOM element where it was initiated and then travel up to that element’s parent, and then up to the parent’s parent, etc., until the event is stopped somehow (perhaps via the event.stopPropagation() method) or it reaches the top level DOM element.

Event bubbling is key to delegating events – notice that I bound the click event to the body – this means that my code is waiting for “click’s” to “bubble” their way up to the body. If they didn’t bubble through the DOM then the event listener I created would never “hear” the event.

While this explains why it is possible to delegate events it doesn’t explain why when using jQuery to create event listeners that we “hear” multiple events each time we click on a div one single time. This bit from the jQuery documentation provides the answer:


jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.

Note that the docs says “…and runs the handler for any elements along that path matching the selector. Therein lies the answer. By definition jQuery will fire our callback handler for each element that matches the selector that I specified when I created the event listener. Because event bubbling means that the event will travel up though the DOM the event is therefore “hitting” other DOM elements that match the given selector. Each time this happens the callback handler is fired and the callback receives the very same event object.

Now that we understand what is happening we can look at our HTML and know that this structure:

<div> <!-- the event bubbles to here and the callback is fired a third time -->
  <div> <!-- the event bubbles to here and the callback is fired a second time -->
    <p>hello world</p>
    <div class="button">I'm a button</div> <!-- click here to fire the click event and the first callback -->
  </div>
</div>

…will cause our callback handler to fire 3 times from a single event instead of firing only once (see the in-code comments above).

How do we setup the listener to prevent this from happening? Well…. we could create a unique selector like .btn but I find that restrictive because it creates unnecessary JS hooks into our HTML (imagine all the selectors you would have, i.e., .btn .add .delete .menu .expand… what a mess!!!). In the end jQuery behaves the way that it behaves but we can easily write a small bit of code to prevent a single event from firing our callbacks multiple times.

Recall that each callback is passed the event object which will be the same for them all. As a result if you log those events to the console you will in fact see that they all have the same timestamp since, quite naturally, they are in fact identical. With this knowledge we can build a “throttling” function. Throttling is the term used to allow the first function call, but prevent subsequent calls.

Review the following (its very much simplified for this example):

   $(document).ready({

      var _fifo = []; // used by the throttler

      // throttle
      function _isOriginal(e){
        for (var i=0;i<_fifo.length;i++){
          if (_fifo[i] === e.timeStamp){
            return false;
          }
        }

        _fifo.push(e.timeStamp);
        if (_fifo.length > 20){
          _fifo.splice(0,1);
        }
        return true;
      }

      // create event listener
      $('body').on('click','div',changeSomething);

      // the callback for the delegated "click" event
      function changeSomething(e){
        // check the event to see if we have already seen it!
        if (!_isOriginal(e)){
            return; // if we ***have*** already seen the event then ignore it!
        }
        // do stuff in here
      }
   });

Pay attention to the _isOriginal function. It does the following:

  • Uses the _fifo array to store the 20 most recent timestamps (“20” is arbitrary, pretty sure 1 or 2 will work as well)
  • Compares the timestamp of the current event against those stored within the _fifo array
  • If there is a match it returns “false” (ignore the event)
  • If there is no match it returns “true” (new event!)
  • Timestamps are cycled in and out of the _fifo array at all times so that we will always have a timestamp from the most recent event and thus will always be able to compare and reject copies. The last/oldest timestamp is pruned (via the splice method ) from the _fifo array once its length hits 20 while the newest is added to the front (read about FIFO stacks)

There you go, a simple and effective “callback throttler”. As always, if you understand how things work you may just find that you don’t need to go in search of a plugin to solve your problem. A little “under-the-hood” knowledge goes a long way 🙂

Installing the Brackets-ESLint NPM package

07 Jan 2017

If you are interested in an ES6 linter for Brackets there is a plugin called “Brackets-ESLint” that will do the job. However, it cannot be installed like any other Brackets plugin. You must first install a plugin called “Brackets-npm-registry” which functions similarly to the Brackets plugin manager but for Brackets-specific NPM modules.

The Brackets-npm-registry Plugin

Visit the following URL and read through the installation instructions for your platform. Note that on Windows you may have to manually navigate to your AppData directory.

Note that installation may take a few minutes.

The Brackets-eslint Plugin

Once “Brackets-npm-registry” is installed you will notice a new icon in the Brackets plugin bar:

eslint_01

Clicking the plugin reveals the “Brackets-npm-registry” module manager:

eslint_02

Scroll through the list and locate “ESLint” – install the plugin (this may also take some time to complete)

Once installation is complete close the installation window, then close the NPM module manager, and then restart Brackets (F5 on Windows).

Working with ESLint

Upon installing ESLint and restarting Brackets you may see linting issues within the left gutter of opened JS files such as can be seen in the image below:

eslint_03

Place the cursor above the red/yellow icons wihtin the left gutter to reveal a tool-tip explaining the linting issue. Alternatively you can toggle the display of the complete list of issues at the bottom of your editing window (also visible within the above image).

Configuring the Linter

Comments can be added to code to configure the linter. Of particular interest is the ability to instruct the linter to ignore a line of code. For example, this JS comment will remove the line it sits on from linting:

// eslint-disable-line

For example, note the following image and how by virtue of the red “X” icon in the gutter that there is a linting issue for that line:

eslint_04

To tell the linter to ignore the line we add the comment to the end and thus the issue goes away:

eslint_05

For further configuration options, including specifying blocks of code to ignore and configuring the linter via in-code comments see the following guide:

Specifying your Preferred Linter

You may not want to use ES6 linting for your ES5-based projects. In that case you’ll want to update Bracket’s preferences file per the description here to use your preferred linter.

Diffing Two Canvases

03 Sep 2016

Below is the script I wrote that will take two canvases and find the differences between them – a canvas diff. What it returns is the bounding area – upper left coordinates and lower-right coordinates – with which you can do as you like.

The challenge here is iterating through the pixel data. The data itself is an array of each pixel’s RGBA values in sequence. For example, if we are looking at four pixels then the pixel array representing them would have a length of 16 (RGBA = 4 array elements x the number of pixels = 16). This imaginary array could look like:

  • 0,0,122,5,100,12,123,6,16,100,43,123,55,55,100,50

With a little formatting to help make it make more sense we can easily see the groupings:

  • 0,0,122,5,    100,12,123,6,    16,100,43,123,    55,55,100,50

Looking at the first group of 4 numbers we can see that the pixel they represent has these RGBA values:

  • R: 0
  • G: 0
  • B: 122
  • A: 5

Imagine a 1024×768 image represented by a single data array of RGBA values. Such an image would have a data array length of 3,145,728 (1024 x 768 x 4). In order to manipulate the pixel data you’d have to discover a way of looping through the array keeping in mind that every group of 4 array elements is itself a single pixel. You would also need to realize that any given group of array elements represents a specific pixel somewhere within your image/canvas.

Image Comparison Example

In the example shown here I’m comparing the pixel data between two images, keeping track of the differences, and returning a bounding area that encompasses them.

This example is in an iframe – view source to see the script that loads the images into image objects, then loads those images into two canvas elements, extracts the image data from the canvases, compares them, and then finally draws the red bounding boxes to illustrate where the images diverge from each other.

Diff Function – Comparing Two Canvases

The function I wrote below compares all the pixels and notes the coordinates of the ones that don’t match. I then use the sort array method to sort the resulting “diff” array by either the X or Y of each diff’d coordinate so that I can find the extremes of each one.

While I’m looking for the differences I am also keeping track of the X and Y coordinate representing each RGBA quadruplet. Note the use of the modulus operator as that is what makes the coordinate-tracking work.

To use this function all you have to do is create two image data objects using the canvas getImageData() method then pass them to the canvasDiff function where the first data object is the original image and the second is the one that has changed. Refer to the iframed example above – view source to see how the diff function seen below was used within the example to produce the bounding differential boxes.

When using images as the source data they need to be of identical size and ideally in PNG format. PNG is optimal because JPG is a lossy compression algorithm that will make it hard to do a legit diff – provided you are using images at all – you could easily just have programmatically-generated canvas art – point is that canvasDiff needs two image data objects where the images are the same physical dimensions.

function canvasDiff(imageData1,imageData2){
    // www.rickluna.com - please leave the attribution!
    var w = imageData1.width;
    var h = imageData1.height;
    var diffs = [];
    var start = {x:null,y:null};
    var end   = {x:null,y:null};
    var pA1_r,pA1_g,pA1_b,pA1_a,
	pA2_r,pA2_g,pA2_b,pA2_a;
    var y = 0;
    var x = 0;
var len = imageData1.data.length;
    for (var i=0;i b.x){
	    return 1;
	} else {
	    return 0;
	}
    });
    start.x = diffs[0].x || 0;
    end.x = diffs[diffs.length-1].x || w;
    diffs.sort(function(a,b){
	if (a.y < b.y){
	    return -1;
	} else if (a.y > b.y){
	    return 1;
	} else {
	    return 0;
	}
    });
    start.y = diffs[0].y || 0;
    end.y = diffs[diffs.length-1].y || h;

    // DONE
    // "start" and "end" have the bounding coordinates
    console.log(start,end);
    return [start,end];
}

Loading an image from the iOS Library in PhoneGap

23 Aug 2016

While working through one of my personal projects I’ve figured out how to load an image from an iOS device’s Library. There are two steps – first use the Camera plugin to provide a UI for the user to select a file. The next is to take the file path the Camera plugin provides and use the File plugin to load it.

Requirements

This was tested via PhoneGap Build using the following setup:

  • CLI 6.3.0
  • iOS deploy target: 9.0.0
  • Camera plugin version 2.2.0
  • File plugin version 3.0.0

If you’re using PhoneGap Build this is what should be added to your config.xml





Using the Camera Plugin to Access the Library

It might seem counter intuitive to use the Camera plugin since it seems logical to first look at the File API to look for files… unlike the File API where you would need to write your own file browser and UI, the Camera Plugin uses native functionality and so makes it trivial to pick an image from a user’s Library. The Camera plugin will present a native UI to the end-user so that they can navigate their Library’s folder structure to locate the image they want to use and in the end provide a path to that image on the device.

This code will do what is described above:

   navigator.camera.getPicture(
      function (fileURI){
         console.log(fileURI);
         /* remove the comment below to use with
          * the rest of the code on this page
          */
         //convertPath(fileURI);
      },
      function (err){
         // fail
         console.log('fail',err);
      },
      {
         allowEdit: true,
         correctOrientation: true,
         destinationType: Camera.DestinationType.FILE_URI,
         sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
         targetHeight: window.innerHeight,
         targetWidth: window.innerWidth
      }
   );

Literally copy and paste the above, here are the things to note about the configuration object:

  • allowEdit – this is a flag that tells the native Library picker UI to allow scaling/positioning of the resource that the user selects.
  • correctOrientation – as it implies, use the image in the correct orientation relevant to how the device is being held
  • destinationType – this is the part that tells the plugin to return the path to the image
  • sourceType – tells the plugin to display UI to allow the user to select the image from the library
  • targetHeight – the desired height of the image – iOS creates a temporary image and passes that path back to you based on any edits and the Height and Width settings. Here I just assume that you would want an image that is the size of the viewport.
  • targetWidth – see above

That’s it. Dead simple. Now we need to load up the file using the path that the Camera plugin returns which requires the use of the File plugin.

Using the File plugin to Load an Image

This part is trickier and the source of much frustration among developers – during my search for documentation there was no single source that explained how this should work. I was left to putting the parts together from various sources as the “official” documentation didn’t directly explain how to do it. Anyway, I’ll do the explaining here within the code comments.

In short, these are the steps that result in a Base64 serialization of the image from which you can do whatever you like:

  1. Convert the image path to a file Entry Object
  2. Pass the FileEntry Object to a function that converts it to a File Object
  3. Pass the File Object to a FileReader to read the file
  4. Handle the response containing the image data

Here is all of the code:

   /**
    * This takes a file:// URI and creates a file entry object. The operation is asynch,
    * so the resulting fileEntry object is passed to the success callback.
    * @type {Function}
    * @name convertPath
    * @param {String} fileURI - the file:// path to the resource
    * @return {} Returns nothing
    */
    function convertPath(fileURI){
        window.resolveLocalFileSystemURL(
            fileURI,
            function(fileEntry){
                getFileSuccess(fileEntry);
            }
        );
    }

   /**
    * This starts the read process via the file entry object. This is asynch, so the file is passed to the success callback
    * @type {Function}
    * @name getFileSuccess
    * @param {Object} fileEntry - the file entry object
    * @return {} Returns nothing
    */
    function getFileSuccess(fileEntry){
        fileEntry.file(
            readFile, // success
            function(err){ // failure
                console.log('Failed to get file.',err);
            }
        );
    }

   /**
    * This creates a file reader using the file object that is passed to it.
    * Note how similar this is to programatically creating an image and loading data into it.
    * @type {Function}
    * @name readFile
    * @param {Object} file - file object
    * @return {} Returns nothing
    */
    function readFile(file){
    	console.log('got file...',file);
        var reader = new window.FileReader();
        reader.oneerror = function(e){
            console.log('FileReader Error: ',e.target.result);
        };
        reader.onloadend = function(fileObject) {
            console.log('we have the file:',fileObject);
            console.log('the image data is in fileObject.target._result');
        };
        reader.readAsDataURL(file);
    }

You can use the fileObject.target._result to populate the background of a div, for example:

$('#myDiv').css('background-image','url:(' + fileObject.target._result + ')');

Or insert it into a canvas:

   var image = new Image();
   var canvas = document.getElementById('canvas');
   var context = canvas.getContext('2d'); //retrieve context
   
   image.onload = function(){
      context.drawImage(this, 0, 0,_canvas.width, _canvas.height);
   }
   image.src = fileObject.target._result; // load the image data

It’s worth noting that of course you’ll need the appropriate styling for your DIVs if using the resulting image data as a background image. Also, if loading the data into a canvas your aspect ratio may be off – you’ll need to figure out how to scale the data to fit the canvas without distortion.