dojox/grid/_View.js

  • Provides:

    • dojox.grid._View
  • Requires:

    • dijit._Widget in common in project dijit
    • dijit._Templated in common in project dijit
    • dojox.grid._Builder in common
    • dojox.html.metrics in common
    • dojox.grid.util in common
    • dojo.dnd.Source in common in project dojo
    • dojo.dnd.Manager in common in project dojo
  • dojox.grid._View

    • type
      Function
    • chains:
      • dijit._Widget: (prototype)
      • dijit._Widget: (call)
      • dijit._Templated: (call)
    • mixins:
      • dijit._Templated.prototype: (prototype)
    • summary
      A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
      Grid creates views automatically based on grid's layout structure.
      Users should typically not need to access individual views directly.
  • dojox.grid._View.defaultWidth

    • type
      String
    • summary
      Default width of the view
  • dojox.grid._View.viewWidth

    • type
      String
    • summary
      Width for the view, in valid css unit
  • dojox.grid._View.templatePath

    • summary
  • dojox.grid._View.themeable

    • summary
  • dojox.grid._View.classTag

    • summary
  • dojox.grid._View.marginBottom

    • summary
  • dojox.grid._View.rowPad

    • summary
  • dojox.grid._View._togglingColumn

    • type
      int
    • summary
      Width of the column being toggled (-1 for none)
  • dojox.grid._View._headerBuilderClass

    • type
      Object
    • summary
      The class to use for our header builder
  • dojox.grid._View._contentBuilderClass

    • type
      Object
    • summary
      The class to use for our content builder
  • dojox.grid._View.postMixInProperties

    • type
      Function
    • source: [view]
         this.rowNodes = {};
    • summary
  • dojox.grid._View.postCreate

    • type
      Function
    • source: [view]
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
    • summary
  • dojox.grid._View.destroy

    • type
      Function
    • source: [view]
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
    • summary
  • dojox.grid._View.focus

    • type
      Function
    • source: [view]
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
    • summary
  • dojox.grid._View.setStructure

    • type
      Function
    • parameters:
      • inStructure: (typeof )
    • source: [view]
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
    • summary
  • dojox.grid._View._cleanupRowWidgets

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
    • summary
  • dojox.grid._View.onBeforeRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • cells: (typeof )
    • source: [view]
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
    • summary
  • dojox.grid._View.onAfterRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • cells: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
    • summary
  • dojox.grid._View.testFlexCells

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
        },

        
        onBeforeRow: function(inRowIndex, cells){
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
        },

        
        onAfterRow: function(inRowIndex, cells, inRowNode){
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
        },


        testFlexCells: function(){
         // FIXME: cheater, this function does double duty as initializer and tester
         this.flexCells = false;
         for(var j=0, row; (row=this.structure.cells[j]); j++){
          for(var i=0, cell; (cell=row[i]); i++){
           cell.view = this;
           this.flexCells = this.flexCells || cell.isFlex();
          }
         }
         return this.flexCells;
    • summary
  • dojox.grid._View.updateStructure

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
        },

        
        onBeforeRow: function(inRowIndex, cells){
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
        },

        
        onAfterRow: function(inRowIndex, cells, inRowNode){
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
        },


        testFlexCells: function(){
         // FIXME: cheater, this function does double duty as initializer and tester
         this.flexCells = false;
         for(var j=0, row; (row=this.structure.cells[j]); j++){
          for(var i=0, cell; (cell=row[i]); i++){
           cell.view = this;
           this.flexCells = this.flexCells || cell.isFlex();
          }
         }
         return this.flexCells;
        },


        updateStructure: function(){
         // header builder needs to update table map
         this.header.update();
         // content builder needs to update markup cache
         this.content.update();
    • summary
  • dojox.grid._View.getScrollbarWidth

    • type
      Function
    • source: [view]
         var hasScrollSpace = this.hasVScrollbar();
         var overflow = dojo.style(this.scrollboxNode, "overflow");
         if(this.noscroll || !overflow || overflow == "hidden"){
          hasScrollSpace = false;
         }else if(overflow == "scroll"){
          hasScrollSpace = true;
         }
         return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
    • returns
      Integer
    • summary
  • dojox.grid._View.getColumnsWidth

    • type
      Function
    • source: [view]
         var h = this.headerContentNode;
         return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
    • returns
      Integer
    • summary
  • dojox.grid._View.setColumnsWidth

    • type
      Function
    • parameters:
      • width: (typeof )
    • source: [view]
         this.headerContentNode.firstChild.style.width = width + 'px';
         if(this.viewWidth){
          this.viewWidth = width + 'px';
         }
    • summary
  • dojox.grid._View.getWidth

    • type
      Function
    • source: [view]
         return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
    • returns
      String
    • summary
  • dojox.grid._View.getContentWidth

    • type
      Function
    • source: [view]
         return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
    • returns
      String
    • summary
  • dojox.grid._View.render

    • type
      Function
    • source: [view]
         this.scrollboxNode.style.height = '';
         this.renderHeader();
         if(this._togglingColumn >= 0){
          this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
          this._togglingColumn = -1;
         }
         var cells = this.grid.layout.cells;
         var getSibling = dojo.hitch(this, function(node, before){
          !dojo._isBodyLtr() && (before = !before);
          var inc = before?-1:1;
          var idx = this.header.getCellNodeIndex(node) + inc;
          var cell = cells[idx];
          while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
           idx += inc;
           cell = cells[idx];
          }
          if(cell){
           return cell.getHeaderNode();
          }
          return null;
         });
         if(this.grid.columnReordering && this.simpleStructure){
          if(this.source){
           this.source.destroy();
          }

          
          // Create the top and bottom markers
          var bottomMarkerId = "dojoxGrid_bottomMarker";
          var topMarkerId = "dojoxGrid_topMarker";
          if(this.bottomMarker){
           dojo.destroy(this.bottomMarker);
          }
          this.bottomMarker = dojo.byId(bottomMarkerId);
          if(this.topMarker){
           dojo.destroy(this.topMarker);
          }
          this.topMarker = dojo.byId(topMarkerId);
          if (!this.bottomMarker) {
           this.bottomMarker = dojo.create("div", {
            "id": bottomMarkerId,
            "class": "dojoxGridColPlaceBottom"
           }, dojo.body());
           this._hide(this.bottomMarker);



           
           this.topMarker = dojo.create("div", {
            "id": topMarkerId,
            "class": "dojoxGridColPlaceTop"
           }, dojo.body());
           this._hide(this.topMarker);
          }
          this.arrowDim = dojo.contentBox(this.bottomMarker);


          var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;

          
          this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
           horizontal: true,
           accept: [ "gridColumn_" + this.grid.id ],
           viewIndex: this.index,
           generateText: false,
           onMouseDown: dojo.hitch(this, function(e){
            this.header.decorateEvent(e);
            if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
             this.header.canResize(e) && !this.header.moveable){
             this.header.beginColumnResize(e);
            }else{
             if(this.grid.headerMenu){
              this.grid.headerMenu.onCancel(true);
             }
             // IE reports a left click as 1, where everything else reports 0
             if(e.button === (dojo.isIE ? 1 : 0)){
              dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
             }
            }
           }),
           onMouseOver: dojo.hitch(this, function(e){
            var src = this.source;
            if(src._getChildByEvent(e)){
             dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
            }
           }),
           _markTargetAnchor: dojo.hitch(this, function(before){
            var src = this.source;
            if(src.current == src.targetAnchor && src.before == before){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);

            
            var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
            var endAdd = 0;


            if (!target) {
             target = src.targetAnchor;
             endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
            }


            // NOTE: this is for backwards compatibility with Dojo 1.3
            var pos = (dojo.position||dojo._abs)(target, true);
            var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);


            dojo.style(this.bottomMarker, "visibility", "visible");
            dojo.style(this.topMarker, "visibility", "visible");
            dojo.style(this.bottomMarker, {
             "left": left + "px",
             "top" : (headerHeight + pos.y) + "px"
            });


            dojo.style(this.topMarker, {
             "left": left + "px",
             "top" : (pos.y - this.arrowDim.h) + "px"
            });


            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
           }),
           _unmarkTargetAnchor: dojo.hitch(this, function(){
            var src = this.source;
            if(!src.targetAnchor){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
            dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
           }),
           destroy: dojo.hitch(this, function(){
            dojo.disconnect(this._source_conn);
            dojo.unsubscribe(this._source_sub);
            dojo.dnd.Source.prototype.destroy.call(this.source);
            if(this.bottomMarker){
             dojo.destroy(this.bottomMarker);
             delete this.bottomMarker;
            }
            if(this.topMarker){
             dojo.destroy(this.topMarker);
             delete this.topMarker;
            }
           }),
           onDndCancel: dojo.hitch(this, function(){
            dojo.dnd.Source.prototype.onDndCancel.call(this.source);
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
           })
          });


          this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
          this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
          this.source.startup();
         }
    • chains:
      • dojo.dnd.Source.prototype.onMouseDown: (call)
      • dojo.dnd.Source.prototype.onMouseOver: (call)
      • dojo.dnd.Source.prototype._markTargetAnchor: (call)
      • dojo.dnd.Source.prototype._unmarkTargetAnchor: (call)
      • dojo.dnd.Source.prototype.destroy: (call)
      • dojo.dnd.Source.prototype.onDndCancel: (call)
    • summary
  • dojox.grid._View._hide

    • type
      Function
    • parameters:
      • node: (typeof )
    • source: [view]
         dojo.style(node, {
          left: "-10000px",
          top: "-10000px",
          "visibility": "hidden"
         });
    • summary
  • dojox.grid._View._onDndDropBefore

    • type
      Function
    • parameters:
      • source: (typeof )
      • nodes: (typeof )
      • copy: (typeof )
    • source: [view]
         if(dojo.dnd.manager().target !== this.source){
          return;
         }
         this.source._targetNode = this.source.targetAnchor;
         this.source._beforeTarget = this.source.before;
         var views = this.grid.views.views;
         var srcView = views[source.viewIndex];
         var tgtView = views[this.index];
         if(tgtView != srcView){
          srcView.convertColPctToFixed();
          tgtView.convertColPctToFixed();
         }
    • summary
  • dojox.grid._View._onDndDrop

    • type
      Function
    • parameters:
      • source: (typeof )
      • nodes: (typeof )
      • copy: (typeof )
    • source: [view]
         if(dojo.dnd.manager().target !== this.source){
          if(dojo.dnd.manager().source === this.source){
           this._removingColumn = true;
          }
          return;
         }
         this._hide(this.bottomMarker);
         this._hide(this.topMarker);


         var getIdx = function(n){
          return n ? dojo.attr(n, "idx") : null;
         };
         var w = dojo.marginBox(nodes[0]).w;
         if(source.viewIndex !== this.index){
          var views = this.grid.views.views;
          var srcView = views[source.viewIndex];
          var tgtView = views[this.index];
          if(srcView.viewWidth && srcView.viewWidth != "auto"){
           srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
          }
          if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
           tgtView.setColumnsWidth(tgtView.getColumnsWidth());
          }
         }
         var stn = this.source._targetNode;
         var stb = this.source._beforeTarget;
         !dojo._isBodyLtr() && (stb = !stb);
         var layout = this.grid.layout;
         var idx = this.index;
         delete this.source._targetNode;
         delete this.source._beforeTarget;

         
         layout.moveColumn(
          source.viewIndex,
          idx,
          getIdx(nodes[0]),
          getIdx(stn),
          stb);
    • summary
  • dojox.grid._View.renderHeader

    • type
      Function
    • source: [view]
         this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
         if(this.flexCells){
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
    • summary
  • dojox.grid._View._getHeaderContent

    • type
      Function
    • parameters:
      • inCell: (typeof )
    • source: [view]
         var n = inCell.name || inCell.grid.getCellName(inCell);
         var ret = [ '
      ');
         }else{
          ret = ret.concat([ ' ',
             inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
             '">
      ',
             inCell.grid.sortInfo > 0 ? '▲' : '▼',
             '
      ',
             '
      ']);
         }
         ret = ret.concat([n, '
      ']);
         return ret.join('');
    • summary
  • dojox.grid._View.resize

    • type
      Function
    • source: [view]
         this.adaptHeight();
         this.adaptWidth();
    • summary
  • dojox.grid._View.hasHScrollbar

    • type
      Function
    • parameters:
      • reset: (typeof )
    • source: [view]
         var hadScroll = this._hasHScroll||false;
         if(this._hasHScroll == undefined || reset){
          if(this.noscroll){
           this._hasHScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasHScroll = false;
           }else if(style == "scroll"){
            this._hasHScroll = true;
           }else{
            this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
           }
          }
         }
         if(hadScroll !== this._hasHScroll){
          this.grid.update();
         }
         return this._hasHScroll; // Boolean
    • returns
      Boolean
    • summary
  • dojox.grid._View.hasVScrollbar

    • type
      Function
    • parameters:
      • reset: (typeof )
    • source: [view]
         var hadScroll = this._hasVScroll||false;
         if(this._hasVScroll == undefined || reset){
          if(this.noscroll){
           this._hasVScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasVScroll = false;
           }else if(style == "scroll"){
            this._hasVScroll = true;
           }else{
            this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
           }
          }
         }
         if(hadScroll !== this._hasVScroll){
          this.grid.update();
         }
         return this._hasVScroll; // Boolean
    • returns
      Boolean
    • summary
  • dojox.grid._View.convertColPctToFixed

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
        },

        
        onBeforeRow: function(inRowIndex, cells){
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
        },

        
        onAfterRow: function(inRowIndex, cells, inRowNode){
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
        },


        testFlexCells: function(){
         // FIXME: cheater, this function does double duty as initializer and tester
         this.flexCells = false;
         for(var j=0, row; (row=this.structure.cells[j]); j++){
          for(var i=0, cell; (cell=row[i]); i++){
           cell.view = this;
           this.flexCells = this.flexCells || cell.isFlex();
          }
         }
         return this.flexCells;
        },


        updateStructure: function(){
         // header builder needs to update table map
         this.header.update();
         // content builder needs to update markup cache
         this.content.update();
        },


        getScrollbarWidth: function(){
         var hasScrollSpace = this.hasVScrollbar();
         var overflow = dojo.style(this.scrollboxNode, "overflow");
         if(this.noscroll || !overflow || overflow == "hidden"){
          hasScrollSpace = false;
         }else if(overflow == "scroll"){
          hasScrollSpace = true;
         }
         return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
        },


        getColumnsWidth: function(){
         var h = this.headerContentNode;
         return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
        },


        setColumnsWidth: function(width){
         this.headerContentNode.firstChild.style.width = width + 'px';
         if(this.viewWidth){
          this.viewWidth = width + 'px';
         }
        },


        getWidth: function(){
         return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
        },


        getContentWidth: function(){
         return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
        },


        render: function(){
         this.scrollboxNode.style.height = '';
         this.renderHeader();
         if(this._togglingColumn >= 0){
          this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
          this._togglingColumn = -1;
         }
         var cells = this.grid.layout.cells;
         var getSibling = dojo.hitch(this, function(node, before){
          !dojo._isBodyLtr() && (before = !before);
          var inc = before?-1:1;
          var idx = this.header.getCellNodeIndex(node) + inc;
          var cell = cells[idx];
          while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
           idx += inc;
           cell = cells[idx];
          }
          if(cell){
           return cell.getHeaderNode();
          }
          return null;
         });
         if(this.grid.columnReordering && this.simpleStructure){
          if(this.source){
           this.source.destroy();
          }

          
          // Create the top and bottom markers
          var bottomMarkerId = "dojoxGrid_bottomMarker";
          var topMarkerId = "dojoxGrid_topMarker";
          if(this.bottomMarker){
           dojo.destroy(this.bottomMarker);
          }
          this.bottomMarker = dojo.byId(bottomMarkerId);
          if(this.topMarker){
           dojo.destroy(this.topMarker);
          }
          this.topMarker = dojo.byId(topMarkerId);
          if (!this.bottomMarker) {
           this.bottomMarker = dojo.create("div", {
            "id": bottomMarkerId,
            "class": "dojoxGridColPlaceBottom"
           }, dojo.body());
           this._hide(this.bottomMarker);



           
           this.topMarker = dojo.create("div", {
            "id": topMarkerId,
            "class": "dojoxGridColPlaceTop"
           }, dojo.body());
           this._hide(this.topMarker);
          }
          this.arrowDim = dojo.contentBox(this.bottomMarker);


          var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;

          
          this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
           horizontal: true,
           accept: [ "gridColumn_" + this.grid.id ],
           viewIndex: this.index,
           generateText: false,
           onMouseDown: dojo.hitch(this, function(e){
            this.header.decorateEvent(e);
            if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
             this.header.canResize(e) && !this.header.moveable){
             this.header.beginColumnResize(e);
            }else{
             if(this.grid.headerMenu){
              this.grid.headerMenu.onCancel(true);
             }
             // IE reports a left click as 1, where everything else reports 0
             if(e.button === (dojo.isIE ? 1 : 0)){
              dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
             }
            }
           }),
           onMouseOver: dojo.hitch(this, function(e){
            var src = this.source;
            if(src._getChildByEvent(e)){
             dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
            }
           }),
           _markTargetAnchor: dojo.hitch(this, function(before){
            var src = this.source;
            if(src.current == src.targetAnchor && src.before == before){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);

            
            var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
            var endAdd = 0;


            if (!target) {
             target = src.targetAnchor;
             endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
            }


            // NOTE: this is for backwards compatibility with Dojo 1.3
            var pos = (dojo.position||dojo._abs)(target, true);
            var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);


            dojo.style(this.bottomMarker, "visibility", "visible");
            dojo.style(this.topMarker, "visibility", "visible");
            dojo.style(this.bottomMarker, {
             "left": left + "px",
             "top" : (headerHeight + pos.y) + "px"
            });


            dojo.style(this.topMarker, {
             "left": left + "px",
             "top" : (pos.y - this.arrowDim.h) + "px"
            });


            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
           }),
           _unmarkTargetAnchor: dojo.hitch(this, function(){
            var src = this.source;
            if(!src.targetAnchor){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
            dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
           }),
           destroy: dojo.hitch(this, function(){
            dojo.disconnect(this._source_conn);
            dojo.unsubscribe(this._source_sub);
            dojo.dnd.Source.prototype.destroy.call(this.source);
            if(this.bottomMarker){
             dojo.destroy(this.bottomMarker);
             delete this.bottomMarker;
            }
            if(this.topMarker){
             dojo.destroy(this.topMarker);
             delete this.topMarker;
            }
           }),
           onDndCancel: dojo.hitch(this, function(){
            dojo.dnd.Source.prototype.onDndCancel.call(this.source);
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
           })
          });


          this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
          this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
          this.source.startup();
         }
        },

        
        _hide: function(node){
         dojo.style(node, {
          left: "-10000px",
          top: "-10000px",
          "visibility": "hidden"
         });
        },


        _onDndDropBefore: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          return;
         }
         this.source._targetNode = this.source.targetAnchor;
         this.source._beforeTarget = this.source.before;
         var views = this.grid.views.views;
         var srcView = views[source.viewIndex];
         var tgtView = views[this.index];
         if(tgtView != srcView){
          srcView.convertColPctToFixed();
          tgtView.convertColPctToFixed();
         }
        },


        _onDndDrop: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          if(dojo.dnd.manager().source === this.source){
           this._removingColumn = true;
          }
          return;
         }
         this._hide(this.bottomMarker);
         this._hide(this.topMarker);


         var getIdx = function(n){
          return n ? dojo.attr(n, "idx") : null;
         };
         var w = dojo.marginBox(nodes[0]).w;
         if(source.viewIndex !== this.index){
          var views = this.grid.views.views;
          var srcView = views[source.viewIndex];
          var tgtView = views[this.index];
          if(srcView.viewWidth && srcView.viewWidth != "auto"){
           srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
          }
          if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
           tgtView.setColumnsWidth(tgtView.getColumnsWidth());
          }
         }
         var stn = this.source._targetNode;
         var stb = this.source._beforeTarget;
         !dojo._isBodyLtr() && (stb = !stb);
         var layout = this.grid.layout;
         var idx = this.index;
         delete this.source._targetNode;
         delete this.source._beforeTarget;

         
         layout.moveColumn(
          source.viewIndex,
          idx,
          getIdx(nodes[0]),
          getIdx(stn),
          stb);
        },


        renderHeader: function(){
         this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
         if(this.flexCells){
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
        },


        // note: not called in 'view' context
        _getHeaderContent: function(inCell){
         var n = inCell.name || inCell.grid.getCellName(inCell);
         var ret = [ '
      ');
         }else{
          ret = ret.concat([ ' ',
             inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
             '">
      ',
             inCell.grid.sortInfo > 0 ? '▲' : '▼',
             '
      ',
             '
      ']);
         }
         ret = ret.concat([n, '
      ']);
         return ret.join('');
        },


        resize: function(){
         this.adaptHeight();
         this.adaptWidth();
        },


        hasHScrollbar: function(reset){
         var hadScroll = this._hasHScroll||false;
         if(this._hasHScroll == undefined || reset){
          if(this.noscroll){
           this._hasHScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasHScroll = false;
           }else if(style == "scroll"){
            this._hasHScroll = true;
           }else{
            this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
           }
          }
         }
         if(hadScroll !== this._hasHScroll){
          this.grid.update();
         }
         return this._hasHScroll; // Boolean
        },


        hasVScrollbar: function(reset){
         var hadScroll = this._hasVScroll||false;
         if(this._hasVScroll == undefined || reset){
          if(this.noscroll){
           this._hasVScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasVScroll = false;
           }else if(style == "scroll"){
            this._hasVScroll = true;
           }else{
            this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
           }
          }
         }
         if(hadScroll !== this._hasVScroll){
          this.grid.update();
         }
         return this._hasVScroll; // Boolean
        },

        
        convertColPctToFixed: function(){
         // Fix any percentage widths to be pixel values
         var hasPct = false;
         this.grid.initialWidth = "";
         var cellNodes = dojo.query("th", this.headerContentNode);
         var fixedWidths = dojo.map(cellNodes, function(c, vIdx){
          var w = c.style.width;
          dojo.attr(c, "vIdx", vIdx);
          if(w && w.slice(-1) == "%"){
           hasPct = true;
          }else if(w && w.slice(-2) == "px"){
           return window.parseInt(w, 10);
          }
          return dojo.contentBox(c).w;
         });
         if(hasPct){
          dojo.forEach(this.grid.layout.cells, function(cell, idx){
           if(cell.view == this){
            var cellNode = cell.view.getHeaderCellNode(cell.index);
            if(cellNode && dojo.hasAttr(cellNode, "vIdx")){
             var vIdx = window.parseInt(dojo.attr(cellNode, "vIdx"));
             this.setColWidth(idx, fixedWidths[vIdx]);
             dojo.removeAttr(cellNode, "vIdx");
            }
           }
          }, this);
          return true;
         }
         return false;
    • returns
      Integer|String|Boolean
    • summary
  • dojox.grid._View.adaptHeight

    • type
      Function
    • parameters:
      • minusScroll: (typeof )
    • source: [view]
         if(!this.grid._autoHeight){
          var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
          var self = this;
          var checkOtherViewScrollers = function(){
           var v;
           for(var i in self.grid.views.views){
            v = self.grid.views.views[i];
            if(v !== self && v.hasHScrollbar()){
             return true;
            }
           }
           return false;
          };
          if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
           h -= dojox.html.metrics.getScrollbar().h;
          }
          dojox.grid.util.setStyleHeightPx(this.scrollboxNode, h);
         }
         this.hasVScrollbar(true);
    • summary
  • dojox.grid._View.adaptWidth

    • type
      Function
    • source: [view]
         if(this.flexCells){
          // the view content width
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         // FIXME: it should be easier to get w from this.scrollboxNode.clientWidth,
         // but clientWidth seemingly does not include scrollbar width in some cases
         var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
         if(!this._removingColumn){
          w = Math.max(w, this.getColumnsWidth()) + 'px';
         }else{
          w = Math.min(w, this.getColumnsWidth()) + 'px';
          this._removingColumn = false;
         }
         var cn = this.contentNode;
         cn.style.width = w;
         this.hasHScrollbar(true);
    • summary
  • dojox.grid._View.setSize

    • type
      Function
    • parameters:
      • w: (typeof )
      • h: (typeof )
    • source: [view]
         var ds = this.domNode.style;
         var hs = this.headerNode.style;


         if(w){
          ds.width = w;
          hs.width = w;
         }
         ds.height = (h >= 0 ? h + 'px' : '');
    • summary
  • dojox.grid._View.renderRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         var rowNode = this.createRowNode(inRowIndex);
         this.buildRow(inRowIndex, rowNode);
         this.grid.edit.restore(this, inRowIndex);
         return rowNode;
    • summary
  • dojox.grid._View.createRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         var node = document.createElement("div");
         node.className = this.classTag + 'Row';
         if (this instanceof dojox.grid._RowSelector){
          dojo.attr(node,"role","presentation");
         }else{
          dojo.attr(node,"role","row");
          if (this.grid.selectionMode != "none") {
           dojo.attr(node, "aria-selected", "false"); //rows can be selected so add aria-selected prop
          }
         }
         node[dojox.grid.util.gridViewTag] = this.id;
         node[dojox.grid.util.rowIndexTag] = inRowIndex;
         this.rowNodes[inRowIndex] = node;
         return node;
    • summary
  • dojox.grid._View.buildRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         this.buildRowContent(inRowIndex, inRowNode);

          
         this.styleRow(inRowIndex, inRowNode);
    • summary
  • dojox.grid._View.buildRowContent

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex);
         if(this.flexCells && this.contentWidth){
          // FIXME: accessing firstChild here breaks encapsulation
          inRowNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
    • summary
  • dojox.grid._View.rowRemoved

    • summary
  • dojox.grid._View.getRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         return this.rowNodes[inRowIndex];
    • summary
  • dojox.grid._View.getCellNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inCellIndex: (typeof )
    • source: [view]
         var row = this.getRowNode(inRowIndex);
         if(row){
          return this.content.getCellNode(row, inCellIndex);
         }
    • summary
  • dojox.grid._View.getHeaderCellNode

    • type
      Function
    • parameters:
      • inCellIndex: (typeof )
    • source: [view]
         if(this.headerContentNode){
          return this.header.getCellNode(this.headerContentNode, inCellIndex);
         }
    • summary
  • dojox.grid._View.styleRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         inRowNode._style = getStyleText(inRowNode);
         this.styleRowNode(inRowIndex, inRowNode);
    • summary
  • dojox.grid._View.styleRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         if(inRowNode){
          this.doStyleRowNode(inRowIndex, inRowNode);
         }
    • summary
  • dojox.grid._View.doStyleRowNode

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
      • inRowNode: (typeof )
    • source: [view]
         this.grid.styleRowNode(inRowIndex, inRowNode);
    • summary
  • dojox.grid._View.updateRow

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         var rowNode = this.getRowNode(inRowIndex);
         if(rowNode){
          rowNode.style.height = '';
          this.buildRow(inRowIndex, rowNode);
         }
         return rowNode;
    • summary
  • dojox.grid._View.updateRowStyles

    • type
      Function
    • parameters:
      • inRowIndex: (typeof )
    • source: [view]
         this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
    • summary
  • dojox.grid._View.lastTop

    • summary
  • dojox.grid._View.firstScroll

    • summary
  • dojox.grid._View.doscroll

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
        },

        
        onBeforeRow: function(inRowIndex, cells){
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
        },

        
        onAfterRow: function(inRowIndex, cells, inRowNode){
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
        },


        testFlexCells: function(){
         // FIXME: cheater, this function does double duty as initializer and tester
         this.flexCells = false;
         for(var j=0, row; (row=this.structure.cells[j]); j++){
          for(var i=0, cell; (cell=row[i]); i++){
           cell.view = this;
           this.flexCells = this.flexCells || cell.isFlex();
          }
         }
         return this.flexCells;
        },


        updateStructure: function(){
         // header builder needs to update table map
         this.header.update();
         // content builder needs to update markup cache
         this.content.update();
        },


        getScrollbarWidth: function(){
         var hasScrollSpace = this.hasVScrollbar();
         var overflow = dojo.style(this.scrollboxNode, "overflow");
         if(this.noscroll || !overflow || overflow == "hidden"){
          hasScrollSpace = false;
         }else if(overflow == "scroll"){
          hasScrollSpace = true;
         }
         return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
        },


        getColumnsWidth: function(){
         var h = this.headerContentNode;
         return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
        },


        setColumnsWidth: function(width){
         this.headerContentNode.firstChild.style.width = width + 'px';
         if(this.viewWidth){
          this.viewWidth = width + 'px';
         }
        },


        getWidth: function(){
         return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
        },


        getContentWidth: function(){
         return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
        },


        render: function(){
         this.scrollboxNode.style.height = '';
         this.renderHeader();
         if(this._togglingColumn >= 0){
          this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
          this._togglingColumn = -1;
         }
         var cells = this.grid.layout.cells;
         var getSibling = dojo.hitch(this, function(node, before){
          !dojo._isBodyLtr() && (before = !before);
          var inc = before?-1:1;
          var idx = this.header.getCellNodeIndex(node) + inc;
          var cell = cells[idx];
          while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
           idx += inc;
           cell = cells[idx];
          }
          if(cell){
           return cell.getHeaderNode();
          }
          return null;
         });
         if(this.grid.columnReordering && this.simpleStructure){
          if(this.source){
           this.source.destroy();
          }

          
          // Create the top and bottom markers
          var bottomMarkerId = "dojoxGrid_bottomMarker";
          var topMarkerId = "dojoxGrid_topMarker";
          if(this.bottomMarker){
           dojo.destroy(this.bottomMarker);
          }
          this.bottomMarker = dojo.byId(bottomMarkerId);
          if(this.topMarker){
           dojo.destroy(this.topMarker);
          }
          this.topMarker = dojo.byId(topMarkerId);
          if (!this.bottomMarker) {
           this.bottomMarker = dojo.create("div", {
            "id": bottomMarkerId,
            "class": "dojoxGridColPlaceBottom"
           }, dojo.body());
           this._hide(this.bottomMarker);



           
           this.topMarker = dojo.create("div", {
            "id": topMarkerId,
            "class": "dojoxGridColPlaceTop"
           }, dojo.body());
           this._hide(this.topMarker);
          }
          this.arrowDim = dojo.contentBox(this.bottomMarker);


          var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;

          
          this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
           horizontal: true,
           accept: [ "gridColumn_" + this.grid.id ],
           viewIndex: this.index,
           generateText: false,
           onMouseDown: dojo.hitch(this, function(e){
            this.header.decorateEvent(e);
            if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
             this.header.canResize(e) && !this.header.moveable){
             this.header.beginColumnResize(e);
            }else{
             if(this.grid.headerMenu){
              this.grid.headerMenu.onCancel(true);
             }
             // IE reports a left click as 1, where everything else reports 0
             if(e.button === (dojo.isIE ? 1 : 0)){
              dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
             }
            }
           }),
           onMouseOver: dojo.hitch(this, function(e){
            var src = this.source;
            if(src._getChildByEvent(e)){
             dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
            }
           }),
           _markTargetAnchor: dojo.hitch(this, function(before){
            var src = this.source;
            if(src.current == src.targetAnchor && src.before == before){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);

            
            var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
            var endAdd = 0;


            if (!target) {
             target = src.targetAnchor;
             endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
            }


            // NOTE: this is for backwards compatibility with Dojo 1.3
            var pos = (dojo.position||dojo._abs)(target, true);
            var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);


            dojo.style(this.bottomMarker, "visibility", "visible");
            dojo.style(this.topMarker, "visibility", "visible");
            dojo.style(this.bottomMarker, {
             "left": left + "px",
             "top" : (headerHeight + pos.y) + "px"
            });


            dojo.style(this.topMarker, {
             "left": left + "px",
             "top" : (pos.y - this.arrowDim.h) + "px"
            });


            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
           }),
           _unmarkTargetAnchor: dojo.hitch(this, function(){
            var src = this.source;
            if(!src.targetAnchor){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
            dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
           }),
           destroy: dojo.hitch(this, function(){
            dojo.disconnect(this._source_conn);
            dojo.unsubscribe(this._source_sub);
            dojo.dnd.Source.prototype.destroy.call(this.source);
            if(this.bottomMarker){
             dojo.destroy(this.bottomMarker);
             delete this.bottomMarker;
            }
            if(this.topMarker){
             dojo.destroy(this.topMarker);
             delete this.topMarker;
            }
           }),
           onDndCancel: dojo.hitch(this, function(){
            dojo.dnd.Source.prototype.onDndCancel.call(this.source);
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
           })
          });


          this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
          this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
          this.source.startup();
         }
        },

        
        _hide: function(node){
         dojo.style(node, {
          left: "-10000px",
          top: "-10000px",
          "visibility": "hidden"
         });
        },


        _onDndDropBefore: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          return;
         }
         this.source._targetNode = this.source.targetAnchor;
         this.source._beforeTarget = this.source.before;
         var views = this.grid.views.views;
         var srcView = views[source.viewIndex];
         var tgtView = views[this.index];
         if(tgtView != srcView){
          srcView.convertColPctToFixed();
          tgtView.convertColPctToFixed();
         }
        },


        _onDndDrop: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          if(dojo.dnd.manager().source === this.source){
           this._removingColumn = true;
          }
          return;
         }
         this._hide(this.bottomMarker);
         this._hide(this.topMarker);


         var getIdx = function(n){
          return n ? dojo.attr(n, "idx") : null;
         };
         var w = dojo.marginBox(nodes[0]).w;
         if(source.viewIndex !== this.index){
          var views = this.grid.views.views;
          var srcView = views[source.viewIndex];
          var tgtView = views[this.index];
          if(srcView.viewWidth && srcView.viewWidth != "auto"){
           srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
          }
          if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
           tgtView.setColumnsWidth(tgtView.getColumnsWidth());
          }
         }
         var stn = this.source._targetNode;
         var stb = this.source._beforeTarget;
         !dojo._isBodyLtr() && (stb = !stb);
         var layout = this.grid.layout;
         var idx = this.index;
         delete this.source._targetNode;
         delete this.source._beforeTarget;

         
         layout.moveColumn(
          source.viewIndex,
          idx,
          getIdx(nodes[0]),
          getIdx(stn),
          stb);
        },


        renderHeader: function(){
         this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
         if(this.flexCells){
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
        },


        // note: not called in 'view' context
        _getHeaderContent: function(inCell){
         var n = inCell.name || inCell.grid.getCellName(inCell);
         var ret = [ '
      ');
         }else{
          ret = ret.concat([ ' ',
             inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
             '">
      ',
             inCell.grid.sortInfo > 0 ? '▲' : '▼',
             '
      ',
             '
      ']);
         }
         ret = ret.concat([n, '
      ']);
         return ret.join('');
        },


        resize: function(){
         this.adaptHeight();
         this.adaptWidth();
        },


        hasHScrollbar: function(reset){
         var hadScroll = this._hasHScroll||false;
         if(this._hasHScroll == undefined || reset){
          if(this.noscroll){
           this._hasHScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasHScroll = false;
           }else if(style == "scroll"){
            this._hasHScroll = true;
           }else{
            this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
           }
          }
         }
         if(hadScroll !== this._hasHScroll){
          this.grid.update();
         }
         return this._hasHScroll; // Boolean
        },


        hasVScrollbar: function(reset){
         var hadScroll = this._hasVScroll||false;
         if(this._hasVScroll == undefined || reset){
          if(this.noscroll){
           this._hasVScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasVScroll = false;
           }else if(style == "scroll"){
            this._hasVScroll = true;
           }else{
            this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
           }
          }
         }
         if(hadScroll !== this._hasVScroll){
          this.grid.update();
         }
         return this._hasVScroll; // Boolean
        },

        
        convertColPctToFixed: function(){
         // Fix any percentage widths to be pixel values
         var hasPct = false;
         this.grid.initialWidth = "";
         var cellNodes = dojo.query("th", this.headerContentNode);
         var fixedWidths = dojo.map(cellNodes, function(c, vIdx){
          var w = c.style.width;
          dojo.attr(c, "vIdx", vIdx);
          if(w && w.slice(-1) == "%"){
           hasPct = true;
          }else if(w && w.slice(-2) == "px"){
           return window.parseInt(w, 10);
          }
          return dojo.contentBox(c).w;
         });
         if(hasPct){
          dojo.forEach(this.grid.layout.cells, function(cell, idx){
           if(cell.view == this){
            var cellNode = cell.view.getHeaderCellNode(cell.index);
            if(cellNode && dojo.hasAttr(cellNode, "vIdx")){
             var vIdx = window.parseInt(dojo.attr(cellNode, "vIdx"));
             this.setColWidth(idx, fixedWidths[vIdx]);
             dojo.removeAttr(cellNode, "vIdx");
            }
           }
          }, this);
          return true;
         }
         return false;
        },


        adaptHeight: function(minusScroll){
         if(!this.grid._autoHeight){
          var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
          var self = this;
          var checkOtherViewScrollers = function(){
           var v;
           for(var i in self.grid.views.views){
            v = self.grid.views.views[i];
            if(v !== self && v.hasHScrollbar()){
             return true;
            }
           }
           return false;
          };
          if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
           h -= dojox.html.metrics.getScrollbar().h;
          }
          dojox.grid.util.setStyleHeightPx(this.scrollboxNode, h);
         }
         this.hasVScrollbar(true);
        },


        adaptWidth: function(){
         if(this.flexCells){
          // the view content width
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         // FIXME: it should be easier to get w from this.scrollboxNode.clientWidth,
         // but clientWidth seemingly does not include scrollbar width in some cases
         var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
         if(!this._removingColumn){
          w = Math.max(w, this.getColumnsWidth()) + 'px';
         }else{
          w = Math.min(w, this.getColumnsWidth()) + 'px';
          this._removingColumn = false;
         }
         var cn = this.contentNode;
         cn.style.width = w;
         this.hasHScrollbar(true);
        },


        setSize: function(w, h){
         var ds = this.domNode.style;
         var hs = this.headerNode.style;


         if(w){
          ds.width = w;
          hs.width = w;
         }
         ds.height = (h >= 0 ? h + 'px' : '');
        },


        renderRow: function(inRowIndex){
         var rowNode = this.createRowNode(inRowIndex);
         this.buildRow(inRowIndex, rowNode);
         this.grid.edit.restore(this, inRowIndex);
         return rowNode;
        },


        createRowNode: function(inRowIndex){
         var node = document.createElement("div");
         node.className = this.classTag + 'Row';
         if (this instanceof dojox.grid._RowSelector){
          dojo.attr(node,"role","presentation");
         }else{
          dojo.attr(node,"role","row");
          if (this.grid.selectionMode != "none") {
           dojo.attr(node, "aria-selected", "false"); //rows can be selected so add aria-selected prop
          }
         }
         node[dojox.grid.util.gridViewTag] = this.id;
         node[dojox.grid.util.rowIndexTag] = inRowIndex;
         this.rowNodes[inRowIndex] = node;
         return node;
        },


        buildRow: function(inRowIndex, inRowNode){

         
         this.buildRowContent(inRowIndex, inRowNode);

          
         this.styleRow(inRowIndex, inRowNode);

        

        
        },


        buildRowContent: function(inRowIndex, inRowNode){
         inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex);
         if(this.flexCells && this.contentWidth){
          // FIXME: accessing firstChild here breaks encapsulation
          inRowNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
        },


        rowRemoved:function(inRowIndex){
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
         this.grid.edit.save(this, inRowIndex);
         delete this.rowNodes[inRowIndex];
        },


        getRowNode: function(inRowIndex){
         return this.rowNodes[inRowIndex];
        },


        getCellNode: function(inRowIndex, inCellIndex){
         var row = this.getRowNode(inRowIndex);
         if(row){
          return this.content.getCellNode(row, inCellIndex);
         }
        },


        getHeaderCellNode: function(inCellIndex){
         if(this.headerContentNode){
          return this.header.getCellNode(this.headerContentNode, inCellIndex);
         }
        },


        // styling
        styleRow: function(inRowIndex, inRowNode){
         inRowNode._style = getStyleText(inRowNode);
         this.styleRowNode(inRowIndex, inRowNode);
        },


        styleRowNode: function(inRowIndex, inRowNode){
         if(inRowNode){
          this.doStyleRowNode(inRowIndex, inRowNode);
         }
        },


        doStyleRowNode: function(inRowIndex, inRowNode){
         this.grid.styleRowNode(inRowIndex, inRowNode);
        },


        // updating
        updateRow: function(inRowIndex){
         var rowNode = this.getRowNode(inRowIndex);
         if(rowNode){
          rowNode.style.height = '';
          this.buildRow(inRowIndex, rowNode);
         }
         return rowNode;
        },


        updateRowStyles: function(inRowIndex){
         this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
        },


        // scrolling
        lastTop: 0,
        firstScroll:0,


        doscroll: function(inEvent){
         //var s = dojo.marginBox(this.headerContentNode.firstChild);
         var isLtr = dojo._isBodyLtr();
         if(this.firstScroll < 2){
          if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
           var s = dojo.marginBox(this.headerNodeContainer);
           if(dojo.isIE){
            this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
           }else if(dojo.isMoz){
            //TODO currently only for FF, not sure for safari and opera
            this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
            //this.headerNodeContainer.style.width = s.w + 'px';
            //set scroll to right in FF
            this.scrollboxNode.scrollLeft = isLtr ?
             this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth :
             this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
           }
          }
          this.firstScroll++;
         }
         this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
         // 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
         var top = this.scrollboxNode.scrollTop;
         if(top !== this.lastTop){
          this.grid.scrollTo(top);
         }
    • returns
      Integer|String|Boolean
    • summary
  • dojox.grid._View.setScrollTop

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


      dojo.require("dijit._Widget");
      dojo.require("dijit._Templated");
      dojo.require("dojox.grid._Builder");
      dojo.require("dojox.html.metrics");
      dojo.require("dojox.grid.util");


      dojo.require("dojo.dnd.Source");
      dojo.require("dojo.dnd.Manager");


      (function(){
       // a private function
       var getStyleText = function(inNode, inStyleText){
        return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
       };


       // some public functions
       dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
        // summary:
        //  A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
        //  Grid creates views automatically based on grid's layout structure.
        //  Users should typically not need to access individual views directly.
        //
        // defaultWidth: String
        //  Default width of the view
        defaultWidth: "18em",


        // viewWidth: String
        //   Width for the view, in valid css unit
        viewWidth: "",


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

        
        themeable: false,
        classTag: 'dojoxGrid',
        marginBottom: 0,
        rowPad: 2,


        // _togglingColumn: int
        //  Width of the column being toggled (-1 for none)
        _togglingColumn: -1,

        
        // _headerBuilderClass: Object
        //  The class to use for our header builder
        _headerBuilderClass: dojox.grid._HeaderBuilder,

        
        // _contentBuilderClass: Object
        //  The class to use for our content builder
        _contentBuilderClass: dojox.grid._ContentBuilder,

        
        postMixInProperties: function(){
         this.rowNodes = {};
        },


        postCreate: function(){
         this.connect(this.scrollboxNode,"onscroll","doscroll");
         dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
         dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
         this.content = new this._contentBuilderClass(this);
         this.header = new this._headerBuilderClass(this);
         //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
         if(!dojo._isBodyLtr()){
          this.headerNodeContainer.style.width = "";
         }
        },


        destroy: function(){
         dojo.destroy(this.headerNode);
         delete this.headerNode;
         for(var i in this.rowNodes){
          dojo.destroy(this.rowNodes[i]);
         }
         this.rowNodes = {};
         if(this.source){
          this.source.destroy();
         }
         this.inherited(arguments);
        },


        // focus
        focus: function(){
         if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
          this.hiddenFocusNode.focus();
         }else{
          this.scrollboxNode.focus();
         }
        },


        setStructure: function(inStructure){
         var vs = (this.structure = inStructure);
         // FIXME: similar logic is duplicated in layout
         if(vs.width && !isNaN(vs.width)){
          this.viewWidth = vs.width + 'em';
         }else{
          this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
         }
         this._onBeforeRow = vs.onBeforeRow||function(){};
         this._onAfterRow = vs.onAfterRow||function(){};
         this.noscroll = vs.noscroll;
         if(this.noscroll){
          this.scrollboxNode.style.overflow = "hidden";
         }
         this.simpleStructure = Boolean(vs.cells.length == 1);
         // bookkeeping
         this.testFlexCells();
         // accomodate new structure
         this.updateStructure();
        },

        
        _cleanupRowWidgets: function(inRowNode){
         // Summary:
         //  Cleans up the widgets for the given row node so that
         //  we can reattach them if needed
         if(inRowNode){
          dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
           if(w._destroyOnRemove){
            w.destroy();
            delete w;
           }else if(w.domNode && w.domNode.parentNode){
            w.domNode.parentNode.removeChild(w.domNode);
           }
          });
         }
        },

        
        onBeforeRow: function(inRowIndex, cells){
         this._onBeforeRow(inRowIndex, cells);
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
        },

        
        onAfterRow: function(inRowIndex, cells, inRowNode){
         this._onAfterRow(inRowIndex, cells, inRowNode);
         var g = this.grid;
         dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
          if(n && n.parentNode){
           var lw = n.getAttribute("linkWidget");
           var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
           var cellDef = g.getCell(cellIdx);
           var w = dijit.byId(lw);
           if(w){
            n.parentNode.replaceChild(w.domNode, n);
            if(!w._started){
             w.startup();
            }
           }else{
            n.innerHTML = "";
           }
          }
         }, this);
        },


        testFlexCells: function(){
         // FIXME: cheater, this function does double duty as initializer and tester
         this.flexCells = false;
         for(var j=0, row; (row=this.structure.cells[j]); j++){
          for(var i=0, cell; (cell=row[i]); i++){
           cell.view = this;
           this.flexCells = this.flexCells || cell.isFlex();
          }
         }
         return this.flexCells;
        },


        updateStructure: function(){
         // header builder needs to update table map
         this.header.update();
         // content builder needs to update markup cache
         this.content.update();
        },


        getScrollbarWidth: function(){
         var hasScrollSpace = this.hasVScrollbar();
         var overflow = dojo.style(this.scrollboxNode, "overflow");
         if(this.noscroll || !overflow || overflow == "hidden"){
          hasScrollSpace = false;
         }else if(overflow == "scroll"){
          hasScrollSpace = true;
         }
         return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
        },


        getColumnsWidth: function(){
         var h = this.headerContentNode;
         return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
        },


        setColumnsWidth: function(width){
         this.headerContentNode.firstChild.style.width = width + 'px';
         if(this.viewWidth){
          this.viewWidth = width + 'px';
         }
        },


        getWidth: function(){
         return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
        },


        getContentWidth: function(){
         return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
        },


        render: function(){
         this.scrollboxNode.style.height = '';
         this.renderHeader();
         if(this._togglingColumn >= 0){
          this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
          this._togglingColumn = -1;
         }
         var cells = this.grid.layout.cells;
         var getSibling = dojo.hitch(this, function(node, before){
          !dojo._isBodyLtr() && (before = !before);
          var inc = before?-1:1;
          var idx = this.header.getCellNodeIndex(node) + inc;
          var cell = cells[idx];
          while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
           idx += inc;
           cell = cells[idx];
          }
          if(cell){
           return cell.getHeaderNode();
          }
          return null;
         });
         if(this.grid.columnReordering && this.simpleStructure){
          if(this.source){
           this.source.destroy();
          }

          
          // Create the top and bottom markers
          var bottomMarkerId = "dojoxGrid_bottomMarker";
          var topMarkerId = "dojoxGrid_topMarker";
          if(this.bottomMarker){
           dojo.destroy(this.bottomMarker);
          }
          this.bottomMarker = dojo.byId(bottomMarkerId);
          if(this.topMarker){
           dojo.destroy(this.topMarker);
          }
          this.topMarker = dojo.byId(topMarkerId);
          if (!this.bottomMarker) {
           this.bottomMarker = dojo.create("div", {
            "id": bottomMarkerId,
            "class": "dojoxGridColPlaceBottom"
           }, dojo.body());
           this._hide(this.bottomMarker);



           
           this.topMarker = dojo.create("div", {
            "id": topMarkerId,
            "class": "dojoxGridColPlaceTop"
           }, dojo.body());
           this._hide(this.topMarker);
          }
          this.arrowDim = dojo.contentBox(this.bottomMarker);


          var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;

          
          this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
           horizontal: true,
           accept: [ "gridColumn_" + this.grid.id ],
           viewIndex: this.index,
           generateText: false,
           onMouseDown: dojo.hitch(this, function(e){
            this.header.decorateEvent(e);
            if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
             this.header.canResize(e) && !this.header.moveable){
             this.header.beginColumnResize(e);
            }else{
             if(this.grid.headerMenu){
              this.grid.headerMenu.onCancel(true);
             }
             // IE reports a left click as 1, where everything else reports 0
             if(e.button === (dojo.isIE ? 1 : 0)){
              dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
             }
            }
           }),
           onMouseOver: dojo.hitch(this, function(e){
            var src = this.source;
            if(src._getChildByEvent(e)){
             dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
            }
           }),
           _markTargetAnchor: dojo.hitch(this, function(before){
            var src = this.source;
            if(src.current == src.targetAnchor && src.before == before){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);

            
            var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
            var endAdd = 0;


            if (!target) {
             target = src.targetAnchor;
             endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
            }


            // NOTE: this is for backwards compatibility with Dojo 1.3
            var pos = (dojo.position||dojo._abs)(target, true);
            var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);


            dojo.style(this.bottomMarker, "visibility", "visible");
            dojo.style(this.topMarker, "visibility", "visible");
            dojo.style(this.bottomMarker, {
             "left": left + "px",
             "top" : (headerHeight + pos.y) + "px"
            });


            dojo.style(this.topMarker, {
             "left": left + "px",
             "top" : (pos.y - this.arrowDim.h) + "px"
            });


            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
           }),
           _unmarkTargetAnchor: dojo.hitch(this, function(){
            var src = this.source;
            if(!src.targetAnchor){ return; }
            if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
             src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
            }
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
            dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
           }),
           destroy: dojo.hitch(this, function(){
            dojo.disconnect(this._source_conn);
            dojo.unsubscribe(this._source_sub);
            dojo.dnd.Source.prototype.destroy.call(this.source);
            if(this.bottomMarker){
             dojo.destroy(this.bottomMarker);
             delete this.bottomMarker;
            }
            if(this.topMarker){
             dojo.destroy(this.topMarker);
             delete this.topMarker;
            }
           }),
           onDndCancel: dojo.hitch(this, function(){
            dojo.dnd.Source.prototype.onDndCancel.call(this.source);
            this._hide(this.bottomMarker);
            this._hide(this.topMarker);
           })
          });


          this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
          this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
          this.source.startup();
         }
        },

        
        _hide: function(node){
         dojo.style(node, {
          left: "-10000px",
          top: "-10000px",
          "visibility": "hidden"
         });
        },


        _onDndDropBefore: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          return;
         }
         this.source._targetNode = this.source.targetAnchor;
         this.source._beforeTarget = this.source.before;
         var views = this.grid.views.views;
         var srcView = views[source.viewIndex];
         var tgtView = views[this.index];
         if(tgtView != srcView){
          srcView.convertColPctToFixed();
          tgtView.convertColPctToFixed();
         }
        },


        _onDndDrop: function(source, nodes, copy){
         if(dojo.dnd.manager().target !== this.source){
          if(dojo.dnd.manager().source === this.source){
           this._removingColumn = true;
          }
          return;
         }
         this._hide(this.bottomMarker);
         this._hide(this.topMarker);


         var getIdx = function(n){
          return n ? dojo.attr(n, "idx") : null;
         };
         var w = dojo.marginBox(nodes[0]).w;
         if(source.viewIndex !== this.index){
          var views = this.grid.views.views;
          var srcView = views[source.viewIndex];
          var tgtView = views[this.index];
          if(srcView.viewWidth && srcView.viewWidth != "auto"){
           srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
          }
          if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
           tgtView.setColumnsWidth(tgtView.getColumnsWidth());
          }
         }
         var stn = this.source._targetNode;
         var stb = this.source._beforeTarget;
         !dojo._isBodyLtr() && (stb = !stb);
         var layout = this.grid.layout;
         var idx = this.index;
         delete this.source._targetNode;
         delete this.source._beforeTarget;

         
         layout.moveColumn(
          source.viewIndex,
          idx,
          getIdx(nodes[0]),
          getIdx(stn),
          stb);
        },


        renderHeader: function(){
         this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
         if(this.flexCells){
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
        },


        // note: not called in 'view' context
        _getHeaderContent: function(inCell){
         var n = inCell.name || inCell.grid.getCellName(inCell);
         var ret = [ '
      ');
         }else{
          ret = ret.concat([ ' ',
             inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
             '">
      ',
             inCell.grid.sortInfo > 0 ? '▲' : '▼',
             '
      ',
             '
      ']);
         }
         ret = ret.concat([n, '
      ']);
         return ret.join('');
        },


        resize: function(){
         this.adaptHeight();
         this.adaptWidth();
        },


        hasHScrollbar: function(reset){
         var hadScroll = this._hasHScroll||false;
         if(this._hasHScroll == undefined || reset){
          if(this.noscroll){
           this._hasHScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasHScroll = false;
           }else if(style == "scroll"){
            this._hasHScroll = true;
           }else{
            this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
           }
          }
         }
         if(hadScroll !== this._hasHScroll){
          this.grid.update();
         }
         return this._hasHScroll; // Boolean
        },


        hasVScrollbar: function(reset){
         var hadScroll = this._hasVScroll||false;
         if(this._hasVScroll == undefined || reset){
          if(this.noscroll){
           this._hasVScroll = false;
          }else{
           var style = dojo.style(this.scrollboxNode, "overflow");
           if(style == "hidden"){
            this._hasVScroll = false;
           }else if(style == "scroll"){
            this._hasVScroll = true;
           }else{
            this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
           }
          }
         }
         if(hadScroll !== this._hasVScroll){
          this.grid.update();
         }
         return this._hasVScroll; // Boolean
        },

        
        convertColPctToFixed: function(){
         // Fix any percentage widths to be pixel values
         var hasPct = false;
         this.grid.initialWidth = "";
         var cellNodes = dojo.query("th", this.headerContentNode);
         var fixedWidths = dojo.map(cellNodes, function(c, vIdx){
          var w = c.style.width;
          dojo.attr(c, "vIdx", vIdx);
          if(w && w.slice(-1) == "%"){
           hasPct = true;
          }else if(w && w.slice(-2) == "px"){
           return window.parseInt(w, 10);
          }
          return dojo.contentBox(c).w;
         });
         if(hasPct){
          dojo.forEach(this.grid.layout.cells, function(cell, idx){
           if(cell.view == this){
            var cellNode = cell.view.getHeaderCellNode(cell.index);
            if(cellNode && dojo.hasAttr(cellNode, "vIdx")){
             var vIdx = window.parseInt(dojo.attr(cellNode, "vIdx"));
             this.setColWidth(idx, fixedWidths[vIdx]);
             dojo.removeAttr(cellNode, "vIdx");
            }
           }
          }, this);
          return true;
         }
         return false;
        },


        adaptHeight: function(minusScroll){
         if(!this.grid._autoHeight){
          var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
          var self = this;
          var checkOtherViewScrollers = function(){
           var v;
           for(var i in self.grid.views.views){
            v = self.grid.views.views[i];
            if(v !== self && v.hasHScrollbar()){
             return true;
            }
           }
           return false;
          };
          if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
           h -= dojox.html.metrics.getScrollbar().h;
          }
          dojox.grid.util.setStyleHeightPx(this.scrollboxNode, h);
         }
         this.hasVScrollbar(true);
        },


        adaptWidth: function(){
         if(this.flexCells){
          // the view content width
          this.contentWidth = this.getContentWidth();
          this.headerContentNode.firstChild.style.width = this.contentWidth;
         }
         // FIXME: it should be easier to get w from this.scrollboxNode.clientWidth,
         // but clientWidth seemingly does not include scrollbar width in some cases
         var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
         if(!this._removingColumn){
          w = Math.max(w, this.getColumnsWidth()) + 'px';
         }else{
          w = Math.min(w, this.getColumnsWidth()) + 'px';
          this._removingColumn = false;
         }
         var cn = this.contentNode;
         cn.style.width = w;
         this.hasHScrollbar(true);
        },


        setSize: function(w, h){
         var ds = this.domNode.style;
         var hs = this.headerNode.style;


         if(w){
          ds.width = w;
          hs.width = w;
         }
         ds.height = (h >= 0 ? h + 'px' : '');
        },


        renderRow: function(inRowIndex){
         var rowNode = this.createRowNode(inRowIndex);
         this.buildRow(inRowIndex, rowNode);
         this.grid.edit.restore(this, inRowIndex);
         return rowNode;
        },


        createRowNode: function(inRowIndex){
         var node = document.createElement("div");
         node.className = this.classTag + 'Row';
         if (this instanceof dojox.grid._RowSelector){
          dojo.attr(node,"role","presentation");
         }else{
          dojo.attr(node,"role","row");
          if (this.grid.selectionMode != "none") {
           dojo.attr(node, "aria-selected", "false"); //rows can be selected so add aria-selected prop
          }
         }
         node[dojox.grid.util.gridViewTag] = this.id;
         node[dojox.grid.util.rowIndexTag] = inRowIndex;
         this.rowNodes[inRowIndex] = node;
         return node;
        },


        buildRow: function(inRowIndex, inRowNode){

         
         this.buildRowContent(inRowIndex, inRowNode);

          
         this.styleRow(inRowIndex, inRowNode);

        

        
        },


        buildRowContent: function(inRowIndex, inRowNode){
         inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex);
         if(this.flexCells && this.contentWidth){
          // FIXME: accessing firstChild here breaks encapsulation
          inRowNode.firstChild.style.width = this.contentWidth;
         }
         dojox.grid.util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
        },


        rowRemoved:function(inRowIndex){
         if(inRowIndex >= 0){
          this._cleanupRowWidgets(this.getRowNode(inRowIndex));
         }
         this.grid.edit.save(this, inRowIndex);
         delete this.rowNodes[inRowIndex];
        },


        getRowNode: function(inRowIndex){
         return this.rowNodes[inRowIndex];
        },


        getCellNode: function(inRowIndex, inCellIndex){
         var row = this.getRowNode(inRowIndex);
         if(row){
          return this.content.getCellNode(row, inCellIndex);
         }
        },


        getHeaderCellNode: function(inCellIndex){
         if(this.headerContentNode){
          return this.header.getCellNode(this.headerContentNode, inCellIndex);
         }
        },


        // styling
        styleRow: function(inRowIndex, inRowNode){
         inRowNode._style = getStyleText(inRowNode);
         this.styleRowNode(inRowIndex, inRowNode);
        },


        styleRowNode: function(inRowIndex, inRowNode){
         if(inRowNode){
          this.doStyleRowNode(inRowIndex, inRowNode);
         }
        },


        doStyleRowNode: function(inRowIndex, inRowNode){
         this.grid.styleRowNode(inRowIndex, inRowNode);
        },


        // updating
        updateRow: function(inRowIndex){
         var rowNode = this.getRowNode(inRowIndex);
         if(rowNode){
          rowNode.style.height = '';
          this.buildRow(inRowIndex, rowNode);
         }
         return rowNode;
        },


        updateRowStyles: function(inRowIndex){
         this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
        },


        // scrolling
        lastTop: 0,
        firstScroll:0,


        doscroll: function(inEvent){
         //var s = dojo.marginBox(this.headerContentNode.firstChild);
         var isLtr = dojo._isBodyLtr();
         if(this.firstScroll < 2){
          if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
           var s = dojo.marginBox(this.headerNodeContainer);
           if(dojo.isIE){
            this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
           }else if(dojo.isMoz){
            //TODO currently only for FF, not sure for safari and opera
            this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
            //this.headerNodeContainer.style.width = s.w + 'px';
            //set scroll to right in FF
            this.scrollboxNode.scrollLeft = isLtr ?
             this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth :
             this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
           }
          }
          this.firstScroll++;
         }
         this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
         // 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
         var top = this.scrollboxNode.scrollTop;
         if(top !== this.lastTop){
          this.grid.scrollTo(top);
         }
        },


        setScrollTop: function(inTop){
         // 'lastTop' is a semaphore to prevent feedback-loop with doScroll above
         this.lastTop = inTop;
         this.scrollboxNode.scrollTop = inTop;
         return this.scrollboxNode.scrollTop;
    • returns
      Integer|String|Boolean
    • summary
  • dojox.grid._View.doContentEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(this.content.decorateEvent(e)){
          this.grid.onContentEvent(e);
         }
    • summary
  • dojox.grid._View.doHeaderEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         if(this.header.decorateEvent(e)){
          this.grid.onHeaderEvent(e);
         }
    • summary
  • dojox.grid._View.dispatchContentEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         return this.content.dispatchEvent(e);
    • summary
  • dojox.grid._View.dispatchHeaderEvent

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
         return this.header.dispatchEvent(e);
    • summary
  • dojox.grid._View.setColWidth

    • type
      Function
    • parameters:
      • inIndex: (typeof )
      • inWidth: (typeof )
    • source: [view]
         this.grid.setCellWidth(inIndex, inWidth + 'px');
    • summary
  • dojox.grid._View.update

    • type
      Function
    • source: [view]
         if(!this.domNode){
          return;
         }
         this.content.update();
         this.grid.update();
         //get scroll after update or scroll left setting goes wrong on IE.
         //See trac: #8040
         var left = this.scrollboxNode.scrollLeft;
         this.scrollboxNode.scrollLeft = left;
         this.headerNode.scrollLeft = left;
    • summary
  • dojox.grid._View.rowNodes

    • summary
  • dojox.grid._View.content

    • summary
  • dojox.grid._View.header

    • summary
  • dojox.grid._View.headerNodeContainer.style.width

    • summary
  • dojox.grid._View.structure

    • summary
  • dojox.grid._View._onBeforeRow

    • summary
  • dojox.grid._View._onAfterRow

    • summary
  • dojox.grid._View.noscroll

    • summary
  • dojox.grid._View.scrollboxNode.style.overflow

    • summary
  • dojox.grid._View.simpleStructure

    • summary
  • dojox.grid._View.flexCells

    • summary
  • dojox.grid._View.headerContentNode.firstChild.style.width

    • summary
  • dojox.grid._View.scrollboxNode.style.height

    • summary
  • dojox.grid._View.bottomMarker

    • summary
  • dojox.grid._View.topMarker

    • summary
  • dojox.grid._View.arrowDim

    • summary
  • dojox.grid._View.source

    • summary
  • dojox.grid._View._source_conn

    • summary
  • dojox.grid._View._source_sub

    • summary
  • dojox.grid._View.source._targetNode

    • summary
  • dojox.grid._View.source._beforeTarget

    • summary
  • dojox.grid._View._removingColumn

    • summary
  • dojox.grid._View.headerContentNode.innerHTML

    • summary
  • dojox.grid._View.contentWidth

    • summary
  • dojox.grid._View._hasHScroll

    • summary
  • dojox.grid._View._hasVScroll

    • summary
  • dojox.grid._View.grid.initialWidth

    • summary
  • dojox.grid._View.scrollboxNode.scrollLeft

    • summary
  • dojox.grid._View.headerNode.scrollLeft

    • summary
  • dojox.grid._View.scrollboxNode.scrollTop

    • summary
  • dojox.grid._GridAvatar

    • type
      Function
    • chains:
      • dojo.dnd.Avatar: (prototype)
      • dojo.dnd.Avatar: (call)
    • summary
  • dojox.grid._GridAvatar.construct

    • type
      Function
    • source: [view]
         var dd = dojo.doc;


         var a = dd.createElement("table");
         a.cellPadding = a.cellSpacing = "0";
         a.className = "dojoxGridDndAvatar";
         a.style.position = "absolute";
         a.style.zIndex = 1999;
         a.style.margin = "0px"; // to avoid dojo.marginBox() problems with table's margins
         var b = dd.createElement("tbody");
         var tr = dd.createElement("tr");
         var td = dd.createElement("td");
         var img = dd.createElement("td");
         tr.className = "dojoxGridDndAvatarItem";
         img.className = "dojoxGridDndAvatarItemImage";
         img.style.width = "16px";
         var source = this.manager.source, node;
         if(source.creator){
          // create an avatar representation of the node
          node = source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node;
         }else{
          // or just clone the node and hope it works
          node = this.manager.nodes[0].cloneNode(true);
          var table, tbody;
          if(node.tagName.toLowerCase() == "tr"){
           // insert extra table nodes
           table = dd.createElement("table");
           tbody = dd.createElement("tbody");
           tbody.appendChild(node);
           table.appendChild(tbody);
           node = table;
          }else if(node.tagName.toLowerCase() == "th"){
           // insert extra table nodes
           table = dd.createElement("table");
           tbody = dd.createElement("tbody");
           var r = dd.createElement("tr");
           table.cellPadding = table.cellSpacing = "0";
           r.appendChild(node);
           tbody.appendChild(r);
           table.appendChild(tbody);
           node = table;
          }
         }
         node.id = "";
         td.appendChild(node);
         tr.appendChild(img);
         tr.appendChild(td);
         dojo.style(tr, "opacity", 0.9);
         b.appendChild(tr);


         a.appendChild(b);
         this.node = a;


         var m = dojo.dnd.manager();
         this.oldOffsetY = m.OFFSET_Y;
         m.OFFSET_Y = 1;
    • summary
  • dojox.grid._GridAvatar.destroy

    • type
      Function
    • source: [view]
         dojo.dnd.manager().OFFSET_Y = this.oldOffsetY;
         this.inherited(arguments);
    • summary
  • dojox.grid._GridAvatar.node

    • summary
  • dojox.grid._GridAvatar.oldOffsetY

    • summary
  • makeAvatar

    • type
      Function
    • source: [view]
        var src = this.source;
        if(src.viewIndex !== undefined && !dojo.hasClass(dojo.body(),"dijit_a11y")){
         return new dojox.grid._GridAvatar(this);
        }
        return oldMakeAvatar.call(dojo.dnd.manager());
    • chains:
      • oldMakeAvatar: (call)
    • summary
  • dojox.grid

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary