Matching Pairs for an AngularJS Gallery

Recently I was working on a gallery using AngularJS for some upcoming projects and one of the requirements for this gallery was for it to self recognize pairs of images based upon orientation.

To begin I built a basic Angular App and and within the main controller I added an array of objects that would represent each image and its meta data.

Note: Any array of objects would work, I just happen to be using AngularJS because its awesome.
$scope.images = [
    {
        title: 'Image number 1',
        description: '',
        src: 'images/landscape.jpg',
        orientation: 'landscape',
        class: null
    },
    {
        title: 'Image number 2',
        description: '',
        src: 'images/landscape.jpg',
        orientation: 'landscape',
        class: null
    },
    {
        title: 'Image number 3',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 4',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 5',
        description: '',
        src: 'images/landscape.jpg',
        orientation: 'landscape',
        likes: 0,
        class: null
    },
    {
        title: 'Image number 6',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 7',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 8',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 9',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    },
    {
        title: 'Image number 10',
        description: '',
        src: 'images/portrait.jpg',
        orientation: 'portrait',
        class: null
    }
];

After I set my array of data the way I wanted it. I then proceeded to work on the logic that would add a class to matched pairs.

The first thing I needed to do was to ask myself in plain English a simple question.

Does the orientation of this image match the orientation of the next image?

Translated to code that would results in something like this.

var o = $scope.images; // array of objects
for(var i = 0; i < o.length; i++) {
    if(o[i + 1] !== undefined) {
        if ((o[i].orientation === o[i + 1].orientation)) {
            console.log(true);
        } else {
            console.log(false);
        }
    }
}

Breaking it Down

First I define a variable to hold the object array. var o just makes the code simpler and easier to write.

Next I defined a simple for loop that will loop through the array of objects.

for(var i = 0; i < o.length; i++) {
    // code to be executed    
}

Inside the for loop we ask our question in a language the computer can interpret with an if statement.

if(o[i + 1] !== undefined) {
    if ((o[i].orientation === o[i + 1].orientation)) {
        console.log(true);
    } else {
        console.log(false);
    }
}

You might have noticed that we have two if statements, that is because in our if/else statement we are comparing an image with the next image in the index. The problem is JavaScript will throw an error like this:

Error: o[(i + 1)] is undefined

This error occurs on the final iteration of the loop because we are referencing something that doesn’t exist. Our loop is comparing current image to current image + 1 and once you get to the last image, there is no (+1) to reference.

To prevent this we end the loop when current image +1 is undefined.

If our first if statement is true we can proceed to execute the if/else statement which then checks for equality.

Check the table below to see the outcome of the loop.

Image Orientation Equal to next Image?
landscape true
landscape false
portrait true
portrait false
landscape false
portrait true
portrait true
portrait true
portrait true
landscape false

Next we need to add our class to the objects that are true.

if ((o[i].orientation === o[i + 1].orientation)) {
    o[i].class = " paired";
    o[i + 1].class = " paired";
}

Here we are adding our class to the matched objects but there is a slight problem.

If you have 3 items that are the same orientation then the 3rd item will also have the additional class added which is not what we want because the 3rd item is not match to the next item. The solution was to simply skip the paired object because once Image A is matched with Image B, there is no need to Check if Image B matches Image C.

if ((o[i].orientation === o[i + 1].orientation)) {
    o[i].class = " paired";
    o[i + 1].class = " paired";
    i = i + 1; // skip the paired objects
}

Putting it Altogether

The complete function loop looks as follows:

var o = $scope.images;
for(var i = 0; i < o.length; i++) {
    if(o[i + 1] !== undefined) {
        if ((o[i].orientation === o[i + 1].orientation)) {
            o[i].class = " paired";
            o[i + 1].class = " paired";
            i = i + 1; // skip the paired object
        }
    }
}

Let me know if you think this can be improved or shortened in any way. The full example with AngularJS can be found below.

See the Pen Matching Image Pairs With AngularJS and JavaScript by Matthew Horne (@horne3754sg) on CodePen.0

In Category: AngularJS