dojox/grid/_Grid.js

  • Provides:

    • dojox.grid._Grid
  • Requires:

    • dijit.dijit in common in project dijit
    • dijit.Menu in common in project dijit
    • dojox.html.metrics in common
    • dojox.grid.util in common
    • dojox.grid._Scroller in common
    • dojox.grid._Layout in common
    • dojox.grid._View in common
    • dojox.grid._ViewManager in common
    • dojox.grid._RowManager in common
    • dojox.grid._FocusManager in common
    • dojox.grid._EditManager in common
    • dojox.grid.Selection in common
    • dojox.grid._RowSelector in common
    • dojox.grid._Events in common
  • dojox.grid._Grid

    • type
      Function
    • chains:
      • dijit._Widget: (prototype)
      • dijit._Widget: (call)
      • dijit._Templated: (call)
      • dojox.grid._Events: (call)
    • mixins:
      • dijit._Templated.prototype: (prototype)
      • dojox.grid._Events.prototype: (prototype)
    • summary
      A grid widget with virtual scrolling, cell editing, complex rows,
      sorting, fixed columns, sizeable columns, etc.
    • description
      _Grid provides the full set of grid features without any
      direct connection to a data store.
      
      The grid exposes a get function for the grid, or optionally
      individual columns, to populate cell contents.
      
      The grid is rendered based on its structure, an object describing
      column and cell layout.
    • example
      A quick sample:
      
      define a get function
      	function get(inRowIndex){ // called in cell context
      		return [this.index, inRowIndex].join(', ');
      	}
      
      define the grid structure:
      	var structure = [ // array of view objects
      		{ cells: [// array of rows, a row is an array of cells
      			[
      				{ name: "Alpha", width: 6 },
      				{ name: "Beta" },
      				{ name: "Gamma", get: get }]
      		]}
      	];
      
      	<div id="grid"
      		rowCount="100" get="get"
      		structure="structure"
      		dojoType="dojox.grid._Grid"></div>
  • dojox.grid._Grid.templatePath

    • summary
  • dojox.grid._Grid.classTag

    • type
      String
    • summary
      CSS class applied to the grid's domNode
  • dojox.grid._Grid.rowCount

    • type
      Integer
    • summary
      Number of rows to display.
  • dojox.grid._Grid.keepRows

    • type
      Integer
    • summary
      Number of rows to keep in the rendering cache.
  • dojox.grid._Grid.rowsPerPage

    • type
      Integer
    • summary
      Number of rows to render at a time.
  • dojox.grid._Grid.autoWidth

    • type
      Boolean
    • summary
      If autoWidth is true, grid width is automatically set to fit the data.
  • dojox.grid._Grid.initialWidth

    • type
      String
    • summary
      A css string to use to set our initial width (only used if autoWidth
      is true).  The first rendering of the grid will be this width, any
      resizing of columns, etc will result in the grid switching to
      autoWidth mode.  Note, this width will override any styling in a
      stylesheet or directly on the node.
  • dojox.grid._Grid.autoHeight

    • type
      Boolean|Integer
    • summary
      If autoHeight is true, grid height is automatically set to fit the data.
      If it is an integer, the height will be automatically set to fit the data
      if there are fewer than that many rows - and the height will be set to show
      that many rows if there are more
  • dojox.grid._Grid.rowHeight

    • type
      Integer
    • summary
      If rowHeight is set to a positive number, it will define the height of the rows
      in pixels. This can provide a significant performance advantage, since it
      eliminates the need to measure row sizes during rendering, which is one
      the primary bottlenecks in the DataGrid's performance.
  • dojox.grid._Grid.autoRender

    • type
      Boolean
    • summary
      If autoRender is true, grid will render itself after initialization.
  • dojox.grid._Grid.defaultHeight

    • type
      String
    • summary
      default height of the grid, measured in any valid css unit.
  • dojox.grid._Grid.height

    • type
      String
    • summary
      explicit height of the grid, measured in any valid css unit.  This will be populated (and overridden)
      if the height: css attribute exists on the source node.
  • dojox.grid._Grid.structure

    • type
      dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]
    • summary
      View layout defintion.
  • dojox.grid._Grid.elasticView

    • type
      Integer
    • summary
      Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
  • dojox.grid._Grid.singleClickEdit

    • type
      boolean
    • summary
      Single-click starts editing. Default is double-click
  • dojox.grid._Grid.selectionMode

    • type
      String
    • summary
      Set the selection mode of grid's Selection.  Value must be 'single', 'multiple',
      or 'extended'.  Default is 'extended'.
  • dojox.grid._Grid.rowSelector

    • type
      Boolean|String
    • summary
      If set to true, will add a row selector view to this grid.  If set to a CSS width, will add
      a row selector of that width to this grid.
  • dojox.grid._Grid.columnReordering

    • type
      Boolean
    • summary
      If set to true, will add drag and drop reordering to views with one row of columns.
  • dojox.grid._Grid.headerMenu

    • type
      dijit.Menu
    • summary
      If set to a dijit.Menu, will use this as a context menu for the grid headers.
  • dojox.grid._Grid.placeholderLabel

    • type
      String
    • summary
      Label of placeholders to search for in the header menu to replace with column toggling
      menu items.
  • dojox.grid._Grid.selectable

    • type
      Boolean
    • summary
      Set to true if you want to be able to select the text within the grid.
      
      
      Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
  • dojox.grid._Grid._click

    • summary
  • dojox.grid._Grid.loadingMessage

    • type
      String
    • summary
      Message that shows while the grid is loading
  • dojox.grid._Grid.errorMessage

    • type
      String
    • summary
      Message that shows when the grid encounters an error loading
  • dojox.grid._Grid.noDataMessage

    • type
      String
    • summary
      Message that shows if the grid has no data - wrap it in a
      span with class 'dojoxGridNoData' if you want it to be
      styled similar to the loading and error messages
  • dojox.grid._Grid.escapeHTMLInData

    • type
      Boolean
    • summary
      This will escape HTML brackets from the data to prevent HTML from
      user-inputted data being rendered with may contain JavaScript and result in
      XSS attacks. This is true by default, and it is recommended that it remain
      true. Setting this to false will allow data to be displayed in the grid without
      filtering, and should be only used if it is known that the data won't contain
      malicious scripts. If HTML is needed in grid cells, it is recommended that
      you use the formatter function to generate the HTML (the output of
      formatter functions is not filtered, even with escapeHTMLInData set to true).
  • dojox.grid._Grid.formatterScope

    • type
      Object
    • summary
      An object to execute format functions within.  If not set, the
      format functions will execute within the scope of the cell that
      has a format function.
  • dojox.grid._Grid.editable

    • type
      boolean
    • summary
      indicates if the grid contains editable cells, default is false
      set to true if editable cell encountered during rendering
      
      
      private
  • dojox.grid._Grid.sortInfo

    • summary
  • dojox.grid._Grid.themeable

    • summary
  • dojox.grid._Grid._placeholders

    • summary
  • dojox.grid._Grid._layoutClass

    • type
      Object
    • summary
      The class to use for our layout - can be overridden by grid subclasses
  • dojox.grid._Grid.buildRendering

    • type
      Function
    • source: [view]
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
    • summary
  • dojox.grid._Grid.postMixInProperties

    • type
      Function
    • source: [view]
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
    • summary
  • dojox.grid._Grid.postCreate

    • type
      Function
    • source: [view]
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
    • summary
  • dojox.grid._Grid.destroy

    • type
      Function
    • source: [view]
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
    • summary
  • dojox.grid._Grid._setAutoHeightAttr

    • type
      Function
    • parameters:
      • ah: (typeof )
      • skipRender: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
    • summary
  • dojox.grid._Grid._getRowCountAttr

    • type
      Function
    • source: [view]
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
    • summary
  • dojox.grid._Grid.textSizeChanged

    • type
      Function
    • source: [view]
         this.render();
    • summary
  • dojox.grid._Grid.sizeChange

    • type
      Function
    • source: [view]
         this.update();
    • summary
  • dojox.grid._Grid.createManagers

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
    • summary
  • dojox.grid._Grid.createSelection

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
    • summary
  • dojox.grid._Grid.createScroller

    • type
      Function
    • source: [view]
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
    • summary
      Creates a new virtual scroller
  • dojox.grid._Grid.createLayout

    • type
      Function
    • source: [view]
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
    • summary
      Creates a new Grid layout
  • dojox.grid._Grid.onMoveColumn

    • type
      Function
    • source: [view]
         this.render();
    • summary
  • dojox.grid._Grid.onResizeColumn

    • type
      Function
    • parameters:
      • cellIdx: (typeof int)
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
    • summary
  • dojox.grid._Grid.createViews

    • type
      Function
    • source: [view]
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
    • summary
  • dojox.grid._Grid.createView

    • type
      Function
    • parameters:
      • inClass: (typeof )
      • idx: (typeof )
    • source: [view]
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
    • summary
  • dojox.grid._Grid.buildViews

    • type
      Function
    • source: [view]
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
    • summary
  • dojox.grid._Grid._setStructureAttr

    • type
      Function
    • parameters:
      • structure: (typeof )
    • source: [view]
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
    • summary
  • dojox.grid._Grid.setStructure

    • type
      Function
    • parameters:
      • inStructure: (typeof dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]])
    • source: [view]
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
    • summary
      Install a new structure and rebuild the grid.
  • dojox.grid._Grid.getColumnTogglingItems

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
    • chains:
      • dijit.CheckedMenuItem.prototype.destroy: (call)
    • summary
  • dojox.grid._Grid._setHeaderMenuAttr

    • type
      Function
    • parameters:
      • menu: (typeof )
    • source: [view]
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
    • summary
  • dojox.grid._Grid.setHeaderMenu

    • type
      Function
    • parameters:
      • menu: (typeof dijit.Menu)
    • source: [view]
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
    • summary
  • dojox.grid._Grid.setupHeaderMenu

    • type
      Function
    • source: [view]
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
    • summary
  • dojox.grid._Grid._fetch

    • type
      Function
    • parameters:
      • start: (typeof )
    • source: [view]
         this.setScrollTop(0);
    • summary
  • dojox.grid._Grid.getItem

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         return null;
    • summary
  • dojox.grid._Grid.showMessage

    • type
      Function
    • parameters:
      • message: (typeof )
    • source: [view]
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
    • summary
  • dojox.grid._Grid._structureChanged

    • type
      Function
    • source: [view]
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
    • summary
  • dojox.grid._Grid.hasLayout

    • type
      Function
    • source: [view]
         return this.layout.cells.length;
    • summary
  • dojox.grid._Grid.resize

    • type
      Function
    • parameters:
      • changeSize: (typeof )
      • resultSize: (typeof )
    • source: [view]
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
    • summary
      Update the grid's rendering dimensions and resize it
      
      Calling sizeChange calls update() which calls _resize...so let's
      save our input values, if any, and use them there when it gets
      called.  This saves us an extra call to _resize(), which can
      get kind of heavy.
  • dojox.grid._Grid._getPadBorder

    • type
      Function
    • source: [view]
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
    • summary
  • dojox.grid._Grid._getHeaderHeight

    • type
      Function
    • source: [view]
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
    • summary
  • dojox.grid._Grid._resize

    • type
      Function
    • parameters:
      • changeSize: (typeof )
      • resultSize: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
    • summary
  • dojox.grid._Grid.adaptWidth

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
        },


        adaptWidth: function() {
         // private: sets width and position for views and update grid width if necessary
         var doAutoWidth = (!this.initialWidth && this.autoWidth);
         var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
          vw = this.views.arrange(1, w);
         this.views.onEach("adaptWidth");
         if(doAutoWidth){
          this.domNode.style.width = vw + "px";
         }
    • summary
  • dojox.grid._Grid.adaptHeight

    • type
      Function
    • parameters:
      • inHeaderHeight: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
        },


        adaptWidth: function() {
         // private: sets width and position for views and update grid width if necessary
         var doAutoWidth = (!this.initialWidth && this.autoWidth);
         var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
          vw = this.views.arrange(1, w);
         this.views.onEach("adaptWidth");
         if(doAutoWidth){
          this.domNode.style.width = vw + "px";
         }
        },


        adaptHeight: function(inHeaderHeight){
         // private: measures and normalizes header height, then sets view heights, and then updates scroller
         // content extent
         var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
         var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
         this.views.onEach('setSize', [0, h]);
         this.views.onEach('adaptHeight');
         if(!this._autoHeight){
          var numScroll = 0, numNoScroll = 0;
          var noScrolls = dojo.filter(this.views.views, function(v){
           var has = v.hasHScrollbar();
           if(has){ numScroll++; }else{ numNoScroll++; }
           return (!has);
          });
          if(numScroll > 0 && numNoScroll > 0){
           dojo.forEach(noScrolls, function(v){
            v.adaptHeight(true);
           });
          }
         }
         if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
          this.scroller.windowHeight = h;
         }else{
          this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
         }
    • summary
  • dojox.grid._Grid.startup

    • type
      Function
    • source: [view]
         if(this._started){return;}
         this.inherited(arguments);
         if(this.autoRender){
          this.render();
         }
    • summary
  • dojox.grid._Grid.render

    • type
      Function
    • source: [view]
         if(!this.domNode){return;}
         if(!this._started){return;}


         if(!this.hasLayout()) {
          this.scroller.init(0, this.keepRows, this.rowsPerPage);
          return;
         }
         //
         this.update = this.defaultUpdate;
         this._render();
    • summary
      Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
      scrolling states, see Update.
  • dojox.grid._Grid._render

    • type
      Function
    • source: [view]
         this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
         this.prerender();
         this.setScrollTop(0);
         this.postrender();
    • summary
  • dojox.grid._Grid.prerender

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
        },


        adaptWidth: function() {
         // private: sets width and position for views and update grid width if necessary
         var doAutoWidth = (!this.initialWidth && this.autoWidth);
         var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
          vw = this.views.arrange(1, w);
         this.views.onEach("adaptWidth");
         if(doAutoWidth){
          this.domNode.style.width = vw + "px";
         }
        },


        adaptHeight: function(inHeaderHeight){
         // private: measures and normalizes header height, then sets view heights, and then updates scroller
         // content extent
         var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
         var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
         this.views.onEach('setSize', [0, h]);
         this.views.onEach('adaptHeight');
         if(!this._autoHeight){
          var numScroll = 0, numNoScroll = 0;
          var noScrolls = dojo.filter(this.views.views, function(v){
           var has = v.hasHScrollbar();
           if(has){ numScroll++; }else{ numNoScroll++; }
           return (!has);
          });
          if(numScroll > 0 && numNoScroll > 0){
           dojo.forEach(noScrolls, function(v){
            v.adaptHeight(true);
           });
          }
         }
         if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
          this.scroller.windowHeight = h;
         }else{
          this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
         }
        },


        // startup
        startup: function(){
         if(this._started){return;}
         this.inherited(arguments);
         if(this.autoRender){
          this.render();
         }
        },


        // render
        render: function(){
         // summary:
         // Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
         // scrolling states, see Update.


         if(!this.domNode){return;}
         if(!this._started){return;}


         if(!this.hasLayout()) {
          this.scroller.init(0, this.keepRows, this.rowsPerPage);
          return;
         }
         //
         this.update = this.defaultUpdate;
         this._render();
        },


        _render: function(){
         this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
         this.prerender();
         this.setScrollTop(0);
         this.postrender();
        },


        prerender: function(){
         // if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
         this.keepRows = this._autoHeight ? 0 : this.keepRows;
         this.scroller.setKeepInfo(this.keepRows);
         this.views.render();
         this._resize();
    • summary
  • dojox.grid._Grid.postrender

    • type
      Function
    • source: [view]
         this.postresize();
         this.focus.initFocusView();
         // make rows unselectable
         dojo.setSelectable(this.domNode, this.selectable);
    • summary
  • dojox.grid._Grid.postresize

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
        },


        adaptWidth: function() {
         // private: sets width and position for views and update grid width if necessary
         var doAutoWidth = (!this.initialWidth && this.autoWidth);
         var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
          vw = this.views.arrange(1, w);
         this.views.onEach("adaptWidth");
         if(doAutoWidth){
          this.domNode.style.width = vw + "px";
         }
        },


        adaptHeight: function(inHeaderHeight){
         // private: measures and normalizes header height, then sets view heights, and then updates scroller
         // content extent
         var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
         var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
         this.views.onEach('setSize', [0, h]);
         this.views.onEach('adaptHeight');
         if(!this._autoHeight){
          var numScroll = 0, numNoScroll = 0;
          var noScrolls = dojo.filter(this.views.views, function(v){
           var has = v.hasHScrollbar();
           if(has){ numScroll++; }else{ numNoScroll++; }
           return (!has);
          });
          if(numScroll > 0 && numNoScroll > 0){
           dojo.forEach(noScrolls, function(v){
            v.adaptHeight(true);
           });
          }
         }
         if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
          this.scroller.windowHeight = h;
         }else{
          this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
         }
        },


        // startup
        startup: function(){
         if(this._started){return;}
         this.inherited(arguments);
         if(this.autoRender){
          this.render();
         }
        },


        // render
        render: function(){
         // summary:
         // Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
         // scrolling states, see Update.


         if(!this.domNode){return;}
         if(!this._started){return;}


         if(!this.hasLayout()) {
          this.scroller.init(0, this.keepRows, this.rowsPerPage);
          return;
         }
         //
         this.update = this.defaultUpdate;
         this._render();
        },


        _render: function(){
         this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
         this.prerender();
         this.setScrollTop(0);
         this.postrender();
        },


        prerender: function(){
         // if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
         this.keepRows = this._autoHeight ? 0 : this.keepRows;
         this.scroller.setKeepInfo(this.keepRows);
         this.views.render();
         this._resize();
        },


        postrender: function(){
         this.postresize();
         this.focus.initFocusView();
         // make rows unselectable
         dojo.setSelectable(this.domNode, this.selectable);
        },


        postresize: function(){
         // views are position absolute, so they do not inflate the parent
         if(this._autoHeight){
          var size = Math.max(this.views.measureContent()) + 'px';

          
          this.viewsNode.style.height = size;
         }
    • summary
  • dojox.grid._Grid.renderRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inNodes: (typeof )
    • source: [view]
         this.views.renderRow(inRowIndex, inNodes, this._skipRowRenormalize);
    • summary
      private, used internally to render rows
  • dojox.grid._Grid.rowRemoved

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         this.views.rowRemoved(inRowIndex);
    • summary
      private, used internally to remove rows
  • dojox.grid._Grid.invalidated

    • summary
  • dojox.grid._Grid.updating

    • summary
  • dojox.grid._Grid.beginUpdate

    • type
      Function
    • source: [view]
         this.invalidated = [];
         this.updating = true;
    • summary
      Use to make multiple changes to rows while queueing row updating.
      NOTE: not currently supporting nested begin/endUpdate calls
  • dojox.grid._Grid.endUpdate

    • type
      Function
    • source: [view]
         this.updating = false;
         var i = this.invalidated, r;
         if(i.all){
          this.update();
         }else if(i.rowCount != undefined){
          this.updateRowCount(i.rowCount);
         }else{
          for(r in i){
           this.updateRow(Number(r));
          }
         }
         this.invalidated = [];
    • summary
      Use after calling beginUpdate to render any changes made to rows.
  • dojox.grid._Grid.defaultUpdate

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
       }

       


       dojo.declare('dojox.grid._Grid',
        [ dijit._Widget, dijit._Templated, dojox.grid._Events ],
        {
        // summary:
        //   A grid widget with virtual scrolling, cell editing, complex rows,
        //   sorting, fixed columns, sizeable columns, etc.
        //
        // description:
        //  _Grid provides the full set of grid features without any
        //  direct connection to a data store.
        //
        //  The grid exposes a get function for the grid, or optionally
        //  individual columns, to populate cell contents.
        //
        //  The grid is rendered based on its structure, an object describing
        //  column and cell layout.
        //
        // example:
        //  A quick sample:
        //
        //  define a get function
        // | function get(inRowIndex){ // called in cell context
        // |  return [this.index, inRowIndex].join(', ');
        // | }
        //
        //  define the grid structure:
        // | var structure = [ // array of view objects
        // |  { cells: [// array of rows, a row is an array of cells
        // |   [
        // |    { name: "Alpha", width: 6 },
        // |    { name: "Beta" },
        // |    { name: "Gamma", get: get }]
        // |  ]}
        // | ];
        //
        // | 
        // |  rowCount="100" get="get"
        // |  structure="structure"
        // |  dojoType="dojox.grid._Grid">



        templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),


        // classTag: String
        //   CSS class applied to the grid's domNode
        classTag: 'dojoxGrid',


        // settings
        // rowCount: Integer
        //  Number of rows to display.
        rowCount: 5,


        // keepRows: Integer
        //  Number of rows to keep in the rendering cache.
        keepRows: 75,


        // rowsPerPage: Integer
        //  Number of rows to render at a time.
        rowsPerPage: 25,


        // autoWidth: Boolean
        //  If autoWidth is true, grid width is automatically set to fit the data.
        autoWidth: false,

        
        // initialWidth: String
        //  A css string to use to set our initial width (only used if autoWidth
        //  is true). The first rendering of the grid will be this width, any
        //  resizing of columns, etc will result in the grid switching to
        //  autoWidth mode. Note, this width will override any styling in a
        //  stylesheet or directly on the node.
        initialWidth: "",


        // autoHeight: Boolean|Integer
        //  If autoHeight is true, grid height is automatically set to fit the data.
        //  If it is an integer, the height will be automatically set to fit the data
        //  if there are fewer than that many rows - and the height will be set to show
        //  that many rows if there are more
        autoHeight: '',


        // rowHeight: Integer
        //  If rowHeight is set to a positive number, it will define the height of the rows
        //  in pixels. This can provide a significant performance advantage, since it
        //  eliminates the need to measure row sizes during rendering, which is one
        //   the primary bottlenecks in the DataGrid's performance.
        rowHeight: 0,

        
        // autoRender: Boolean
        //  If autoRender is true, grid will render itself after initialization.
        autoRender: true,


        // defaultHeight: String
        //  default height of the grid, measured in any valid css unit.
        defaultHeight: '15em',

        
        // height: String
        //  explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
        //  if the height: css attribute exists on the source node.
        height: '',


        // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
        //  View layout defintion.
        structure: null,


        // elasticView: Integer
        // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
        elasticView: -1,


        // singleClickEdit: boolean
        //  Single-click starts editing. Default is double-click
        singleClickEdit: false,


        // selectionMode: String
        //  Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
        //  or 'extended'. Default is 'extended'.
        selectionMode: 'extended',


        // rowSelector: Boolean|String
        //   If set to true, will add a row selector view to this grid. If set to a CSS width, will add
        //   a row selector of that width to this grid.
        rowSelector: '',


        // columnReordering: Boolean
        //   If set to true, will add drag and drop reordering to views with one row of columns.
        columnReordering: false,


        // headerMenu: dijit.Menu
        //   If set to a dijit.Menu, will use this as a context menu for the grid headers.
        headerMenu: null,


        // placeholderLabel: String
        //   Label of placeholders to search for in the header menu to replace with column toggling
        //   menu items.
        placeholderLabel: "GridColumns",

        
        // selectable: Boolean
        //  Set to true if you want to be able to select the text within the grid.
        selectable: false,

        
        // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
        _click: null,

        
        // loadingMessage: String
        // Message that shows while the grid is loading
        loadingMessage: "${loadingState}",


        // errorMessage: String
        // Message that shows when the grid encounters an error loading
        errorMessage: "${errorState}",


        // noDataMessage: String
        // Message that shows if the grid has no data - wrap it in a
        // span with class 'dojoxGridNoData' if you want it to be
        // styled similar to the loading and error messages
        noDataMessage: "",

        
        // escapeHTMLInData: Boolean
        //  This will escape HTML brackets from the data to prevent HTML from
        //   user-inputted data being rendered with may contain JavaScript and result in
        //   XSS attacks. This is true by default, and it is recommended that it remain
        //   true. Setting this to false will allow data to be displayed in the grid without
        //   filtering, and should be only used if it is known that the data won't contain
        //   malicious scripts. If HTML is needed in grid cells, it is recommended that
        //   you use the formatter function to generate the HTML (the output of
        //   formatter functions is not filtered, even with escapeHTMLInData set to true).
        escapeHTMLInData: true,

        
        // formatterScope: Object
        //  An object to execute format functions within. If not set, the
        //  format functions will execute within the scope of the cell that
        //  has a format function.
        formatterScope: null,

        
        // editable: boolean
        // indicates if the grid contains editable cells, default is false
        // set to true if editable cell encountered during rendering
        editable: false,

        
        // private
        sortInfo: 0,
        themeable: true,
        _placeholders: null,


        // _layoutClass: Object
        // The class to use for our layout - can be overridden by grid subclasses
        _layoutClass: dojox.grid._Layout,


        // initialization
        buildRendering: function(){
         this.inherited(arguments);
         if(!this.domNode.getAttribute('tabIndex')){
          this.domNode.tabIndex = "0";
         }
         this.createScroller();
         this.createLayout();
         this.createViews();
         this.createManagers();


         this.createSelection();


         this.connect(this.selection, "onSelected", "onSelected");
         this.connect(this.selection, "onDeselected", "onDeselected");
         this.connect(this.selection, "onChanged", "onSelectionChanged");


         dojox.html.metrics.initOnFontResize();
         this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
         dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
         if (this.selectionMode != "none") {
          dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
         }


         dojo.addClass(this.domNode, this.classTag);
         if(!this.isLeftToRight()){
          dojo.addClass(this.domNode, this.classTag+"Rtl");
         }
        },

        
        postMixInProperties: function(){
         this.inherited(arguments);
         var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
         this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
         this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
         if(this.srcNodeRef && this.srcNodeRef.style.height){
          this.height = this.srcNodeRef.style.height;
         }
         // Call this to update our autoheight to start out
         this._setAutoHeightAttr(this.autoHeight, true);
         this.lastScrollTop = this.scrollTop = 0;
        },

        
        postCreate: function(){
         this._placeholders = [];
         this._setHeaderMenuAttr(this.headerMenu);
         this._setStructureAttr(this.structure);
         this._click = [];
         this.inherited(arguments);
         if(this.domNode && this.autoWidth && this.initialWidth){
          this.domNode.style.width = this.initialWidth;
         }
         if (this.domNode && !this.editable){
          // default value for aria-readonly is false, set to true if grid is not editable
          dojo.attr(this.domNode,"aria-readonly", "true");
         }
        },


        destroy: function(){
         this.domNode.onReveal = null;
         this.domNode.onSizeChange = null;


         // Fixes IE domNode leak
         delete this._click;


         this.edit.destroy();
         delete this.edit;


         this.views.destroyViews();
         if(this.scroller){
          this.scroller.destroy();
          delete this.scroller;
         }
         if(this.focus){
          this.focus.destroy();
          delete this.focus;
         }
         if(this.headerMenu&&this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.inherited(arguments);
        },


        _setAutoHeightAttr: function(ah, skipRender){
         // Calculate our autoheight - turn it into a boolean or an integer
         if(typeof ah == "string"){
          if(!ah || ah == "false"){
           ah = false;
          }else if (ah == "true"){
           ah = true;
          }else{
           ah = window.parseInt(ah, 10);
          }
         }
         if(typeof ah == "number"){
          if(isNaN(ah)){
           ah = false;
          }
          // Autoheight must be at least 1, if it's a number. If it's
          // less than 0, we'll take that to mean "all" rows (same as
          // autoHeight=true - if it is equal to zero, we'll take that
          // to mean autoHeight=false
          if(ah < 0){
           ah = true;
          }else if (ah === 0){
           ah = false;
          }
         }
         this.autoHeight = ah;
         if(typeof ah == "boolean"){
          this._autoHeight = ah;
         }else if(typeof ah == "number"){
          this._autoHeight = (ah >= this.get('rowCount'));
         }else{
          this._autoHeight = false;
         }
         if(this._started && !skipRender){
          this.render();
         }
        },


        _getRowCountAttr: function(){
         return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
          this.invalidated.rowCount : this.rowCount;
        },

        
        textSizeChanged: function(){
         this.render();
        },


        sizeChange: function(){
         this.update();
        },


        createManagers: function(){
         // summary:
         //  create grid managers for various tasks including rows, focus, selection, editing


         // row manager
         this.rows = new dojox.grid._RowManager(this);
         // focus manager
         this.focus = new dojox.grid._FocusManager(this);
         // edit manager
         this.edit = new dojox.grid._EditManager(this);
        },


        createSelection: function(){
         // summary: Creates a new Grid selection manager.


         // selection manager
         this.selection = new dojox.grid.Selection(this);
        },


        createScroller: function(){
         // summary: Creates a new virtual scroller
         this.scroller = new dojox.grid._Scroller();
         this.scroller.grid = this;
         this.scroller.renderRow = dojo.hitch(this, "renderRow");
         this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
        },


        createLayout: function(){
         // summary: Creates a new Grid layout
         this.layout = new this._layoutClass(this);
         this.connect(this.layout, "moveColumn", "onMoveColumn");
        },


        onMoveColumn: function(){
         this.render();
        },

        
        onResizeColumn: function(/*int*/ cellIdx){
         // Called when a column is resized.
        },


        // views
        createViews: function(){
         this.views = new dojox.grid._ViewManager(this);
         this.views.createView = dojo.hitch(this, "createView");
        },


        createView: function(inClass, idx){
         var c = dojo.getObject(inClass);
         var view = new c({ grid: this, index: idx });
         this.viewsNode.appendChild(view.domNode);
         this.viewsHeaderNode.appendChild(view.headerNode);
         this.views.addView(view);
         dojo.attr(this.domNode, "align", dojo._isBodyLtr() ? 'left' : 'right');
         return view;
        },


        buildViews: function(){
         for(var i=0, vs; (vs=this.layout.structure[i]); i++){
          this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
         }
         this.scroller.setContentNodes(this.views.getContentNodes());
        },


        _setStructureAttr: function(structure){
         var s = structure;
         if(s && dojo.isString(s)){
          dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
          s=dojo.getObject(s);
         }
         this.structure = s;
         if(!s){
          if(this.layout.structure){
           s = this.layout.structure;
          }else{
           return;
          }
         }
         this.views.destroyViews();
         this.focus.focusView = null;
         if(s !== this.layout.structure){
          this.layout.setStructure(s);
         }
         this._structureChanged();
        },


        setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
         // summary:
         //  Install a new structure and rebuild the grid.
         dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
         this._setStructureAttr(inStructure);
        },

        
        getColumnTogglingItems: function(){
         // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
         //  added to a menu for toggling columns on and off.
         return dojo.map(this.layout.cells, function(cell){
          if(!cell.menuItems){ cell.menuItems = []; }


          var self = this;
          var item = new dijit.CheckedMenuItem({
           label: cell.name,
           checked: !cell.hidden,
           _gridCell: cell,
           onChange: function(checked){
            if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
             var items = this._gridCell.menuItems;
             if(items.length > 1){
              dojo.forEach(items, function(item){
               if(item !== this){
                item.setAttribute("checked", checked);
               }
              }, this);
             }
             checked = dojo.filter(self.layout.cells, function(c){
              if(c.menuItems.length > 1){
               dojo.forEach(c.menuItems, "item.set('disabled', false);");
              }else{
               c.menuItems[0].set('disabled', false);
              }
              return !c.hidden;
             });
             if(checked.length == 1){
              dojo.forEach(checked[0].menuItems, "item.set('disabled', true);");
             }
            }
           },
           destroy: function(){
            var index = dojo.indexOf(this._gridCell.menuItems, this);
            this._gridCell.menuItems.splice(index, 1);
            delete this._gridCell;
            dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
           }
          });
          cell.menuItems.push(item);
          return item;
         }, this); // dijit.CheckedMenuItem[]
        },


        _setHeaderMenuAttr: function(menu){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           p.unReplace(true);
          });
          this._placeholders = [];
         }
         if(this.headerMenu){
          this.headerMenu.unBindDomNode(this.viewsHeaderNode);
         }
         this.headerMenu = menu;
         if(!menu){ return; }


         this.headerMenu.bindDomNode(this.viewsHeaderNode);
         if(this.headerMenu.getPlaceholders){
          this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
         }
        },


        setHeaderMenu: function(/* dijit.Menu */ menu){
         dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
         this._setHeaderMenuAttr(menu);
        },

        
        setupHeaderMenu: function(){
         if(this._placeholders && this._placeholders.length){
          dojo.forEach(this._placeholders, function(p){
           if(p._replaced){
            p.unReplace(true);
           }
           p.replace(this.getColumnTogglingItems());
          }, this);
         }
        },


        _fetch: function(start){
         this.setScrollTop(0);
        },


        getItem: function(inRowIndex){
         return null;
        },

        
        showMessage: function(message){
         if(message){
          this.messagesNode.innerHTML = message;
          this.messagesNode.style.display = "";
         }else{
          this.messagesNode.innerHTML = "";
          this.messagesNode.style.display = "none";
         }
        },


        _structureChanged: function() {
         this.buildViews();
         if(this.autoRender && this._started){
          this.render();
         }
        },


        hasLayout: function() {
         return this.layout.cells.length;
        },


        // sizing
        resize: function(changeSize, resultSize){
         // summary:
         //  Update the grid's rendering dimensions and resize it

         
         // Calling sizeChange calls update() which calls _resize...so let's
         // save our input values, if any, and use them there when it gets
         // called. This saves us an extra call to _resize(), which can
         // get kind of heavy.
         this._pendingChangeSize = changeSize;
         this._pendingResultSize = resultSize;
         this.sizeChange();
        },


        _getPadBorder: function() {
         this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
         return this._padBorder;
        },


        _getHeaderHeight: function(){
         var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
         vns.height = t + 'px';
         // header heights are reset during measuring so must be normalized after measuring.
         this.views.normalizeHeaderNodeHeight();
         return t;
        },

        
        _resize: function(changeSize, resultSize){
         // Restore our pending values, if any
         changeSize = changeSize || this._pendingChangeSize;
         resultSize = resultSize || this._pendingResultSize;
         delete this._pendingChangeSize;
         delete this._pendingResultSize;
         // if we have set up everything except the DOM, we cannot resize
         if(!this.domNode){ return; }
         var pn = this.domNode.parentNode;
         if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
          return;
         }
         // useful measurement
         var padBorder = this._getPadBorder();
         var hh = undefined;
         var h;
         // grid height
         if(this._autoHeight){
          this.domNode.style.height = 'auto';
         }else if(typeof this.autoHeight == "number"){
          h = hh = this._getHeaderHeight();
          h += (this.scroller.averageRowHeight * this.autoHeight);
          this.domNode.style.height = h + "px";
         }else if(this.domNode.clientHeight <= padBorder.h){
          if(pn == document.body){
           this.domNode.style.height = this.defaultHeight;
          }else if(this.height){
           this.domNode.style.height = this.height;
          }else{
           this.fitTo = "parent";
          }
         }
         // if we are given dimensions, size the grid's domNode to those dimensions
         if(resultSize){
          changeSize = resultSize;
         }
         if(changeSize){
          dojo.marginBox(this.domNode, changeSize);
          this.height = this.domNode.style.height;
          delete this.fitTo;
         }else if(this.fitTo == "parent"){
          h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
          this.domNode.style.height = Math.max(0, h) + "px";
         }

         
         var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });


         if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
          // We need to hide the header, since the Grid is essentially hidden.
          this.viewsHeaderNode.style.display = "none";
         }else{
          // Otherwise, show the header and give it an appropriate height.
          this.viewsHeaderNode.style.display = "block";
          if(!hasFlex && hh === undefined){
           hh = this._getHeaderHeight();
          }
         }
         if(hasFlex){
          hh = undefined;
         }


         // NOTE: it is essential that width be applied before height
         // Header height can only be calculated properly after view widths have been set.
         // This is because flex column width is naturally 0 in Firefox.
         // Therefore prior to width sizing flex columns with spaces are maximally wrapped
         // and calculated to be too tall.
         this.adaptWidth();
         this.adaptHeight(hh);


         this.postresize();
        },


        adaptWidth: function() {
         // private: sets width and position for views and update grid width if necessary
         var doAutoWidth = (!this.initialWidth && this.autoWidth);
         var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
          vw = this.views.arrange(1, w);
         this.views.onEach("adaptWidth");
         if(doAutoWidth){
          this.domNode.style.width = vw + "px";
         }
        },


        adaptHeight: function(inHeaderHeight){
         // private: measures and normalizes header height, then sets view heights, and then updates scroller
         // content extent
         var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
         var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
         this.views.onEach('setSize', [0, h]);
         this.views.onEach('adaptHeight');
         if(!this._autoHeight){
          var numScroll = 0, numNoScroll = 0;
          var noScrolls = dojo.filter(this.views.views, function(v){
           var has = v.hasHScrollbar();
           if(has){ numScroll++; }else{ numNoScroll++; }
           return (!has);
          });
          if(numScroll > 0 && numNoScroll > 0){
           dojo.forEach(noScrolls, function(v){
            v.adaptHeight(true);
           });
          }
         }
         if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
          this.scroller.windowHeight = h;
         }else{
          this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
         }
        },


        // startup
        startup: function(){
         if(this._started){return;}
         this.inherited(arguments);
         if(this.autoRender){
          this.render();
         }
        },


        // render
        render: function(){
         // summary:
         // Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
         // scrolling states, see Update.


         if(!this.domNode){return;}
         if(!this._started){return;}


         if(!this.hasLayout()) {
          this.scroller.init(0, this.keepRows, this.rowsPerPage);
          return;
         }
         //
         this.update = this.defaultUpdate;
         this._render();
        },


        _render: function(){
         this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
         this.prerender();
         this.setScrollTop(0);
         this.postrender();
        },


        prerender: function(){
         // if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
         this.keepRows = this._autoHeight ? 0 : this.keepRows;
         this.scroller.setKeepInfo(this.keepRows);
         this.views.render();
         this._resize();
        },


        postrender: function(){
         this.postresize();
         this.focus.initFocusView();
         // make rows unselectable
         dojo.setSelectable(this.domNode, this.selectable);
        },


        postresize: function(){
         // views are position absolute, so they do not inflate the parent
         if(this._autoHeight){
          var size = Math.max(this.views.measureContent()) + 'px';

          
          this.viewsNode.style.height = size;
         }
        },


        renderRow: function(inRowIndex, inNodes){
         // summary: private, used internally to render rows
         this.views.renderRow(inRowIndex, inNodes, this._skipRowRenormalize);
        },


        rowRemoved: function(inRowIndex){
         // summary: private, used internally to remove rows
         this.views.rowRemoved(inRowIndex);
        },


        invalidated: null,


        updating: false,


        beginUpdate: function(){
         // summary:
         //  Use to make multiple changes to rows while queueing row updating.
         // NOTE: not currently supporting nested begin/endUpdate calls
         this.invalidated = [];
         this.updating = true;
        },


        endUpdate: function(){
         // summary:
         //  Use after calling beginUpdate to render any changes made to rows.
         this.updating = false;
         var i = this.invalidated, r;
         if(i.all){
          this.update();
         }else if(i.rowCount != undefined){
          this.updateRowCount(i.rowCount);
         }else{
          for(r in i){
           this.updateRow(Number(r));
          }
         }
         this.invalidated = [];
        },


        // update
        defaultUpdate: function(){
         // note: initial update calls render and subsequently this function.
         if(!this.domNode){return;}
         if(this.updating){
          this.invalidated.all = true;
          return;
         }
         //this.edit.saveState(inRowIndex);
         this.lastScrollTop = this.scrollTop;
         this.prerender();
         this.scroller.invalidateNodes();
         this.setScrollTop(this.lastScrollTop);
         this.postrender();
         //this.edit.restoreState(inRowIndex);
    • summary
  • dojox.grid._Grid.update

    • type
      Function
    • source: [view]
         this.render();
    • summary
      Update the grid, retaining edit and scrolling states.
  • dojox.grid._Grid.updateRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof Integer)
        Index of the row to render
    • source: [view]
         inRowIndex = Number(inRowIndex);
         if(this.updating){
          this.invalidated[inRowIndex]=true;
         }else{
          this.views.updateRow(inRowIndex);
          this.scroller.rowHeightChanged(inRowIndex);
         }
    • summary
      Render a single row.
  • dojox.grid._Grid.updateRows

    • type
      Function
    • parameters:
      • startIndex: (typeof Integer)
        Index of the starting row to render
      • howMany: (typeof Integer)
        How many rows to update.
    • source: [view]
         startIndex = Number(startIndex);
         howMany = Number(howMany);
         var i;
         if(this.updating){
          for(i=0; i     this.invalidated[i+startIndex]=true;
          }
         }else{
          for(i=0; i     this.views.updateRow(i+startIndex, this._skipRowRenormalize);
          }
          this.scroller.rowHeightChanged(startIndex);
         }
    • summary
      Render consecutive rows at once.
  • dojox.grid._Grid.updateRowCount

    • type
      Function
    • parameters:
      • inRowCount: (typeof int)
        Number of rows in the grid.
    • source: [view]
         if(this.updating){
          this.invalidated.rowCount = inRowCount;
         }else{
          this.rowCount = inRowCount;
          this._setAutoHeightAttr(this.autoHeight, true);
          if(this.layout.cells.length){
           this.scroller.updateRowCount(inRowCount);
          }
          this._resize();
          if(this.layout.cells.length){
           this.setScrollTop(this.scrollTop);
          }
         }
    • summary
      Change the number of rows.
  • dojox.grid._Grid.updateRowStyles

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         this.views.updateRowStyles(inRowIndex);
    • summary
      Update the styles for a row after it's state has changed.
  • dojox.grid._Grid.getRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         if (this.focus.focusView && !(this.focus.focusView instanceof dojox.grid._RowSelector)){
           return this.focus.focusView.rowNodes[inRowIndex];
         }else{ // search through views
          for (var i = 0, cView; (cView = this.views.views[i]); i++) {
           if (!(cView instanceof dojox.grid._RowSelector)) {
            return cView.rowNodes[inRowIndex];
           }
          }
         }
         return null;
    • summary
      find the rowNode that is not a rowSelector
  • dojox.grid._Grid.rowHeightChanged

    • type
      Function
    • parameters:
      • inRowIndex: (typeof Integer)
        index of the row that has changed height
    • source: [view]
         this.views.renormalizeRow(inRowIndex);
         this.scroller.rowHeightChanged(inRowIndex);
    • summary
      Update grid when the height of a row has changed. Row height is handled automatically as rows
      are rendered. Use this function only to update a row's height outside the normal rendering process.
  • dojox.grid._Grid.fastScroll

    • type
      Boolean
    • summary
      flag modifies vertical scrolling behavior. Defaults to true but set to false for slower
      scroll performance but more immediate scrolling feedback
  • dojox.grid._Grid.delayScroll

    • summary
  • dojox.grid._Grid.scrollRedrawThreshold

    • type
      int
    • summary
      pixel distance a user must scroll vertically to trigger grid scrolling.
  • dojox.grid._Grid.scrollTo

    • type
      Function
    • parameters:
      • inTop: (typeof Integer)
        vertical position of the grid in pixels
    • source: [view]
         if(!this.fastScroll){
          this.setScrollTop(inTop);
          return;
         }
         var delta = Math.abs(this.lastScrollTop - inTop);
         this.lastScrollTop = inTop;
         if(delta > this.scrollRedrawThreshold || this.delayScroll){
          this.delayScroll = true;
          this.scrollTop = inTop;
          this.views.setScrollTop(inTop);
          if(this._pendingScroll){
           window.clearTimeout(this._pendingScroll);
          }
          var _this = this;
          this._pendingScroll = window.setTimeout(function(){
           delete _this._pendingScroll;
           _this.finishScrollJob();
          }, 200);
         }else{
          this.setScrollTop(inTop);
         }
    • summary
      Vertically scroll the grid to a given pixel position
  • dojox.grid._Grid.finishScrollJob

    • type
      Function
    • source: [view]
         this.delayScroll = false;
         this.setScrollTop(this.scrollTop);
    • summary
  • dojox.grid._Grid.setScrollTop

    • type
      Function
    • parameters:
      • inTop: (typeof )
    • source: [view]
         this.scroller.scroll(this.views.setScrollTop(inTop));
    • summary
  • dojox.grid._Grid.scrollToRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof Integer)
        grid row index
    • source: [view]
         this.setScrollTop(this.scroller.findScrollTop(inRowIndex) + 1);
    • summary
      Scroll the grid to a specific row.
  • dojox.grid._Grid.styleRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         if(inRowNode){
          this.rows.styleRowNode(inRowIndex, inRowNode);
         }
    • summary
  • dojox.grid._Grid._mouseOut

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         this.rows.setOverRow(-2);
    • summary
  • dojox.grid._Grid.getCell

    • type
      Function
    • parameters:
      • inIndex: (typeof Integer)
        Grid column index of cell to retrieve
    • source: [view]
         return this.layout.cells[inIndex];
    • summary
      Retrieves the cell object for a given grid column.
    • return_summary
      a grid cell
  • dojox.grid._Grid.setCellWidth

    • type
      Function
    • parameters:
      • inIndex: (typeof )
      • inUnitWidth: (typeof )
    • source: [view]
         this.getCell(inIndex).unitWidth = inUnitWidth;
    • summary
  • dojox.grid._Grid.getCellName

    • type
      Function
    • parameters:
      • inCell: (typeof )
    • source: [view]
         return "Cell " + inCell.index; // String
    • summary
      Returns the cell name of a passed cell
    • returns
      String
  • dojox.grid._Grid.canSort

    • type
      Function
    • parameters:
      • inSortInfo: (typeof Integer)
        Sort information, 1-based index of column on which to sort, positive for an ascending sort
        and negative for a descending sort
    • source: [view]
         // summary:
         //  Determines if the grid can be sorted
         // inSortInfo: Integer
         //  Sort information, 1-based index of column on which to sort, positive for an ascending sort
         //   and negative for a descending sort
         // returns: Boolean
         //  True if grid can be sorted on the given column in the given direction
    • summary
      Determines if the grid can be sorted
    • return_summary
      Boolean
      True if grid can be sorted on the given column in the given direction
  • dojox.grid._Grid.sort

    • type
      Function
    • source: [view]
    • summary
  • dojox.grid._Grid.getSortAsc

    • type
      Function
    • parameters:
      • inSortInfo: (typeof )
    • source: [view]
         inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
         return Boolean(inSortInfo > 0); // Boolean
    • summary
      Returns true if grid is sorted in an ascending direction.
    • returns
      Boolean
  • dojox.grid._Grid.getSortIndex

    • type
      Function
    • parameters:
      • inSortInfo: (typeof )
    • source: [view]
         inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
         return Math.abs(inSortInfo) - 1; // Integer
    • summary
      Returns the index of the column on which the grid is sorted
    • returns
      Integer
  • dojox.grid._Grid.setSortIndex

    • type
      Function
    • parameters:
      • inIndex: (typeof Integer)
        Column index on which to sort.
      • inAsc: (typeof Boolean)
        If true, sort the grid in ascending order, otherwise in descending order
    • source: [view]
         var si = inIndex +1;
         if(inAsc != undefined){
          si *= (inAsc ? 1 : -1);
         } else if(this.getSortIndex() == inIndex){
          si = -this.sortInfo;
         }
         this.setSortInfo(si);
    • summary
      Sort the grid on a column in a specified direction
  • dojox.grid._Grid.setSortInfo

    • type
      Function
    • parameters:
      • inSortInfo: (typeof )
    • source: [view]
         if(this.canSort(inSortInfo)){
          this.sortInfo = inSortInfo;
          this.sort();
          this.update();
         }
    • summary
  • dojox.grid._Grid.doKeyEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         e.dispatch = 'do' + e.type;
         this.onKeyEvent(e);
    • summary
  • dojox.grid._Grid._dispatch

    • type
      Function
    • parameters:
      • m: (typeof )
      • e: (typeof )
    • source: [view]
         if(m in this){
          return this[m](e);
         }
         return false;
    • summary
  • dojox.grid._Grid.dispatchKeyEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         this._dispatch(e.dispatch, e);
    • summary
  • dojox.grid._Grid.dispatchContentEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         this.edit.dispatchEvent(e) || e.sourceView.dispatchContentEvent(e) || this._dispatch(e.dispatch, e);
    • summary
  • dojox.grid._Grid.dispatchHeaderEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         e.sourceView.dispatchHeaderEvent(e) || this._dispatch('doheader' + e.type, e);
    • summary
  • dojox.grid._Grid.dokeydown

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         this.onKeyDown(e);
    • summary
  • dojox.grid._Grid.doclick

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onCellClick(e);
         }else{
          this.onRowClick(e);
         }
    • summary
  • dojox.grid._Grid.dodblclick

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onCellDblClick(e);
         }else{
          this.onRowDblClick(e);
         }
    • summary
  • dojox.grid._Grid.docontextmenu

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onCellContextMenu(e);
         }else{
          this.onRowContextMenu(e);
         }
    • summary
  • dojox.grid._Grid.doheaderclick

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onHeaderCellClick(e);
         }else{
          this.onHeaderClick(e);
         }
    • summary
  • dojox.grid._Grid.doheaderdblclick

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onHeaderCellDblClick(e);
         }else{
          this.onHeaderDblClick(e);
         }
    • summary
  • dojox.grid._Grid.doheadercontextmenu

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(e.cellNode){
          this.onHeaderCellContextMenu(e);
         }else{
          this.onHeaderContextMenu(e);
         }
    • summary
  • dojox.grid._Grid.doStartEdit

    • type
      Function
    • parameters:
      • inCell: (typeof )
      • inRowIndex: (typeof )
    • source: [view]
         this.onStartEdit(inCell, inRowIndex);
    • summary
  • dojox.grid._Grid.doApplyCellEdit

    • type
      Function
    • parameters:
      • inValue: (typeof )
      • inRowIndex: (typeof )
      • inFieldIndex: (typeof )
    • source: [view]
         this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
    • summary
  • dojox.grid._Grid.doCancelEdit

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         this.onCancelEdit(inRowIndex);
    • summary
  • dojox.grid._Grid.doApplyEdit

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         this.onApplyEdit(inRowIndex);
    • summary
  • dojox.grid._Grid.addRow

    • type
      Function
    • source: [view]
         this.updateRowCount(this.get('rowCount')+1);
    • summary
      Add a row to the grid.
  • dojox.grid._Grid.removeSelectedRows

    • type
      Function
    • source: [view]
         if(this.allItemsSelected){
          this.updateRowCount(0);
         }else{
          this.updateRowCount(Math.max(0, this.get('rowCount') - this.selection.getSelected().length));
         }
         this.selection.clear();
    • summary
      Remove the selected rows from the grid.
  • dojox.grid._Grid.domNode.tabIndex

    • summary
  • dojox.grid._Grid.lastScrollTop

    • summary
  • dojox.grid._Grid.domNode.style.width

    • summary
  • dojox.grid._Grid.domNode.onReveal

    • summary
  • dojox.grid._Grid.domNode.onSizeChange

    • summary
  • dojox.grid._Grid._autoHeight

    • summary
  • dojox.grid._Grid.rows

    • summary
  • dojox.grid._Grid.focus

    • summary
  • dojox.grid._Grid.edit

    • summary
  • dojox.grid._Grid.selection

    • summary
  • dojox.grid._Grid.scroller

    • summary
  • dojox.grid._Grid.scroller.grid

    • summary
  • dojox.grid._Grid.scroller.renderRow

    • summary
  • dojox.grid._Grid.scroller.removeRow

    • summary
  • dojox.grid._Grid.layout

    • summary
  • dojox.grid._Grid.views

    • summary
  • dojox.grid._Grid.views.createView

    • summary
  • dojox.grid._Grid.focus.focusView

    • summary
  • dojox.grid._Grid.messagesNode.innerHTML

    • summary
  • dojox.grid._Grid.messagesNode.style.display

    • summary
  • dojox.grid._Grid._pendingChangeSize

    • summary
  • dojox.grid._Grid._pendingResultSize

    • summary
  • dojox.grid._Grid._padBorder

    • summary
  • dojox.grid._Grid.domNode.style.height

    • summary
  • dojox.grid._Grid.fitTo

    • summary
  • dojox.grid._Grid._parentContentBoxHeight

    • summary
  • dojox.grid._Grid.viewsHeaderNode.style.display

    • summary
  • dojox.grid._Grid.scroller.windowHeight

    • summary
  • dojox.grid._Grid.viewsNode.style.height

    • summary
  • dojox.grid._Grid.invalidated.all

    • summary
  • dojox.grid._Grid.invalidated.rowCount

    • summary
  • dojox.grid._Grid.scrollTop

    • summary
  • dojox.grid._Grid._pendingScroll

    • summary
  • dojo.isCopyKey

    • summary
  • dojox.grid.__CellDef

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
    • summary
  • dojox.grid.__CellDef.name

    • type
      String?
    • summary
      The text to use in the header of the grid for this cell.
  • dojox.grid.__CellDef.value

    • type
      String?
    • summary
      If &quot;get&quot; is not specified, this is used as the data for the cell.
      defaultValue: String?
      If &quot;get&quot; and &quot;value&quot; aren't specified or if &quot;get&quot; returns an undefined
      value, this is used as the data for the cell.  &quot;formatter&quot; is not run
      on this if &quot;get&quot; returns an undefined value.
  • dojox.grid.__CellDef.get

    • type
      Function?
    • summary
      function(rowIndex){} rowIndex is of type Integer.  This
      function will be called when a cell	requests data.  Returns the
      unformatted data for the cell.
  • dojox.grid.__CellDef.formatter

    • type
      Function?
    • summary
      function(data, rowIndex){} data is of type anything, rowIndex
      is of type Integer.  This function will be called after the cell
      has its data but before it passes it back to the grid to render.
      Returns the formatted version of the cell's data.
  • dojox.grid.__CellDef.type

    • type
      dojox.grid.cells._Base|Function?
    • summary
      TODO
  • dojox.grid.__CellDef.editable

    • type
      Boolean?
    • summary
      Whether this cell should be editable or not.
  • dojox.grid.__CellDef.hidden

    • type
      Boolean?
    • summary
      If true, the cell will not be displayed.
      noresize: Boolean?
      If true, the cell will not be able to be resized.
  • dojox.grid.__CellDef.width

    • type
      Integer|String?
    • summary
      A CSS size.  If it's an Integer, the width will be in em's.
  • dojox.grid.__CellDef.colSpan

    • type
      Integer?
    • summary
      How many columns to span this cell.  Will not work in the first
      sub-row of cells.
  • dojox.grid.__CellDef.rowSpan

    • type
      Integer?
    • summary
      How many sub-rows to span this cell.
  • dojox.grid.__CellDef.styles

    • type
      String?
    • summary
      A string of styles to apply to both the header cell and main
      grid cells.  Must end in a ';'.
  • dojox.grid.__CellDef.headerStyles

    • type
      String?
    • summary
      A string of styles to apply to just the header cell.  Must end
      in a ';'
  • dojox.grid.__CellDef.cellStyles

    • type
      String?
    • summary
      A string of styles to apply to just the main grid cells.  Must
      end in a ';'
  • dojox.grid.__CellDef.classes

    • type
      String?
    • summary
      A space separated list of classes to apply to both the header
      cell and the main grid cells.
  • dojox.grid.__CellDef.headerClasses

    • type
      String?
    • summary
      A space separated list of classes to apply to just the header
      cell.
  • dojox.grid.__CellDef.cellClasses

    • type
      String?
    • summary
      A space separated list of classes to apply to just the main
      grid cells.
  • dojox.grid.__CellDef.attrs

    • type
      String?
    • summary
      A space separated string of attribute='value' pairs to add to
      the header cell element and main grid cell elements.
  • dojox.grid.__ViewDef

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._Grid");


      dojo.require("dijit.dijit");
      dojo.require("dijit.Menu");


      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");
      dojo.require("dojox.grid._Scroller");
      dojo.require("dojox.grid._Layout");
      dojo.require("dojox.grid._View");
      dojo.require("dojox.grid._ViewManager");
      dojo.require("dojox.grid._RowManager");
      dojo.require("dojox.grid._FocusManager");
      dojo.require("dojox.grid._EditManager");
      dojo.require("dojox.grid.Selection");
      dojo.require("dojox.grid._RowSelector");
      dojo.require("dojox.grid._Events");




      dojo.requireLocalization("dijit", "loading");


      (function(){
       // NOTE: this is for backwards compatibility with Dojo 1.3
       if(!dojo.isCopyKey){
        dojo.isCopyKey = dojo.dnd.getCopyKeyState;
       }

       
       dojox.grid.__CellDef = function(){
        // name: String?
        //  The text to use in the header of the grid for this cell.
        // get: Function?
        //  function(rowIndex){} rowIndex is of type Integer. This
        //  function will be called when a cell requests data. Returns the
        //  unformatted data for the cell.
        // value: String?
        //  If "get" is not specified, this is used as the data for the cell.
        // defaultValue: String?
        //  If "get" and "value" aren't specified or if "get" returns an undefined
        //  value, this is used as the data for the cell. "formatter" is not run
        //  on this if "get" returns an undefined value.
        // formatter: Function?
        //  function(data, rowIndex){} data is of type anything, rowIndex
        //  is of type Integer. This function will be called after the cell
        //  has its data but before it passes it back to the grid to render.
        //  Returns the formatted version of the cell's data.
        // type: dojox.grid.cells._Base|Function?
        //  TODO
        // editable: Boolean?
        //  Whether this cell should be editable or not.
        // hidden: Boolean?
        //  If true, the cell will not be displayed.
        // noresize: Boolean?
        //  If true, the cell will not be able to be resized.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's.
        // colSpan: Integer?
        //  How many columns to span this cell. Will not work in the first
        //  sub-row of cells.
        // rowSpan: Integer?
        //  How many sub-rows to span this cell.
        // styles: String?
        //  A string of styles to apply to both the header cell and main
        //  grid cells. Must end in a ';'.
        // headerStyles: String?
        //  A string of styles to apply to just the header cell. Must end
        //  in a ';'
        // cellStyles: String?
        //  A string of styles to apply to just the main grid cells. Must
        //  end in a ';'
        // classes: String?
        //  A space separated list of classes to apply to both the header
        //  cell and the main grid cells.
        // headerClasses: String?
        //  A space separated list of classes to apply to just the header
        //  cell.
        // cellClasses: String?
        //  A space separated list of classes to apply to just the main
        //  grid cells.
        // attrs: String?
        //  A space separated string of attribute='value' pairs to add to
        //  the header cell element and main grid cell elements.
        this.name = name;
        this.value = value;
        this.get = get;
        this.formatter = formatter;
        this.type = type;
        this.editable = editable;
        this.hidden = hidden;
        this.width = width;
        this.colSpan = colSpan;
        this.rowSpan = rowSpan;
        this.styles = styles;
        this.headerStyles = headerStyles;
        this.cellStyles = cellStyles;
        this.classes = classes;
        this.headerClasses = headerClasses;
        this.cellClasses = cellClasses;
        this.attrs = attrs;
       }

       



       
       dojox.grid.__ViewDef = function(){
        // noscroll: Boolean?
        //  If true, no scrollbars will be rendered without scrollbars.
        // width: Integer|String?
        //  A CSS size. If it's an Integer, the width will be in em's. If
        //  "noscroll" is true, this value is ignored.
        // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
        //  The structure of the cells within this grid.
        // type: String?
        //  A string containing the constructor of a subclass of
        //  dojox.grid._View. If this is not specified, dojox.grid._View
        //  is used.
        // defaultCell: dojox.grid.__CellDef?
        //  A cell definition with default values for all cells in this view. If
        //  a property is defined in a cell definition in the "cells" array and
        //  this property, the cell definition's property will override this
        //  property's property.
        // onBeforeRow: Function?
        //  function(rowIndex, cells){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]]. This function is called
        //  before each row of data is rendered. Before the header is
        //  rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        // onAfterRow: Function?
        //  function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
        //  is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
        //  This function is called after each row of data is rendered. After the
        //  header is rendered, rowIndex will be -1. "cells" is a reference to the
        //  internal structure of this view's cells so any changes you make to
        //  it will persist between calls.
        this.noscroll = noscroll;
        this.width = width;
        this.cells = cells;
        this.type = type;
        this.defaultCell = defaultCell;
        this.onBeforeRow = onBeforeRow;
        this.onAfterRow = onAfterRow;
    • summary
  • dojox.grid.__ViewDef.noscroll

    • type
      Boolean?
    • summary
      If true, no scrollbars will be rendered without scrollbars.
  • dojox.grid.__ViewDef.width

    • type
      Integer|String?
    • summary
      A CSS size.  If it's an Integer, the width will be in em's. If
      &quot;noscroll&quot; is true, this value is ignored.
  • dojox.grid.__ViewDef.cells

    • type
      dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
    • summary
      The structure of the cells within this grid.
  • dojox.grid.__ViewDef.type

    • type
      String?
    • summary
      A string containing the constructor of a subclass of
      dojox.grid._View.  If this is not specified, dojox.grid._View
      is used.
  • dojox.grid.__ViewDef.defaultCell

    • type
      dojox.grid.__CellDef?
    • summary
      A cell definition with default values for all cells in this view.  If
      a property is defined in a cell definition in the &quot;cells&quot; array and
      this property, the cell definition's property will override this
      property's property.
  • dojox.grid.__ViewDef.onBeforeRow

    • type
      Function?
    • summary
      function(rowIndex, cells){} rowIndex is of type Integer, cells
      is of type Array[dojox.grid.__CellDef[]].  This function is called
      before each row of data is rendered.  Before the header is
      rendered, rowIndex will be -1.  &quot;cells&quot; is a reference to the
      internal structure of this view's cells so any changes you make to
      it will persist between calls.
  • dojox.grid.__ViewDef.onAfterRow

    • type
      Function?
    • summary
      function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
      is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
      This function is called	after each row of data is rendered.  After the
      header is rendered, rowIndex will be -1.  &quot;cells&quot; is a reference to the
      internal structure of this view's cells so any changes you make to
      it will persist between calls.
  • dojox.grid._Grid.markupFactory

    • type
      Function
    • parameters:
      • props: (typeof )
      • node: (typeof )
      • ctor: (typeof )
      • cellFunc: (typeof )
    • source: [view]
        var d = dojo;
        var widthFromAttr = function(n){
         var w = d.attr(n, "width")||"auto";
         if((w != "auto")&&(w.slice(-2) != "em")&&(w.slice(-1) != "%")){
          w = parseInt(w, 10)+"px";
         }
         return w;
        };
        // if(!props.store){ console.debug("no store!"); }
        // if a structure isn't referenced, do we have enough
        // data to try to build one automatically?
        if( !props.structure &&
         node.nodeName.toLowerCase() == "table"){


         // try to discover a structure
         props.structure = d.query("> colgroup", node).map(function(cg){
          var sv = d.attr(cg, "span");
          var v = {
           noscroll: (d.attr(cg, "noscroll") == "true") ? true : false,
           __span: (!!sv ? parseInt(sv, 10) : 1),
           cells: []
          };
          if(d.hasAttr(cg, "width")){
           v.width = widthFromAttr(cg);
          }
          return v; // for vendetta
         });
         if(!props.structure.length){
          props.structure.push({
           __span: Infinity,
           cells: [] // catch-all view
          });
         }
         // check to see if we're gonna have more than one view


         // for each tr in our th, create a row of cells
         d.query("thead > tr", node).forEach(function(tr, tr_idx){
          var cellCount = 0;
          var viewIdx = 0;
          var lastViewIdx;
          var cView = null;
          d.query("> th", tr).map(function(th){
           // what view will this cell go into?


           // NOTE:
           //  to prevent extraneous iteration, we start counters over
           //  for each row, incrementing over the surface area of the
           //  structure that colgroup processing generates and
           //  creating cell objects for each to place into those
           //  cell groups. There's a lot of state-keepking logic
           //  here, but it is what it has to be.
           if(!cView){ // current view book keeping
            lastViewIdx = 0;
            cView = props.structure[0];
           }else if(cellCount >= (lastViewIdx+cView.__span)){
            viewIdx++;
            // move to allocating things into the next view
            lastViewIdx += cView.__span;
            var lastView = cView;
            cView = props.structure[viewIdx];
           }


           // actually define the cell from what markup hands us
           var cell = {
            name: d.trim(d.attr(th, "name")||th.innerHTML),
            colSpan: parseInt(d.attr(th, "colspan")||1, 10),
            type: d.trim(d.attr(th, "cellType")||""),
            id: d.trim(d.attr(th,"id")||"")
           };
           cellCount += cell.colSpan;
           var rowSpan = d.attr(th, "rowspan");
           if(rowSpan){
            cell.rowSpan = rowSpan;
           }
           if(d.hasAttr(th, "width")){
            cell.width = widthFromAttr(th);
           }
           if(d.hasAttr(th, "relWidth")){
            cell.relWidth = window.parseInt(dojo.attr(th, "relWidth"), 10);
           }
           if(d.hasAttr(th, "hidden")){
            cell.hidden = (d.attr(th, "hidden") == "true" || d.attr(th, "hidden") === true/*always boolean true in Chrome*/);
           }


           if(cellFunc){
            cellFunc(th, cell);
           }


           cell.type = cell.type ? dojo.getObject(cell.type) : dojox.grid.cells.Cell;


           if(cell.type && cell.type.markupFactory){
            cell.type.markupFactory(th, cell);
           }


           if(!cView.cells[tr_idx]){
            cView.cells[tr_idx] = [];
           }
           cView.cells[tr_idx].push(cell);
          });
         });
        }


        return new ctor(props, node);
    • returns
      for vendetta
    • summary
  • dojox.grid

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary