Card Stories - Client Documentation

=HTML & CSS=

Overview
The following principles apply:


 * the HTML is not be generated by the plugin
 * the metadata is stored in the DOM instead of in a JavaScript object attached to $.cardstories
 * each game state is implemented in a different plugin because it has a different behavior and user interface (XXX contradicts below)

The list of all possible div is enumerated in static/index.html and static/test/index.html. The non relevant parts are hiden dynamically.

Layout strategy
The game design uses an absolute positioning layout strategy. The div of each game state is given all the space in the game div:

The background, logo, top and bottom line are positioned in the enclosing div (.cardstories) and shared among all states. The images that indicate the state progression during the game creation (1, 2, 3, 4) are common to multiple game states and are therefore described in the CSS part dedicated to the enclosing div of the game:

so that only the image path name needs to be specified for the game state div.

The set_active function from jquery.cardstories.js sets the cardstories_active class on all parents of the element displaying the state. This allows for state display embedded in divs that can be hidden when necessary.

Game state display
The game is displayed in a div that depends on the state of the game. All parts are hidden by default, using the following CSS stanza:

Each function displaying a game state (create, vote, etc.) is given the root of the DOM where the game is displayed (.cardstories). The unset_active and set_active functions update the display for a given state. They start by removing the cardstories_active class in all childs of the .cardstories element and then add the cardstories_active class to the DOM element where the state is displayed. The following CSS stanza ensure that only the relevant part is displayed:

=Javascript=

Overview
The architecture of the JavaScript client is a single JQuery plugin with two arguments as called in the example:

The HTML to which the plugin is applied is divided according to the state of the game: one div for each state with a class of the form cardstories_STATE. The invitation state is further divided in three div: one for the owner of the game, another for a visitor and the last one for the registered player to pick a card.

If the game_id parameter is missing, the plugin will display cards and an input box to enter the sentence.

Skin gallery
In order to make it easier to check the layout of a specific state in the game, you can add a skin=XXX argument to the game URL. When provided, instead of running the game, the corresponding function from skin.js is called. The purpose of these functions are merely to mockup a state of the game and call the relevant display function to reveal the desired layout.

For example, to get the list of pages that can be accessed that way:

http://localhost:5000/static/?skin

Authentication
If no player_id parameter and no CARDSTORIES_ID cookie are set, the user is asked for a nickname. Otherwise the application proceeds directly to the game creation.

The jquery.cookie.js plugin retrieves the CARDSTORIES_ID cookie.

Long polling
The client is architectured to give immediate feedback when an event occurs using the long polling notification service. The game is refreshed as soon as an action is required from the player or when (s)he is invited to a new game.

The introduction of long polling removes the need for the player to reload the page when information displayed on the screen gets outdated, ie when:
 * the lobby is displayed and a new game becomes available
 * a game is displayed and its state changes

There is no need to wait for notifications when displaying a game that is complete or when waiting for a user interaction such as picking a card or voting for a card. The following code shows that the notification queue is sollicited (long polling) when it is expected invitations, except if a participating user is to pick a card.

The poll function implements the core of the notification feature. It uses a sequence number to ensure that no two long poll are in a race condition. When a poll request is sent, a global sequence number is incremented.

When the answer from a poll request is received, it will be discarded if the sequence number has increased, i.e. if another poll request has been sent in the meantime.

Although the window of opportunity for such a race condition is small, it can be very disrupting when it happens.

Lobby
The list of games is the default view. From there the user can click on a game to display it or chose to create a new one.

When reading the list of games from the server, the client needs to create HTML rows. Instead of encoding the HTML in the cardstories JQuery plugin, a template is extracted from the page (and hidden so that it does not show to the user). It must be made available under the cardstories_template as follows:

...

It is extracted and the placeholders are replaced with actual values for each row returned by the lobby function of the webservice.

The created rows are then injected in the body of a table and run thru the tablesorter plugin to allow for pagination and sorting.

Note that tablesorter silently does nothing if the element on which it is applied does not contain the thead or tbody elements.

The handling of the lobby is divided in three functions: two for the display of a given state ( lobbyInProgress and lobbyFinished ) and one to send a request to the server ( refreshLobby ).

Card picking
In order to make the best use of the display size, the jqDock widget is used to display the deck proposed to the game author.

jqDock used to display the cards has many options but cannot do the following:
 * always have an item selected, even when the mouse moves out
 * add css class to the images that are left untouched
 * display a label above the image
 * add a div next to the image, for instance to show that a given card is the player card

Invitation state - Author view
To accommodate for the smaller div size of the images on this screen, 150 pixels wide thumbs of the cards are stored. (There are four card sizes: width 100 in small, 150 in thumbs, 280 in medium and 333 in images)

Because jqDock relies on images instead of div to display and resize the deck, the jquery.cardstories.js code can't rely solely on CSS class to display the images. In order to keep the code free of path names, the templates are encoded as meta information in the parent div, as shown below:

Where card will be set to the src attribute with the {card} card placeholder replaced with the card number (range from 1 to 36), nocard will be used instead of the card if there is none available and the waiting text will replace the player name in the title attribute when there is none.

Invitations
The advertise function is called after the sentence for the game is validated by the author to invite players.

Vote status
The implementation of the vote state can be found in three separate functions which are used depending on the user status : vote_owner will watch the votes from everyone during the voting phase, vote_voter will be offered to vote except for the card picked during in the previous state and the vote_viewer will see the board with the sentence but cannot act. The implementation of the complete state is more straightforward because all the viewers are treated equally.

Tests: jslint
Although jslint.com provides an interactive way to check JavaScript code, it is more convenient to use the command line:

Unfortunately it is not yet packaged for debian. The alternative is to compile it from sources, using the version found (but not installed) in the jscoverage package: