Jasmine Tutorial: Unit Testing Promises In Services

Leave a comment Standard

So recently I’ve been doing a lot of Angular unit tests with Jasmine and Grunt. I have to say, testing promises is extremely frustrating and most of the examples I found out there either 1) didn’t work or 2) wouldn’t allow you to test content in a then block if you had multiple chained promises, or if you had a promise being called from and returned from another service. After many hours of frustrating trial and errors I found a solution I’m happy with so I want to share.

Let’s assume this is your controller:

'use strict';

angular.module('myModule').controller('myCtrl', ['$scope', 'api',
function ($scope, $api) {

  $scope.data = null;
  $scope.message = null;

  /**
  * Load some data from the API service
  * @return boolean
  **/
  $scope.loadData = function () {

    var config = {
      method: 'GET',
      url: 'http://api.domain.com/someRESTfulEndpoint',
      headers: {'Content-Type': 'application/json'},
      data: null
    };

    return $api.load(config).then(function (request) {
      if (request) {
        $scope.message = 'Your data was successfully loaded';
        $scope.data = request.response;
        return true;
      } else {
        $scope.message = 'The API service failed';
      }
      return false;
    });
  };
}]);

And here is the service making your API calls:

'use strict';

angular.module('myModule').service('api', ['$rootScope', '$http',
  function ($rootScope, $http) {

    /**
    * Makes the $http request given the proper configuration options
    * @param Object configruation for the $http request
    * @return Object $http promise that resolves to request payload or error
    **/
    this.load = function (options) {
      return $http({
        method: options.method || 'GET',
        url: options.url || 'http://api.domain.com/someDefaultEndpoint',
        headers: options.headers || null,
        data: options.data || null
      }).then(
        function (request) {
          //we got a response back, return just the API payload data
          if (request.status === 200 && request.data) {
            return request.data;
          } else {
            return {
              results: false,
              message: 'API request error',
              response: request
           };
         }
       }
     );
   };
}]);

Finally, this is your working unit tests:

'use strict';

describe('testing myModule', function () {

  beforeEach(module('myModule'));

  var $controller, $rootScope, $scope, $api, $httpBackend, $q;

  beforeEach(
    inject(function (_$controller_, _$rootScope_, api, _$httpBackend_, _$q_) {
      $controller = _$controller_;
      $rootScope = _$rootScope_;
      $httpBackend = _$httpBackend_;
      $q = _$q_;
      $api = api;
      $scope = $rootScope.$new();

      $httpBackend.when('GET').respond('test http GET call');
      $httpBackend.when('POST').respond('test http POST call');

      $controller('myCtrl', {
        $scope: $scope,
        $api: $api
      });
    })
  );

  it('has a $scope.loadData() function', function() {

    var testConfig = {
      method: 'POST',
      url: 'http://api.domain.com/endpoint',
      data: { some: 'data'}
    };

    var fakeData = { data: 'is fake' };

    //we spy on the API service and also return a fake promise call
    spyOn($api, 'load').and.callFake(
      function() {
        var deferred = $q.defer();
        deferred.resolve({result: true, response: fakeData});
        return deferred.promise;
      });
    });

    $scope.loadData(testConfig); //call the function we're testing in the controller
    $scope.$apply(); //we have to call this so Angular will try and resolve the promise
    expect($api.load.calls.count()).toEqual(1); //make sure it's called the api service
    expect($scope.message).toEqual('Your data was successfully loaded');
    expect($scope.data).toEqual(fakeData);
  });

  it('returns an error if the API fails', function() {

    var testConfig = {
      method: 'POST',
      url: 'http://api.domain.com/endpoint',
      data: { some: 'data'}
    };

    spyOn($api, 'load').and.callFake(
      function() {
        var deferred = $q.defer();
        deferred.resolve({
        result: false,
        message: 'api error'
      });
      return deferred.promise;
    });

    $scope.loadData(testConfig);
    $scope.$apply();
    expect($scope.message).toEqual('api error');
    expect($api.load.calls.count()).toEqual(1);
  });
});

 

