JavaScript

I'm working on a new pet project - called Risk... in the browser. Yes, I know, there are game portals out there which have it, and it has been done before. I just want to do it for myself, seems like a massive, but fun, project.

I found a great post on making a map, and it is definitely something I'll check out for the design phase of the project. I've started designing the JavaScript part of the application though, and along the way I thought I'd post about object oriented JavaScript and inheritance.

On his site, Crockford describes JavaScript as "... a class-free, object-oriented language, and as such, it uses prototypal inheritance instead of classical inheritance" - no better way to say it. So what does this mean for me when I'm designing a Risk game?

One example is in the design for the military. In classical Risk, we have 3 types of military units: infantry, cavalry, and artillery. In my initial design, I had them as a JSON object:

'armyUnits': {
  	'Infantry': 1,
  	'Cavalry': 5,
  	'Artillery': 10,
  },

My thought was to iterate over them, using the key/value pairs to create the pieces on the board, adding methods to the instances created. This will turn into soup. This structure actually lends itself to an inheritance-based model. So let's take a look at how that could be built.

First, we need a parent 'class'. Again, no real classes in JavaScript, just functions, so we can start with something basic like this:

var military = function() {
}

var unit = new military();

console.log(unit, typeof unit)
•> military {} "object"

Great, so now we have the parent class, and you can see we have instantiated it with the keyword 'new', and created an object from it. This is cool and all, but not very useful yet. Now we need to think about what attributes all of these units will share and can be inherited, and which attributes will be unit-specific, and providing private methods to get and set those.

So let's take movement, strength, color, and unitName for our attributes. Of these, probably only movement can be inherited, while the others are unit-specific. Additionally, we probably want one of the three to be the default, if no options are passed to the class at instantiation. Knowing all this, if we take another pass at our parent class, it might look something like this:

var military = function(uName) {
  //unit name - artillery, cavalry or infantry
  this.unitName = uName == undefined ? 'Infantry' : uName.toString(),
  this.movement = 1,
  this.color = 'gray',
  this.strength = 1;

}

Great, so now we can define a new unit and it's slightly more meaningful:

var a = new military();

console.log(a, a.strength);
military {unitName: "Infantry", movement: 1, color: "gray", strength: 1} 1
var b = new military('cavalry');
console.log(b, b.strength);
military {unitName: "cavalry", movement: 1, color: "gray", strength: 1} 1

So you can see we already have a problem. All of our units are inheriting, but they're inheriting everything the same, which is not what we want. A cavalry unit has a strength of 5, so let's fix that.

var military = function(uName) {

this.unitName = uName == undefined ? 'Infantry' : uName.toString(),
this.movement = 1,
this.color = 'gray',
this.strength = 1,
this.getStrength = function() {
  return this.strength;
  },
this.setStrength = function() {
  if(this.unitName == 'Cavalry'){
    return this.strength = 5;
  }
  else if(this.unitName == 'Artillery'){
    return this.strength = 10;
  }
  else {
    return this.strength;
  }
};


}

Right, now we have getter/setters for the strength attributes, and it's conditional based on the name of the unit we pass into the class. This all looks to be good, so now let's take a look at the inheritance piece.

We'll create unit-specific classes - like 'cavalry', and then there are a couple of ways to enable the inheritance. We can use apply(), which takes an array of arguments

var cavalry = function() {
  military.apply(this, ['Cavalry']);
}
var c = new cavalry();
console.log(c, typeof c);
•> cavalry {unitName: "Cavalry", movement: 1, color: "gray", strength: 5} "object"

Awesome! We have created a new military unit, of the type 'cavalry'. Notice our strength is 5, which is what we wanted for that type. Another way we can inherit from military is to use call(), probably better in our case, as it accepts a comma-separated list of strings for the arguments. That looks something like this:

var cavalry = function() {
  military.call(this, 'Cavalry'); //we can add additional args here, ', 'Bob', 'bail of hay', etc..' and it won't affect our class at present. they will just be lost
  this.strength = this.setStrength();
}
var c = new cavalry();
console.log(c, typeof c);
•> cavalry {unitName: "Cavalry", movement: 1, color: "gray", strength: 5}color: "gray"getStrength: ()movement: 1setStrength: ()strength: 5unitName: "Cavalry"__proto__: cavalry "object"

