text: //>>built
  require({cache:{
  'url:dojox/grid/resources/View.html':"<div class=\"dojoxGridView\" role=\"presentation\">\n\t<div class=\"dojoxGridHeader\" dojoAttachPoint=\"headerNode\" role=\"presentation\">\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\" role=\"presentation\">\n\t\t\t<div dojoAttachPoint=\"headerContentNode\" role=\"row\"></div>\n\t\t</div>\n\t</div>\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" dojoAttachPoint=\"hiddenFocusNode\" role=\"presentation\" />\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" role=\"presentation\" />\n\t<div class=\"dojoxGridScrollbox\" dojoAttachPoint=\"scrollboxNode\" role=\"presentation\">\n\t\t<div class=\"dojoxGridContent\" dojoAttachPoint=\"contentNode\" hidefocus=\"hidefocus\" role=\"presentation\"></div>\n\t</div>\n</div>\n"}});
  define("dojox/grid/_View", [
  	"dojo",
  	"dijit/registry",
  	"../main",
  	"dojo/_base/declare",
  	"dojo/_base/array",
  	"dojo/_base/lang",
  	"dojo/_base/connect",
  	"dojo/_base/sniff",
  	"dojo/query",
  	"dojo/_base/window",
  	"dojo/text!./resources/View.html",
  	"dojo/dnd/Source",
  	"dijit/_Widget",
  	"dijit/_TemplatedMixin",
  	"dojox/html/metrics",
  	"./util",
  	"dojo/_base/html",
  	"./_Builder",
  	"dojo/dnd/Avatar",
  	"dojo/dnd/Manager"
  ], function(dojo, dijit, dojox, declare, array, lang, connect, has, query,
  	win, template, Source, _Widget, _TemplatedMixin, metrics, util, html, _Builder, Avatar){
  
  	// a private function
  	var getStyleText = function(inNode, inStyleText){
  		return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
  	};
  
  	// some public functions
  	var _View = declare('dojox.grid._View', [_Widget, _TemplatedMixin], {
  		// 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: "",
  
  		templateString: template,
  		
  		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: _Builder._HeaderBuilder,
  		
  		// _contentBuilderClass: Object
  		//		The class to use for our content builder
  		_contentBuilderClass: _Builder._ContentBuilder,
  		
  		postMixInProperties: function(){
  			this.rowNodes = {};
  		},
  
  		postCreate: function(){
  			this.connect(this.scrollboxNode,"onscroll","doscroll");
  			util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
  			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(!this.grid.isLeftToRight()){
  				this.headerNodeContainer.style.width = "";
  			}
  		},
  
  		destroy: function(){
  			html.destroy(this.headerNode);
  			delete this.headerNode;
  			for(var i in this.rowNodes){
  				this._cleanupRowWidgets(this.rowNodes[i]);
  				html.destroy(this.rowNodes[i]);
  			}
  			this.rowNodes = {};
  			if(this.source){
  				this.source.destroy();
  			}
  			this.inherited(arguments);
  		},
  
  		// focus
  		focus: function(){
  			if(has("ie") || has("webkit") || has("opera")){
  				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){
  				array.forEach(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;
  			array.forEach(query(".dojoxGridStubNode", inRowNode), function(n){
  				if(n && n.parentNode){
  					var lw = n.getAttribute("linkWidget");
  					var cellIdx = window.parseInt(html.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();
  						}
  						dojo.destroy(n);
  					}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 = html.style(this.scrollboxNode, "overflow");
  			if(this.noscroll || !overflow || overflow == "hidden"){
  				hasScrollSpace = false;
  			}else if(overflow == "scroll"){
  				hasScrollSpace = true;
  			}
  			return (hasScrollSpace ? 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, html._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 = lang.hitch(this, function(node, before){
  				!this.grid.isLeftToRight() && (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){
  					html.destroy(this.bottomMarker);
  				}
  				this.bottomMarker = html.byId(bottomMarkerId);
  				if(this.topMarker){
  					html.destroy(this.topMarker);
  				}
  				this.topMarker = html.byId(topMarkerId);
  				if (!this.bottomMarker) {
  					this.bottomMarker = html.create("div", {
  						"id": bottomMarkerId,
  						"class": "dojoxGridColPlaceBottom"
  					}, win.body());
  					this._hide(this.bottomMarker);
  
  					
  					this.topMarker = html.create("div", {
  						"id": topMarkerId,
  						"class": "dojoxGridColPlaceTop"
  					}, win.body());
  					this._hide(this.topMarker);
  				}
  				this.arrowDim = html.contentBox(this.bottomMarker);
  
  				var headerHeight = html.contentBox(this.headerContentNode.firstChild.rows[0]).h;
  				
  				this.source = new Source(this.headerContentNode.firstChild.rows[0], {
  					horizontal: true,
  					accept: [ "gridColumn_" + this.grid.id ],
  					viewIndex: this.index,
  					generateText: false,
  					onMouseDown: lang.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 === (has("ie") ? 1 : 0)){
  								Source.prototype.onMouseDown.call(this.source, e);
  							}
  						}
  					}),
  					onMouseOver: lang.hitch(this, function(e){
  						var src = this.source;
  						if(src._getChildByEvent(e)){
  							Source.prototype.onMouseOver.apply(src, arguments);
  						}
  					}),
  					_markTargetAnchor: lang.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");
  						}
  						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 = html.contentBox(target).w + this.arrowDim.w/2 + 2;
  						}
  
  						var pos = html.position(target, true);
  						var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);
  
  						html.style(this.bottomMarker, "visibility", "visible");
  						html.style(this.topMarker, "visibility", "visible");
  						html.style(this.bottomMarker, {
  							"left": left + "px",
  							"top" : (headerHeight + pos.y) + "px"
  						});
  
  						html.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: lang.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);
  						Source.prototype._unmarkTargetAnchor.call(src);
  					}),
  					destroy: lang.hitch(this, function(){
  						connect.disconnect(this._source_conn);
  						connect.unsubscribe(this._source_sub);
  						Source.prototype.destroy.call(this.source);
  						if(this.bottomMarker){
  							html.destroy(this.bottomMarker);
  							delete this.bottomMarker;
  						}
  						if(this.topMarker){
  							html.destroy(this.topMarker);
  							delete this.topMarker;
  						}
  					}),
  					onDndCancel: lang.hitch(this, function(){
  						Source.prototype.onDndCancel.call(this.source);
  						this._hide(this.bottomMarker);
  						this._hide(this.topMarker);
  					})
  				});
  
  				this._source_conn = connect.connect(this.source, "onDndDrop", this, "_onDndDrop");
  				this._source_sub = connect.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
  				this.source.startup();
  			}
  		},
  		
  		_hide: function(node){
  			html.style(node, {
  				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 ? html.attr(n, "idx") : null;
  			};
  			var w = html.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;
  			!this.grid.isLeftToRight() && (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;
  			}
  			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);
  			if(/^\s+$/.test(n)){
  				n = '&nbsp;'//otherwise arrow styles will be messed up
  			}
  			var ret = [ '<div class="dojoxGridSortNode' ];
  			
  			if(inCell.index != inCell.grid.getSortIndex()){
  				ret.push('">');
  			}else{
  				ret = ret.concat([ ' ',
  							inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
  							'"><div class="dojoxGridArrowButtonChar">',
  							inCell.grid.sortInfo > 0 ? '&#9650;' : '&#9660;',
  							'</div><div class="dojoxGridArrowButtonNode" role="presentation"></div>',
  							'<div class="dojoxGridColCaption">']);
  			}
  			ret = ret.concat([n, '</div></div>']);
  			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 = html.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 = html.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 = query("th", this.headerContentNode);
  			var fixedWidths = array.map(cellNodes, function(c, vIdx){
  				var w = c.style.width;
  				html.attr(c, "vIdx", vIdx);
  				if(w && w.slice(-1) == "%"){
  					hasPct = true;
  				}else if(w && w.slice(-2) == "px"){
  					return window.parseInt(w, 10);
  				}
  				return html.contentBox(c).w;
  			});
  			if(hasPct){
  				array.forEach(this.grid.layout.cells, function(cell, idx){
  					if(cell.view == this){
  						var cellNode = cell.view.getHeaderCellNode(cell.index);
  						if(cellNode && html.hasAttr(cellNode, "vIdx")){
  							var vIdx = window.parseInt(html.attr(cellNode, "vIdx"));
  							this.setColWidth(idx, fixedWidths[vIdx]);
  							html.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 -= metrics.getScrollbar().h;
  				}
  				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){
  				html.attr(node,"role","presentation");
  			}else{
  				html.attr(node,"role","row");
  				if (this.grid.selectionMode != "none") {
  					node.setAttribute("aria-selected", "false"); //rows can be selected so add aria-selected prop
  				}
  			}
  			node[util.gridViewTag] = this.id;
  			node[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;
  			}
  			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 = this.grid.isLeftToRight();
  			if(this.firstScroll < 2){
  				if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
  					var s = html.marginBox(this.headerNodeContainer);
  					if(has("ie")){
  						this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
  					}else if(has("mozilla")){
  						//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;
  		},
  
  		// event handlers (direct from DOM)
  		doContentEvent: function(e){
  			if(this.content.decorateEvent(e)){
  				this.grid.onContentEvent(e);
  			}
  		},
  
  		doHeaderEvent: function(e){
  			if(this.header.decorateEvent(e)){
  				this.grid.onHeaderEvent(e);
  			}
  		},
  
  		// event dispatch(from Grid)
  		dispatchContentEvent: function(e){
  			return this.content.dispatchEvent(e);
  		},
  
  		dispatchHeaderEvent: function(e){
  			return this.header.dispatchEvent(e);
  		},
  
  		// column resizing
  		setColWidth: function(inIndex, inWidth){
  			this.grid.setCellWidth(inIndex, inWidth + 'px');
  		},
  
  		update: function(){
  			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;
  		}
  	});
  
  	var _GridAvatar = declare("dojox.grid._GridAvatar", Avatar, {
  		construct: function(){
  			var dd = win.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);
  			html.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;
  		},
  		destroy: function(){
  			dojo.dnd.manager().OFFSET_Y = this.oldOffsetY;
  			this.inherited(arguments);
  		}
  	});
  
  	var oldMakeAvatar = dojo.dnd.manager().makeAvatar;
  	dojo.dnd.manager().makeAvatar = function(){
  		var src = this.source;
  		if(src.viewIndex !== undefined && !html.hasClass(win.body(),"dijit_a11y")){
  			return new _GridAvatar(this);
  		}
  		return oldMakeAvatar.call(dojo.dnd.manager());
  	};
  
  	return _View;
  
  }); 