HTML5 Tutorial: Simple Music Player

Leave a comment Standard

So this is a pretty simple example but I was playing around with flash for my chat room and this was byproduct of that experimentation. It’s funny how even when I’m trying to learn something new I do my best to make it useful for other situations which is a good habit to get into if you’re not doing it already.

Try out the working demo or download the code

Caveats

This will only work on a browser that is HTML5 compliant and has support for audio. That means older browsers and most versions of Internet Explorer are not supported. Firefox, Chrome and Opera work as well as the newest versions of Internet Explorer.

The Audio Tag

If you’re familiar with HTML then most of the index file below will look pretty familiar. The thing you really have to pay attention to is the new <audio> tag. It looks like this:

<audio id="rock" src="http://whiteoakstables.net/chat/audio/rock.wav" preload="auto"></audio>

You may notice that it looks a whole lot like a hyperlink with the src that defines the location of the file. Preload is an optional attribute, it tells your browser to start downloading the file as soon as the DOM, or page elements, have finished loading. In addition to setting preload to true I’ve added an ID attribute so I can reference this particular song in my music player.

The Index File

<!DOCTYPE html>
<html>
 <head>
 <script data-require="jquery@*" data-semver="2.1.3" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
 <link data-require="bootstrap-glyphicons@*" data-semver="3.2.1" rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/img/glyphicons-halflings.png" />
 <link data-require="bootstrap@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
 <script data-require="bootstrap@*" data-semver="3.3.1" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
 <link rel="stylesheet" href="style.css" />
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="text-center">Bootstrap HTML5 Music Player</h1>
 <audio id="rock" src="http://whiteoakstables.net/chat/audio/rock.wav" preload="auto"></audio>
 <audio id="blues" src="http://whiteoakstables.net/chat/audio/blues.wav" preload="auto"></audio>
 <audio id="electronica" src="http://whiteoakstables.net/chat/audio/electronica.wav" preload="auto"></audio>
 <audio id="classical" src="http://whiteoakstables.net/chat/audio/classical.wav" preload="auto"></audio>
 <audio id="latin" src="http://whiteoakstables.net/chat/audio/latin.wav" preload="auto"></audio>
 <audio id="indie" src="http://whiteoakstables.net/chat/audio/indie.wav" preload="auto"></audio>
 <div class="audiocontroller">
 <i class="audio-logo glyphicon glyphicon-headphones"></i>
 <i class="dynamiclink glyphicon glyphicon-play" id="play"></i></a>
 <i class="dynamiclink glyphicon glyphicon-pause" id="pause"></i>
 <select id="currentTrack">
 <option value="rock">Rock</option>
 <option value="blues">Blues</option>
 <option value="electronica">Electronica</option>
 <option value="classical">Classical</option>
 <option value="latin">Latin</option>
 <option value="indie">Indie</option>
 </select>
 <i class="dynamiclink glyphicon glyphicon-stop" id="stop"></i>
 </div>
 <p class="text-center">
 <a id="author" href="http://design1online.com" target="_blank">by Design1online.com, LLC</a>
 </p>
 </body>
</html>

The Javascript File

//Simple HTML5 Music Player by design1online.com, LLC

var currentTrack = null;
var paused = false;

$(document).ready(function() {
 currentTrack = $('#currentTrack').val();
 
 $("#play").click(function() { play(); });
 $("#stop").click(function() { stop(); });
 $("#pause").click(function() { pause(); });
});

function play() {

 //set the track back to the beginning
 if (!paused) {
 stop();
 currentTrack = $('#currentTrack').val();
 
 //make sure track starts from the begining each time
 document.getElementById(currentTrack).load();
 }

 //play the track
 document.getElementById(currentTrack).play();
}
 
//stop playing the current track
function stop() {
 if (currentTrack) {
 document.getElementById(currentTrack).pause();
 paused = false;
 }
}

//stop the track but don't go back to the beginning
function pause() {
 paused = true;
 document.getElementById(currentTrack).pause();
}

