854 lines
26 KiB
JavaScript
854 lines
26 KiB
JavaScript
|
//>>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") < 9 ? 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 = ' '//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 ? '▲' : '▼',
|
||
|
'</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;
|
||
|
|
||
|
});
|