So that's fine too. We have a cavalry unit with a strength of 5. So probably the last thing we will want to do is create some instances of these classes and then have the ability to extend them. If I have the need to add a 'hungry' variable into the cavalry class for example, I want to be able to do so once and have it apply to all instances I've created.

So let's take a look at that.

var horse = new cavalry();
var superHorse = new cavalry();
// now to extend
superHorse.isHungry = function() { console.log('wheres my food?'); }
// call it
superHorse.isHungry();
•> wheres my food?

//call it
horse.isHungry();
Uncaught TypeError: horse.isHungry is not a function(…)

So that did and didn't work. It worked for the one object - superHorse, because isHungry() is only acting as a property added to a specific object (kind of a static method), rather than it being an extension of the cavalry constructor, so it could apply to all instances. So let's make that happen, with a simple change.

cavalry.prototype.isHungry = function() { console.log('I am HUUUUNGRY!'); }

And voila! By applying it to the prototype, it's now accessible to all instances, so let's see what happened to horse and superHorse:

horse.isHungry()
•> I am HUUUUNGRY!

superHorse.isHungry()
•> wheres my food?

Oooh, interesting, so horse object correctly received the method, but superHorse still shows the previous message. That's because it was previously applied as a method to superHorse, so the 'child' method is overriding the 'parent'. But if we look at the __proto__ property for it, we can see the constructor method in action:

superHorse.__proto__.isHungry()
•> I am HUUUUNGRY!

Speaking of hunger, I'm off to lunch, and then on to more of Risk.

 

 

 

I had a previous post on creating a CSS only multi-level flyout menu. I'm in the process of recovering that one, and will relink it when it's back up, but for now, a recent task (a.k.a take home test for an interview) asked me to create that very same menu, using a combo of JavaScript and CSS.

The idea of course, is to make it programmatic so it will scale to an infinite level of submenus. I find many of the tests we're asked to do during interviews involve some form of recursion - flatten a nested array of nested arrays, build minesweeper, and this one is no exception. So this was my solution for it. It's one way to do it - not the only way however.

I am including the original code in the snippets, though the running model below (is a bit wonky because of integration with WordPress I suspect), is a bit modified due to JavaScript scope conflicts and I added a div wrapper in the html to give sufficient height for the menu to display.

On to the design. My idea was to have an html element with a unique id to hang this menu off of.

HTML

So the html was pretty simple:

<ul id="dropdown_menu">
    </ul>

Like I said, simple. Now for the CSS.

CSS

The CSS needs to handle a few things - the styling of the unordered list and it's list items, plus any nested lists and list items. It also needs to deal with some state & interactivity - namely the concept of something being hidden vs. visible, and the mouseover, or hover, interaction animation.

Again, not overwhelmingly difficult - notice the craziness with the multiple nested uls though. That should probably be addressed for enhanced scalability.

html, body {
        padding: 0;
        margin: 0;
        font: normal 16px/135% sans-serif;
      }
      ul,
      ul li {
        list-style: none outside none;
        padding: 0;
        margin: 0;
      }

      .hidden {
        display: none;
      }

      ul li > ul {
        position: relative;
        top: -65px;
        right: -100%;
      }

      .menu-item {
        width: 200px;
        height: 70px;
        vertical-align: middle;
        line-height: 400%;
        text-align: center;
        background-color: lightblue;
        box-sizing: border-box;
        border: 1px solid black;
        opacity: 0.85;
      }
      .menu-item:hover {
        cursor: pointer;
        opacity: 1;
      }
      .menu-item > ul > .menu-item {
        background-color: violet;
      }
      .menu-item > ul > .menu-item > ul > .menu-item {
        background-color: lightgreen;
      }

      /* testing further levels with modified js object */
      .menu-item > ul > .menu-item > ul > .menu-item > ul > .menu-item {
        background-color: orange;
      }

Again, slight changes have been made to the working model below.

JavaScript

Finally the JS. This is where the bulk of the work is being done. I opted to use jQuery, just for convenience, though the entire thing can be done in native JS of course.

We're starting with a native JSON object. Originally, this was composed as 3 separate files - the js, css, and HTML file referencing the previous 2. Thus, the 'window' on the MENU variable so it was globally available.