How It All Works

So now let’s talk about the javascript file. At first glance it looks relatively simple because it is! When you want to select a track you simply ask for it using getElementById and then you tell it to play or to pause. One thing that is sadly lacking is a stop() functionality. With html5 you can only pause an audio file — which does stop the playback but it also keeps the audio file at the same position as when you called pause on it. This means that if you wanted to play the audio file from the beginning again and you just called play() it would continue playing from where it left off. That’s where the load() function comes into play — this will tell the audio track to start loading if it wasn’t set to preload and it will reset the track back to the beginning.

The only other thing to mention is the currentTrack variable. I use this to keep track of which of the songs is currently selected and the user wasn’t to listen to.

jQuery Tutorial: Hide or Display a Field Based on the Value of Another Field

Comments 10 Standard

Gah I know it’s been a while since I’ve posted something and I try to post every month but I’ve been busy programming games for myself and my clients (which is a good thing!). But here’s some yummy coding snippets to make your life easier.

Creating the Form

For this example let’s assume that we have a game which requires parental emails or parental permission to play if the member who is signing up is under 13 years of age* (good ole COPPA). Create an php file with the following contents:

<html>
<head>
    <title>Test Hide/Show Fields</title>
    <script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
    <script language="javascript" type="text/javascript" src="showhide.js"></script>
</head>
<body>
    <?php
        //this will show you the values in the form the data when you hit the submit button
        if ($_POST) {
            echo "Form was submitted, here are the form values: <pre>";
            print_r($_POST);
            echo "</pre>";
        }
    ?>
    <form method="POST">
        <p>Name: <input type="text" name="player_name" /></p>
        <p>Email: <input type="text" name="player_email" /></p>
        <p>Age: 
             <select id="age" name="age">
             <?php
                  //sorry but if you're over 30 you're too old to join, lol
                  for ($age = 6; $age <= 30; $age++)
                       echo "<option value=\"$age\">$age</option>
             ?>
             </select>
        </p>
        <div id="parentPermission">
                <p>Parent's Name: <input type="text" name="parent_name" /></p>
                <p>Parent's Email: <input type="text" name="parent_email" /></p>
                <p>You must have parental permission before you can play.</p>
        </div>
        <p align="center"><input type="submit" value="Join Game!" /></p> 
 </form>
</body>
</html>

Writing the jQuery Code

Now all that’s left is to write the code that will show (or hide) the fields we want to display when the user has selected a specific value in our selection drop down list. Create a file called showhide.js and save it to the same location as the form you created in the previous step.

/**
* File: js/showhide.js
* Author: design1online.com, LLC
* Purpose: toggle the visibility of fields depending on the value of another field
**/
$(document).ready(function() {
    toggleFields(); //call this first so we start out with the correct visibility depending on the selected form values
   //this will call our toggleFields function every time the selection value of our underAge field changes
    $("#age").change(function() { toggleFields(); });

});
//this toggles the visibility of our parent permission fields depending on the current selected value of the underAge field
function toggleFields()
{
    if ($("#age").val() < 13)
        $("#parentPermission").show();
    else
        $("#parentPermission").hide();
}

Summary

Now every time you select an age below 13 you will see the parent permission form fields displayed. If you select an age 13 or older the parent permission fields will disappear. This is useful if you have conditional data you want to collect based on a specific value or selection response. Hope it helps!

*Note

The age field in this example is just to show you how you can show/hide fields depending on the value selected. If you intend to store the age of a person in your database you need to store their date of birth since age changes every year.

Demo and working code

Try our JSFiddle demo to see this code in action!

PHP Tutorial: 2 Player Tic-Tac-Toe Game (no database required)

Comments 11 Standard

In the first part of my games tutorial series we created a PHP Hangman game and then in the second installment we converted Hangman to use AJAX. Now it’s time to follow the same approach, only with Tic Tac Toe.

The Beauty of Classes

