This is a documentation for Board Game Arena: play board games online !

Stock

Board Game Arenasta
Siirry navigaatioon Siirry hakuun

"Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines.

Stock is very flexible and is the most used component in BGA games.

Stock is used for example:

  • To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...).
  • To display items in player panels (ex: Takenoko, Amyitis, ...)
  • ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components.

Using stock:

  • Your items are arranged nicely and sorted by type.
  • When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one.
  • Select/unselect items is a built-in functionnality.
  • You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component.

Using stock: a simple example

Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards.

At first, don't forget to add "ebg/stock" as a dependency:

define([
    "dojo","dojo/_base/declare",
    "ebg/core/gamegui",
    "ebg/counter",
    "ebg/stock"     /// <==== HERE
],

The stock is initialized in Javascript "setup" method like this:

    // Player hand
    this.playerHand = new ebg.stock();
    this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );

Explanations:

  • We create a new stock object for the player hand.
  • As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl).

Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns.

Here's how we tell stock what are the items type to display:

    // Explain there are 13 images per row in the CSS sprite image
    this.playerHand.image_items_per_row = 13;

    // Create cards types:
    for( var color=1;color<=4;color++ )
    {
        for( var value=2;value<=14;value++ )
        {
            // Build card type id
            var card_type_id = this.getCardUniqueId( color, value );
            this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id );
        }
    }

Explanations:

  • At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.
  • Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite.

Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId".

From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) );

In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id );

If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id );

Complete stock component reference

create( page, container_div, item_width, item_height ):

With create, you create a new stock component. Parameters:

  • page: the container page. Usually: "this".
  • container_div: the container "
    " element (a void
    element in your template, with an id).
  • a stock item width and height, in pixels.

(See "Hearts" example above).


count():

Return the total number of items in the stock right now.

addItemType( type, weight, image, image_position ):

Define a new type of item to the stock.


This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color).

Parameters:

  • type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs.
  • weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted).
  • image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here.

Be careful: you must specify the image url as this:

  g_themeurl+'img/your_game_name/yourimage.png'
  • image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third.

Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this:

    // Specify that there is 10 image items per row in images used in "myStockObject" control.
    this.myStockObject.image_items_per_row = 10;

addToStock( type, from )

Add an item to the stock, with the specified type.

To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens).

Parameters:

  • type: ID of the item type to use (as specified in "addItemType")
  • from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item.

Example:

  // Add a money token to the "player money" stock.
  // The money token will appear on "player_id" player panel and will move to its position.
  this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id );

Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.

addToStockWithId( type, id, from )

This is exactly the same method than "addToStock", except that you associate an ID to the newly created item.

This is especially useful:

  • When you need to know which item(s) has been selected by the user (see "getSelectedItems").
  • When you need to remove a specific item from the stock with "removeFromStockById"

Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM.

removeFromStock( type, to )

Remove an item of the specific type from the stock.

"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.

removeFromStockById( id, to )

Remove an item with a specific ID from the stock.

"to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear.

removeAll()

Remove all items from the stock.

getPresentTypeList()

Return an array with all the types of items present in the stock right now.

Example:

    this.myStockControl.removeAll();
    this.myStockControl.addToStock( 65 );
    this.myStockControl.addToStock( 34 );
    this.myStockControl.addToStock( 89 );
    this.myStockControl.addToStock( 65 );
    
    // The following returns: { 34:1,  65:1,  89:1  }
    var item_types = this.myStockControl.getPresentTypeList();

resetItemsPosition()

If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method.

item_margin

By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this.

Example:

     this.myStockControl.item_margin=5;

changeItemsWeight( newWeights )

With this method you can change dynamically the weight of the item types in a stock control.

Items are immediately re-sorted with the new weight.

Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this.

newWeights is an associative array: item type id => new weight.

Example:

    // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30.
    this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } );

setSelectionMode( mode )

For each stock control, you can specify a selection mode:

  • 0: no item can be selected by the player.
  • 1: a maximum of one item can be selected by the player at the same time.
  • 2: several items can be selected by the player at the same time.

isSelected( id )

Return true/false wether the specified item id has been selected or not.

selectItem( id )

Select the specified item.

unselectItem( id )

Unselect the specified item.

unselectAll()

Unselect all items of the stock.

onChangeSelection

This callback method is called when the player select/unselect an item of the stock.

You can connect this to one of your method like this:

    dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' );
    
    (...)
    
    onMyMethodToCall: function( control_name )
    {
        // This method is called when myStockControl selected items changed
        var items = this.myStockControl.getSelectedItems();
        
        // (do something)
    },

Note: The "control_name" argument is the ID (the "DOM" id) of the

container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method.

getSelectedItems()

Return the list of selected items, as an array with the following format:

[
   { type:1,  id:  1001 },
   { type:1,  id:  1002 },
   { type:3,  id:  1003 }
   ...
]

getUnselectedItems()

Same as the previous one, but return unselected item instead of seleted ones.

getAllItems()

Get all items (same format than getSelectedItems and getUnselectedItems).

setOverlap( horizontal_percent, vertical_percent )

Make items on the stock control "overlap" on each other, to save space.

By default, horizontal_overlap and vertical_overlap are 0.

When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100.

vertical_overlap works differently: one items on two are shifted up.

See "Jaipur" game to see an example to use of this function.

onItemCreate

Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it.

Complete example:

    // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item:
    this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); 

     (...)

    // And here is our "setupNewCard":
    setupNewCard: function( card_div, card_type_id, card_id )
    {
       // Add a special tooltip on the card:
       this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' );

       // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type

       // Add some custom HTML content INSIDE the Stock item:
       dojo.place( this.format_block( 'jstpl_my_card_content', {
                                ....
                           } ), card_div.id );
    }

Tips when adding/removing items to/from Stock components

The usual way is the following:

Situation A:

When you add a card to a stock item, and this card is not coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from.

Situation B:

When you add a card to a stock item, and this card is coming from another stock:

  • on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48".
  • then, remove the source item with "removeFromStockById".

(note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide).

Situation C:

When you move a card from a stock item to something that is not a stock item:

  • insert the card as a classic HTML template (dojo.place / this.format_block).
  • place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above).
  • slide it to its new position with "this.slideToObject"
  • remove the card from the Stock item with "removeFromStockById".

Using the methods above, your cards should slided to, from and between your Stock controls smoothly