window.MENU = [
      {
        'title': 'Item 1',
        'submenu': null,
      },
      {
        'title': 'Item 2',
        'submenu': [
          {
            'title': 'Sub 2 Sub1',
            'submenu': [
              {
                'title': 'Sub2 SubSub 1',
                'submenu': [
                  {
                    'title': 'Sub2 SubSubSub 1',
                    'submenu': null,
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        'title': 'Item 3',
        'submenu': [
          {
....

 

The most difficult thing about a task like this is probably structuring the design. I decided I wanted to keep it fairly simple. I'd start with variables for the HTML I wanted to insert into the parent, so an empty string will do for that, and something to hold the MENU object.

A couple of things about me - I like comments, and I try to be defensive in my coding, meaning it won't blow up if the unexpected happens. So this first declaration is just to return nothing basically, if for some reason the MENU object can't be parsed:

// defense ...
      if(MENU == null || MENU == undefined) {
        return false;
      }

Then the html variable is basically a document.getElementById('blah') ala jQuery.

//parent node to which will append further html
var html = $('#dropdown_menu');
var list = '';

 

Then I wanted a function which would slurp up the object and parse it, and a second function which would handle the action of creating lists or list items as needed. This first function is recursive, calling itself at each level as it descends:

function parseMenuBlock(data) {
        if(data.submenu == null) {
          list += createListItem(data.title, 1);
        }
        else {
          list += createListItem(data.title, 0);
          list += ('<ul class="hidden">');
          for(n in data.submenu) {
            parseMenuBlock(data.submenu[n]);
          }
          list += ('</ul>');
          list += closeListItem();
        }
      }

So this keeps appending onto the 'list' variable, the composed HTML string, as it's parsing the MENU object. It's looking at the submenu attribute and if its null, meaning it has no children, it just generates a list item for that block and stops. Otherwise, it creates the list item, and begins a new unordered list. Inside the unordered list, it recurses, calling itself to parse the next child level of the MENU object.

Obviously there's another method being called inside of here - the createListItem(). That I'm just passing the title attribute value to, so we can use that in the HTML title attribute, and a boolean flag. This flag decides whether we close the HTML for the list item ('</il>'), or leave it open (in the event there's a nested unordered list inside it).

// tackles the creation of a single list item element, close argument decides whether or not to close it or leave open for nested ul
function createListItem(data, close) {
  if(close == 1){
    return '<li class="menu-item" title="' + data + '">' + data + '</li>';
  }
  else {
    return '<li class="menu-item" title="' + data + '">' + data;
  }
}

function closeListItem() {
  return  '</li>';
}

 

Lastly, we need to kick the whole thing off by opening a loop to iterate over the MENU object, calling our ingestion method - parseMenuBlock(), and return the list value, and append it to the DOM object

for(i in MENU) {
        parseMenuBlock(MENU[i]);
      }
html.append(list);

 

The other anonymous functions in here deal with interactions, so just to take a quick look at those. This first one is called when the user's mouse moves into a menu item. If it can find a hidden child item, it reveals it, otherwise, do nothing.

$(document).on('mouseenter', 'li', function(e){
        //check if the element is hidden and remove 
        if($(this).children(':first').hasClass('hidden')) {
          $(this).children(':first').toggleClass('hidden');
        }
        //otherwise leave it alone...can be removed... left for readability
        else {
          return;
        }
      });

 

This next one sets a timeout to hide the child after the user moves the mouse away - a slight delay of 250ms in case the user is inaccurate with the mouse. Notice the t= $(this). That sets t to the object we're binding the mouse event to - in this case, an 'li'.

//bind mouseleave function to a delayed visibility toggle
      $(document).on('mouseleave', 'li', function(e) {
        var t = $(this);
        setTimeout(function(){
          t.children(':first').toggleClass('hidden');}, 250);// end setTimeout ...
      });

 

This last one is probably not desirable actually, but I was using for debugging and testing. It simply alerts the title attribute for the bound element. Notice the $(document).on(event, element, function()) syntax. This is necessary because at the time the page is loaded, none of these elements are present in the DOM, so the DOM has no knowledge of their existence. So we need to bind at the document level, to dynamic elements being added after the initial render of the DOM.

//bind click event to dynamically inserted elements
      $(document).on('click', 'li', function(e) {
        e.stopPropagation();
        alert($(this).attr('title'));
      });

 

And that's pretty much it. As I mentioned, below is a slightly wonky version of the menu in action. Enjoy, and feel free to comment.

Today's mission was randomizing dice rolls, for a given number of players at a table. The concept obviously comes in handy in a number of board games, or at a gambling table, and several simple dice-based games as well.

For the purposes of this demo, I decided on using a six-sided die, and we'll have any number of players, say 2-10. When designing this, I need methods to handle the actual action of rolling the dice, and then another method to handle the randomization, and any algorithm-related activity of the dice roll.

Let's start with the first one, we'll call it rollDice(). To keep it simple, I'm going to just pass it a number of dice to roll. We'll store the results in an array, and return the array of values.

var rollDice = function(numDice) {
    var roll=[];
    //do something numDice times ...
    console.log('roll', roll);
    return roll;
  };

Great, we're off to a rolling start. That's returning an empty array, which is what we want. Once we push values in there, it will be populated.

Next up is our second function, the randomizer, and I'm going to call that randomizeDiceRoll(). So for that one, to keep it simple, I'll define the dice configuration within the method, but this would be a perfect situation for an external config setting of some kind - a global object, a call() implementation, or a Die class which holds config for multiple types and shapes of dies. This one will simply randomize the outcome based on the number of sides in the die.

var randomizeDiceRoll = function() {
    var diceSides = [1,2,3,4,5,6];
      return Math.floor((Math.random() * diceSides[diceSides.length-1]) + 1);
 };

This we can test a few times in console and see it execute, and it appears to be handling the outcome fairly randomly, so we're good here. Let's move on to the last step, which is plugging this into our previous method.

var rollDice = function(numDice) {
    var roll=[];
    for(var i=0;i<numDice;i++) {
      roll.push( randomizeDiceRoll() );
    }

    console.log('roll', roll);
    return roll;
  };

Testing that in console, I can see I'm getting 3 rolls back for 3 players, 2 for 2 players, etc. So this is working as well.

rollDice(3)
•>  roll [3, 5, 2]
[3, 5, 2]
rollDice(2)
•>  roll [1, 2]
[1, 2]
rollDice(8)
•>  roll [1,2,2,5,4,6,1,1]
[1, 2, 2, 5, 4, 6, 1, 1]

So we hit a snag. What happens when we have a tie? Well, we can just force everyone to re-roll, adding a new boolean variable - tie, along with some recursion to our rollDice() method. Something like this:

var tie = false;
 
roll.forEach(function(n, idx) {
  if(roll[idx] == roll[idx+1]) {
    tie = true;
  }
});
if(tie == true) {
  rollDice(numDice);
}

So this works - I rolled for 3, got a tie, and it re-rolled, eliminating the tie:

rollDice(3);
roll [3, 3, 5]
roll [2, 3, 1]

Tie problem solved but now we have an additional problem. If you look at those results, the last item in the first array originally had the highest score, placing them in first position to start a game, or possibly win a battle. After re-rolling though, they are actually in last, unless we're using the numbers in reverse order, either way, their fortune has been flipped on its head. So let's fix that

var rollDice = function(numDice) {
    var roll=[],
        diceSides = [1,2,3,4,5,6];
    for(var i=0;i<numDice;i++) {
      roll.push( randomizeDiceRoll(diceSides) );
    }

    console.log('roll', roll);
  
    checkForTies(roll, diceSides);
};
  var randomizeDiceRoll = function(diceSides) {
    //var diceSides = [1,2,3,4,5,6];
    return Math.floor((Math.random() * diceSides[diceSides.length-1]) + 1);
  };



var checkForTies = function(roll, diceSides) {
  if(roll.length > diceSides.length) {
    return roll;
  }
  else {
    roll.forEach(
    function(n, idx) {
      if(roll.indexOf(n) != roll.lastIndexOf(n)) {
        tie = true;
        roll[roll.indexOf(n)] = randomizeDiceRoll(diceSides);
        roll[roll.lastIndexOf(n)] = randomizeDiceRoll(diceSides);
        checkForTies(roll, diceSides);
      }
  });
  return roll;
  }
  
}

rollDice(6); //should end with unique values for each array element
rollDice(7); //there will be duplicate elements

OK, so you can see we've restructured things a bit. We're now passing the diceSides to each of the child functions (not ideal, but it works for now), and we check for a tie. If the number of sides of the dice is greater than or equal to the number of players rolling, we can sort out the tie - if not, we just return the original array of values, as it's mathematically impossible for there NOT to be a tie (ex: 7 players with a 6-sided die).

For now, we have a solution for our randomized dice roll. Some enhancements would be a config flag to say whether or not to trigger the tie-resolving method (you may want it in certain cases, but not in others), and a cleaner implementation architecturally. So I'll work on those soon.

Thanks for reading - feedback welcome.