One of the things I like about classes is how easy it is to use and reuse them without writing a lot of code to go with it. So to start our Tic Tac Toe game we’re going to copy all the files from our original PHP Hangman game. We won’t need to change anything in the game class but we will need to make some modifications to the other class. First we’ll remove all references to letters, then we’ll remove any functions we don’t need anymore. Finally we change the main functions to display a Tic Tac Toe board instead of our hangman pictures, and finish it off by changing the logic behind how you win a game and how you make a move in the game.

Our new Tic Tac Toe game will need a player (or turn) variable so we know whose turn it is to place an X or an O. Then we’re going to add another variable to keep track of how many guesses have been made — that makes it easier to figure out if there’s a tie game instead of looping through the whole array each time someone guesses. We’ll also need a new array called Board to store all of the X and O’s placed on our game board.

The Index File

We’re going to keep things as short and easy as possible. The only changes we have to make to our index file is to load a tic tac toe game instead of a hangman game. Then we change the page title and we’re nearly done!

<?php
/***
* File: index.php
* Author: design1online.com, LLC
* Created: 1.31.2012
* License: Public GNU
* Description: PHP/MySQL Version of 2 Player Tic Tac Toe
***/
require_once('oop/class.game.php');
require_once('oop/class.tictactoe.php');

//this will store their information as they refresh the page
session_start();

//if they haven't started a game yet let's load one
if (!$_SESSION['game']['tictactoe'])
    $_SESSION['game']['tictactoe'] = new tictactoe();

?>
<html>
    <head>
        <title>Tic Tac Toe</title>
        <link rel="stylesheet" type="text/css" href="inc/style.css" />
    </head>
    <body>
        <div id="content">
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
        <h2>Let's Play Tic Tac Toe!</h2>
        <?php
            $_SESSION['game']['tictactoe']->playGame($_POST);
        ?>
        </form>
        </div>
    </body>
</html>

The Updated Class File

Here’s the class file with our updated game logic. Can you see how similar it is to our hangman class file? What’s changed and what looks the same?

<?php
/***
* File: oop/class.tictactoe.php
* Author: design1online.com, LLC
* Created: 1.31.2012
* License: Public GNU
* Description: tic tac toe game
***/

class tictactoe extends game
{
    var $player = "X";            //whose turn is
    var $board = array();        //the tic tac toe board
    var $totalMoves = 0;        //how many moves have been made so far        

    /**
    * Purpose: default constructor
    * Preconditions: none
    * Postconditions: parent object started
    **/
    function tictactoe()
    {
        /**
        * instantiate the parent game class so this class
        * inherits all of the game class's attributes 
        * and methods
        **/
        game::start();
    }

    /**
    * Purpose: start a new tic tac toe game
    * Preconditions: maximum number of guesses
    * Postconditions: game is ready to be displayed
    **/
    function newGame()
    {
        //setup the game
        $this->start();

        //reset the player
        $this->player = "X";
        $this->totalMoves = 0;

        //clear out the board
        $this->board = array();
    }

    /**
    * Purpose: run the game until it's tied or someone has won
    * Preconditions: all $_POST content
    * Postconditions: game is in play
    **/
    function playGame($postdata)
    {
        if (!$this->isOver() && $postdata['move'])
            $this->move($postdata);

        //player pressed the button to start a new game
        if ($_POST['newgame'])
            $this->newGame();

        //display the game
        $this->displayGame();
    }

