docs: function ChoiceTable(options) {
          var that;
          that = this;
  
          /**
           * ### ChoiceTable.table
           *
           * The HTML element triggering the listener function when clicked
           */
          this.table = null;
  
          /**
           * ### ChoiceTable.choicesSetSize
           *
           * How many choices can be on the same row/column
           */
          this.choicesSetSize = null;
  
          /**
           * ### ChoiceTable.tr
           *
           * Reference to TR elements of the table
           *
           * Note: if the orientation is vertical there will be multiple TR
           * otherwise just one.
           *
           * @see createTR
           */
          this.trs = [];
  
          /**
           * ### ChoiceTable.listener
           *
           * The listener function
           */
          this.listener = function(e) {
              var name, value, td;
              var i, len, removed;
  
              e = e || window.event;
              td = e.target || e.srcElement;
  
              // Not a clickable choice.
              if ('undefined' === typeof that.choicesIds[td.id]) return;
  
              // Relative time.
              if ('string' === typeof that.timeFrom) {
                  that.timeCurrentChoice = node.timer.getTimeSince(that.timeFrom);
              }
              // Absolute time.
              else {
                  that.timeCurrentChoice = Date.now ?
                      Date.now() : new Date().getTime();
              }
  
              // Id of elements are in the form of name_value or name_item_value.
              value = td.id.split(that.separator);
  
              // Separator not found, not a clickable cell.
              if (value.length === 1) return;
  
              name = value[0];
              value = value[1];
  
              // One more click.
              that.numberOfClicks++;
  
              // Click on an already selected choice.
              if (that.isChoiceCurrent(value)) {
                  that.unsetCurrentChoice(value);
                  J.removeClass(td, 'selected');
  
                  if (that.selectMultiple) {
                      // Remove selected TD (need to keep this clean for reset).
                      i = -1, len = that.selected.length;
                      for ( ; ++i < len ; ) {
                          if (that.selected[i].id === td.id) {
                              that.selected.splice(i, 1);
                              break;
                          }
                      }
                  }
                  else {
                      that.selected = null;
                  }
                  removed = true;
              }
              // Click on a new choice.
              else {
  
                  // Have we exhausted available choices?
                  if ('number' === typeof that.selectMultiple &&
                      that.selected.length === that.selectMultiple) return;
  
                  that.setCurrentChoice(value);
                  J.addClass(td, 'selected');
  
                  if (that.selectMultiple) {
                      that.selected.push(td);
                  }
                  else {
                      // If only 1 selection allowed, remove old selection.
                      if (that.selected) J.removeClass(that.selected, 'selected');
                      that.selected = td;
                  }
              }
  
              // Remove any warning/errors on click.
              if (that.isHighlighted()) that.unhighlight();
  
              // Call onclick, if any.
              if (that.onclick) {
                  // TODO: Should we parseInt it anyway when we store
                  // the current choice?
                  value = parseInt(value, 10);
                  that.onclick.call(that, value, removed, td);
              }
          };
  
          /**
           * ### ChoiceTable.mainText
           *
           * The main text introducing the choices
           *
           * @see ChoiceTable.spanMainText
           */
          this.mainText = null;
  
          /**
           * ### ChoiceTable.hint
           *
           * An additional text with information about how to select items
           *
           * If not specified, it may be auto-filled, e.g. '(pick 2)'.
           *
           * @see Feedback.texts.autoHint
           */
          this.hint = null;
  
          /**
           * ### ChoiceTable.spanMainText
           *
           * The span containing the main text
           */
          this.spanMainText = null;
  
          /**
           * ### ChoiceTable.choices
           *
           * The array available choices
           */
          this.choices = null;
  
          /**
           * ### ChoiceTable.choicesValues
           *
           * Map of choices' values to indexes in the choices array
           */
          this.choicesValues = {};
  
          /**
           * ### ChoiceTable.choicesIds
           *
           * Map of choices' cells ids to choices
           *
           * Used to determine what are the clickable choices.
           */
          this.choicesIds = {};
  
          /**
           * ### ChoiceTable.choicesCells
           *
           * The cells of the table associated with each choice
           */
          this.choicesCells = null;
  
          /**
           * ### ChoiceTable.left
           *
           * A non-clickable first cell of the row/column
           *
           * It will be placed to the left of the choices if orientation
           * is horizontal, or above the choices if orientation is vertical
           *
           * @see ChoiceTable.orientation
           */
          this.left = null;
  
          /**
           * ### ChoiceTable.leftCell
           *
           * The rendered left cell
           *
           * @see ChoiceTable.renderSpecial
           */
          this.leftCell = null;
  
          /**
           * ### ChoiceTable.right
           *
           * A non-clickable last cell of the row/column
           *
           * It will be placed to the right of the choices if orientation
           * is horizontal, or below the choices if orientation is vertical
           *
           * @see ChoiceTable.orientation
           */
          this.right = null;
  
          /**
           * ### ChoiceTable.rightCell
           *
           * The rendered right cell
           *
           * @see ChoiceTable.renderSpecial
           */
          this.rightCell = null;
  
          /**
           * ### ChoiceTable.timeCurrentChoice
           *
           * Time when the last choice was made
           */
          this.timeCurrentChoice = null;
  
          /**
           * ### ChoiceTable.timeFrom
           *
           * Time is measured from timestamp as saved by node.timer
           *
           * Default event is a new step is loaded (user can interact with
           * the screen). Set it to FALSE, to have absolute time.
           *
           * @see node.timer.getTimeSince
           */
          this.timeFrom = 'step';
  
          /**
           * ### ChoiceTable.order
           *
           * The current order of display of choices
           *
           * @see ChoiceTable.originalOrder
           */
          this.order = null;
  
          /**
           * ### ChoiceTable.correctChoice
           *
           * The array of correct choice/s
           *
           * The field is an array or number|string depending
           * on the value of ChoiceTable.selectMultiple
           *
           * @see ChoiceTable.selectMultiple
           */
          this.correctChoice = null;
  
          /**
           * ### ChoiceTable.requiredChoice
           *
           * The number of required choices. Default 0
           */
          this.requiredChoice = null;
  
          /**
           * ### ChoiceTable.attempts
           *
           * List of currentChoices at the moment of verifying correct answers
           */
          this.attempts = [];
  
          /**
           * ### ChoiceTable.numberOfClicks
           *
           * Total number of clicks on different choices
           */
          this.numberOfClicks = 0;
  
          /**
           * ### ChoiceTable.selected
           *
           * Currently selected TD elements
           *
           * @see ChoiceTable.currentChoice
           */
          this.selected = null;
  
          /**
           * ### ChoiceTable.currentChoice
           *
           * Choice/s associated with currently selected cell/s
           *
           * The field is an array or number|string depending
           * on the value of ChoiceTable.selectMultiple
           *
           * @see ChoiceTable.selectMultiple
           *
           * @see ChoiceTable.selected
           */
          this.currentChoice = null;
  
          /**
           * ### ChoiceTable.selectMultiple
           *
           * The number of maximum simulataneous selection (>1), or false
           */
          this.selectMultiple = null;
  
          /**
           * ### ChoiceTable.shuffleChoices
           *
           * If TRUE, choices are randomly assigned to cells
           *
           * @see ChoiceTable.order
           */
          this.shuffleChoices = null;
  
          /**
           * ### ChoiceTable.renderer
           *
           * A callback that renders the content of each cell
           *
           * The callback must accept three parameters:
           *
           *   - a td HTML element,
           *   - a choice
           *   - the index of the choice element within the choices array
           *
           * and optionally return the _value_ for the choice (otherwise
           * the order in the choices array is used as value).
           */
          this.renderer = null;
  
          /**
           * ### ChoiceTable.orientation
           *
           * Orientation of display of choices: vertical ('V') or horizontal ('H')
           *
           * Default orientation is horizontal.
           */
          this.orientation = 'H';
  
          /**
           * ### ChoiceTable.group
           *
           * The name of the group where the table belongs, if any
           */
          this.group = null;
  
          /**
           * ### ChoiceTable.groupOrder
           *
           * The order of the choice table within the group
           */
          this.groupOrder = null;
  
          /**
           * ### ChoiceTable.freeText
           *
           * If truthy, a textarea for free-text comment will be added
           *
           * If 'string', the text will be added inside the textarea
           */
          this.freeText = null;
  
          /**
           * ### ChoiceTable.textarea
           *
           * Textarea for free-text comment
           */
          this.textarea = null;
  
          /**
           * ### ChoiceTable.separator
           *
           * Symbol used to separate tokens in the id attribute of every cell
           *
           * Default ChoiceTable.separator
           *
           * @see ChoiceTable.renderChoice
           */
          this.separator = ChoiceTable.separator;
      }