    /**
    * Purpose: display the game interface
    * Preconditions: none
    * Postconditions: start a game or keep playing the current game
    **/
    function displayGame()
    {

        //while the game isn't over
        if (!$this->isOver())
        {
            echo "<div id=\"board\">";

            for ($x = 0; $x < 3; $x++)
            {
                for ($y = 0; $y < 3; $y++)
                {
                    echo "<div class=\"board_cell\">";

                    //check to see if that position is already filled
                    if ($this->board[$x][$y])
                        echo "<img src=\"images/{$this->board[$x][$y]}.jpg\" alt=\"{$this->board[$x][$y]}\" title=\"{$this->board[$x][$y]}\" />";
                    else
                    {
                        //let them choose to put an x or o there
                        echo "<select name=\"{$x}_{$y}\">
                                <option value=\"\"></option>
                                <option value=\"{$this->player}\">{$this->player}</option>
                            </select>";
                    }

                    echo "</div>";
                }

                echo "<div class=\"break\"></div>";
            }

            echo "
                <p align=\"center\">
                    <input type=\"submit\" name=\"move\" value=\"Take Turn\" /><br/>
                    <b>It's player {$this->player}'s turn.</b></p>
            </div>";
        }
        else
        {

            //someone won the game or there was a tie
            if ($this->isOver() != "Tie")
                echo successMsg("Congratulations player " . $this->isOver() . ", you've won the game!");
            else if ($this->isOver() == "Tie")
                echo errorMsg("Whoops! Looks like you've had a tie game. Want to try again?");

            session_destroy(); 

            echo "<p align=\"center\"><input type=\"submit\" name=\"newgame\" value=\"New Game\" /></p>";
        }
    }

    /**
    * Purpose: trying to place an X or O on the board
    * Preconditions: the position they want to make their move
    * Postconditions: the game data is updated
    **/
    function move($postdata)
    {            

        if ($this->isOver())
            return;

        //remove duplicate entries on the board    
        $postdata = array_unique($postdata);

        foreach ($postdata as $key => $value)
        {
            if ($value == $this->player)
            {    
                //update the board in that position with the player's X or O 
                $coords = explode("_", $key);
                $this->board[$coords[0]][$coords[1]] = $this->player;

                //change the turn to the next player
                if ($this->player == "X")
                    $this->player = "O";
                else
                    $this->player = "X";

                $this->totalMoves++;
            }
        }

        if ($this->isOver())
            return;
    }

    /**
    * Purpose: check for a winner
    * Preconditions: none
    * Postconditions: return the winner if found
    **/
    function isOver()
    {

        //top row
        if ($this->board[0][0] && $this->board[0][0] == $this->board[0][1] && $this->board[0][1] == $this->board[0][2])
            return $this->board[0][0];

        //middle row
        if ($this->board[1][0] && $this->board[1][0] == $this->board[1][1] && $this->board[1][1] == $this->board[1][2])
            return $this->board[1][0];

        //bottom row
        if ($this->board[2][0] && $this->board[2][0] == $this->board[2][1] && $this->board[2][1] == $this->board[2][2])
            return $this->board[2][0];

        //first column
        if ($this->board[0][0] && $this->board[0][0] == $this->board[1][0] && $this->board[1][0] == $this->board[2][0])
            return $this->board[0][0];

        //second column
        if ($this->board[0][1] && $this->board[0][1] == $this->board[1][1] && $this->board[1][1] == $this->board[2][1])
            return $this->board[0][1];

        //third column
        if ($this->board[0][2] && $this->board[0][2] == $this->board[1][2] && $this->board[1][2] == $this->board[2][2])
            return $this->board[0][2];

        //diagonal 1
        if ($this->board[0][0] && $this->board[0][0] == $this->board[1][1] && $this->board[1][1] == $this->board[2][2])
            return $this->board[0][0];

        //diagonal 2
        if ($this->board[0][2] && $this->board[0][2] == $this->board[1][1] && $this->board[1][1] == $this->board[2][0])
            return $this->board[0][2];

        if ($this->totalMoves >= 9)
            return "Tie";
    }
}

Try the working example or Download the source code.

Learn how to create an AJAX version of this game.

AJAX Tutorial: Hangman Game (no database required)

Comments 6 Standard

Last year I made an PHP tutorial of an OOP Hangman game (no database required) for a Siminar I spoke at. This year as a part of my new Game Tutorial Series I’m adding a new tutorial to my collection. This tutorial will teach you how to modify the PHP hangman game we created and add some AJAX to it using jQuery so we don’t have to refresh the page every time we guess a new letter or start a new game. If you haven’t followed along with the original PHP tutorial I would strongly suggest you do as I won’t touch on anything introduced in the last one.

Download the Working Source Code
.zip archive

Getting jQuery

First thing is first we’ll need to get the jQuery library before we start updating any code. For those of you that don’t know, jQuery is code library that makes doing JavaScript quick and pretty painless. You can download or link to a copy offered on a Content Delivery Network (CDN) like Google Code. Personally I recommend downloading a copy if you’re going to post this game on a high traffic/visibility website. Sometimes if you link to a copy of jQuery on a CDN your site can experience lag and/or delays if the CDN is slow and your game won’t work at all if the CDN is down. On the other hand if you have a small website or limited space to store your files then there’s no need to download a copy of jQuery, linking to it is a better option. In this tutorial I’ve downloaded and included the jQuery file in the js folder of the .zip archive.

Setting Up For AJAX

Because we want our game to display using AJAX we need to create a new JavaScript file called hangman.js. This is what we’ll use to make all of our AJAX calls and respond to the player’s input.

Now that we have two JavaScript files we have to update our index.php file so it knows both of those JavaScript files are necessary to run the game. In the <head> tag, under the link to our stylesheet, we add two lines of code that tell our browser to load our JavaScript files:

<head>
        <title>Hangman</title>
        <link rel="stylesheet" type="text/css" href="inc/style.css" />
        <script language="Javascript" src="js/jquery-1.7.1.min.js"></script>
        <script language="Javascript" src="js/hangman.js"></script>
</head>

We also need to remove our $_SESSION[‘game’][‘hangman’] check from the top of our index file. Our AJAX calls will be running the game so it’s no longer necessary here. However we leave the session_start() at the top of the page so that if the player accidentally refreshes the page they don’t loose the game they had in progress.

Next we remove the code  inside of our <div id=”content”> and set that aside for later because we’ll need to use parts of it in our AJAX. In it’s place we’re going to enter a loading message. This is what the page will display before the AJAX calls have finished processing.

<body>
        <div id="content">
        <center>Loading Hangman.... please wait.</center>
        </div>
</body>

Writing the Hangman.js File

Now it’s time to jump into jQuery and AJAX.

$(document).ready(function() {

    //start the game when the page loads
    playGame();

});

jQuery uses a special function to check when the page has finished loading. Anything you put inside of this function will run as soon as the page is loaded, or in response to something someone has done on the page, like mouse clicks or using the keyboard. For this tutorial all we need it to do is call our AJAX function that will load and display the game to the content div on our index.php file.

/***
* Purpose: play hangman
* Preconditions: none
* Postconditions: new game has started or existing game is in play
***/
function playGame()
{
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame'},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

Inside of our playGame() function we use AJAX to tell the browser to load our ajax file and send it some data (the type of action we’re doing, whether or not to start a new game, the letter the player guessed). Then we use a success callback function to load the results of our ajax call onto the page. A callback function is a function that runs as a result of being called by another process. In this case our callback function, success,  is loading the data we’ve retrieved through AJAX and putting it into the content div’s HTML property.

/***
* Purpose: guess a letter
* Preconditions: none
* Postconditions: game status updated
***/
function guessLetter()
{
    //make sure they've entered something into the box
    if (!$("#letter").val()) {
        alert("You must enter a letter.");
        return;
    }

    //check to make sure they've entered a letter
    if (!isLetter($("#letter").val())) {
        alert("This is not a letter. Please enter a letter.");

        //clear out the value in the input box
        $("#letter").val("");
        return;
    }

    //if it was a letter then submit the guess
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame', letter: $("#letter").val()},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

/***
* Purpose: check to see if a value is a letter
* Preconditions: value to check
* Postconditions: returns true if this is a letter
***/
function isLetter(value)
{
    var lettersOnly = /^[a-zA-Z]+$/;

    //check to make sure there are no numbers and the value isn't more than 1 characters
    if(value.match(lettersOnly) && value.length == 1)
        return true;

    //otherwise this isn't a letter
    return false;
}

If we want to respond to someone trying to guess a letter we use a fairly similar process. Our guessLetter function checks to make sure the player has entered a value into our letter input box, then checks to make sure the value inside of it is really a letter, and finally uses an AJAX call to update the game by passing it the letter entered.

/***
* Purpose: start a brand new game
* Preconditions: none
* Postconditions: new game has started
***/
function newGame()
{
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame', newgame: true},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

The last piece of our ajax file is the newGame function. When the game is over we want to make sure we use AJAX to update the game state and then refresh the page to a new game.

Writing the AJAX File

Now that our JavaScript file will send AJAX requests we need to write the file on the other end of the request — the file that responds to the data we’re sending it. Create a new folder and name is ajax. Inside of it make an index.php file. Inside of the file put the following:

<?php
//include the required OOP files
require_once('../oop/class.game.php');
require_once('../oop/class.hangman.php');

//this will keep the game data as they make a new ajax request
session_start();

//respond to AJAX requests
echo doAction($_GET);

function doAction($getdata)
{
    switch ($_GET['type'])
    {
        case "playGame":
            return playGame($getdata);
        default:
            return "Invalid option selected.";
    }
}

/***
* Purpose: Display and play the game
* Preconditions: a game exists
* Postconditions: the current game is displayed to the screen
***/
function playGame($getdata)
{    
    //if they haven't started a game yet let's load one
    if (!$_SESSION['game']['hangman'])
        $_SESSION['game']['hangman'] = new hangman();

    echo "<h2>Let's Play Hangman!</h2>";
    $_SESSION['game']['hangman']->playGame($getdata);
}

In this file we have two functions, doAction and playGame. Both functions take the $_GET data sent by our AJAX calls and do various things depending on the data sent to them. doAction is run every time this ajax file loads. It decides which function it needs to call, depending on the type we’ve sent it, and then returns the result to the screen.

Now pull up that code I had you set aside earlier. We’re going to move that into our playGame function with a few adjustments. We no longer need the <form> tags around our game data. In addition instead of sending $_POST data to our hangman object we’re now sending $_GET data.  The $_GET data contains the information we were previously posting from the <form> tags. Since AJAX is refreshing what appears inside of our content div there’s no reason to use our <form> and $_POST variables anymore.

Last But Not Least

We’re almost done! Before we can view our handy work we need to open our hangman OOP file. Anywhere we had a $_POST statement we need to change that to a $_GET since we’re no longer using the $_POST variable.

Finally,  we need to update our new game and guess buttons so they run the newGame and playGame javascript functions we wrote earlier:

<input type=\"text\" name=\"letter\" value=\"\" size=\"2\" maxlength=\"1\" id=\"letter\" />
<input type=\"submit\" name=\"submit\" value=\"Guess\" onClick=\"guessLetter()\" />

<div id=\"start_game\"><input type=\"submit\" name=\"newgame\" value=\"New Game\" onClick=\"newGame()\" /></div>"

Conclusion

Well, that wasn’t so hard now was it? Try the working version to see what it’s like! In this tutorial we took our existing PHP Hangman game and modified it to use AJAX. If you play the game you’ll see the page no longer has to refresh each time you click the guess letter button or the new game button. To accomplish this we first downloaded jQuery, created a JavaScript file to make AJAX requests, wrote a file to return a response to our AJAX requests, and then updated our hangman class to use $_GET and our new JavaScript functions.

1 Code Snippet a Month Challenge

Comments 2 Standard

This was initially designed as a way for me to challenge myself in creating a code snippet every month that would be useful to online game development. I did pretty well at first but fell behind in the end as life caught up to me. Hopefully you’ll find some of these useful!

Language(s) Name Description
PHP Format Dates Take country into consideration when formatting dates.
PHP Filename From Domain Path If you have http://domain.com/contacts.php this function returns contacts.php
C++ C++ Mysql Database Class Connect to a MySQL database from a C++ application using this nifty class. You’ll need both the .cpp and .h files
PHP Mixing HEX Colors Take two color HEX values and combine them to get their intermediate color. For instance white (#FFFFFF) + black (#000000) = gray (#80000)
MSSQL Remove All But 1 Duplicate Records For those times when you forget to set a key, or set the wrong key — duplicate records are a pain. Here’s an easy way to remove them all in MSSQL.
PHP/Cpanel Dynamically Create an Email name@yourdomain.com Dynamically create an email account for members as they sign up. This assumes you have cPanel already installed and that you have shell exec rights.
PHP Word Functions For all you word puzzle aficionados.
PHP Dynamically Colored Images, Overlays & Transparencies For all those neopet wanna be games out there. Let your members dynamically color their pets any way they like. This requires that you have php compiled with the GD library.
PHP & MySQL PHP Class File Generator Quick and easy php class file generator. Enter your DB connection settings (or save them in an include file), then select the table you want to create the class for. The generator will generate a .php file for download that has the shell of your OOP class.

HTML Tutorial: A Crash Course In Tables

Leave a comment Standard

It amazes me how many people proclaim to be programmers but they can’t even write simple HTML code. Sooo, this post is in response to all the would be web developers out there who don’t really know what in the hell they’re doing when it comes to tables.

FAQ: Why is it important to properly format and nest your tables?

Different browsers behave differently for code that is written improperly. To help ensure your table displays the way you intended it to always use correct nesting and ensure you have matching tags.

A Simple Table

<table>
   <tr>
     <td>hello there</td>
     <td>bye for now</td>
   </tr>
</table>

Simple Table (Visual)

hello there bye for now

This table has one row and two columns. A table always starts and ends with a <table> and </table> tag. If you forget to put the end </table> tag and start another table immediately following you’ll sometimes find that the browser will close your first table for you — but not always! It’s not safe to assume that your browser is smart enough to fix your HTML mistakes for you.

Now a table isn’t limited to a number of rows or columns but I find many people don’t know how to span rows or columns appropriately.

Spanning A Column

<table>
  <tr>
   <td>hello there</td>
   <td>bye for now</td>
  </tr>
  <tr>
   <td colspan="2">huh?</td>
  </tr>
</table>

Spanning A Column (Visual)

hello there bye for now
huh?

When you span a column the cell takes up the space of both columns. A lot of time I see people put in extra <td> and </td> tags even when they have a colspan set to the appropriate number. The colspan always equals the number of columns you want to span (if that isn’t obvious enough). There’s never any need to put a colspan of 1 because that’s the same thing as having a <td> and </td> without a colspan attribute.

Spanning A Row

<table>
  <tr>
   <td rowspan="2">Hey there</td>
   <td>bye for now</td>
  </tr>
  <tr>
    <td>huh?</td>
  </tr>
</table>

Spanning A Row (Visual)

Hey there bye for now
huh?

This does the opposite thing that a colspan does. Your table cells are now merged down instead of merged across. When you do a row span there is no need to include a <td> and </td> for the row you’re merging over. If you do you’ll end up with strange results and a misshappen table. The cell that has the rowspan attribute on it is always the one that merges into the cell that would have been beneath it.

Table Attributes

Here’s a list of attributes you can assign to the table tags. Ironically enough I’ve decided to put these in a table.

Attribute Description Example
Border this sets an outline around the tables <table border=”1″>
Cell Padding this puts space around the content inside of a table cell <table cellpadding=”2″>
Cell Spacing this puts space between the td cells <table cellpadding=”0″>
Width set the exact or relative width of the entire table or cell <td width=”20%”>
Height set the exact or relative height of the entire table or cell <td height=”22″>
Align sets the text alignment inside of the cell (left, right, middle, justify) <td align=”right”>
Valign sets the vertical alignment of the td cell (top, bottom, middle, abstop, absmiddle, absbottom, baseline) <td valign=”middle”>
Class used to setup a style on the cell <td class=”darkblue”>
Background set the background color of the table <table background=”#000000″>
Foreground set the text color in the table <td foreground=”#FFFFFF”>