Author: abelevich
Date: 2007-05-31 13:21:30 -0400 (Thu, 31 May 2007)
New Revision: 963
Added:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js
Removed:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js
Modified:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridBody2.js
Log:
Modified:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridBody2.js
===================================================================
---
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridBody2.js 2007-05-31
17:21:16 UTC (rev 962)
+++
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridBody2.js 2007-05-31
17:21:30 UTC (rev 963)
@@ -181,10 +181,6 @@
if(ClientUILib.isGecko) {
this.defaultRowHeight -= this.getBorderWidth("tb") +
this.getPadding("tb");
}
- for(var i=0; i<this.rowsCount; i++) {
- templFrozen.rows[i].index = i;
- templNormal.rows[i].index = i;
- }
this.helpObj = new ClientUI.common.box.Box(templFrozen, null, true);
this.countToLoad = 0;
this.startRow = 0;
@@ -283,7 +279,7 @@
else if(to == this.grid.dataModel.getCount()) {
from = to - this.rowsCount;
}
-
+
var range = $R(from, to);
if(this.currRange.start == from && this.currRange.end == to) {
@@ -375,7 +371,7 @@
}
if(switchType === 0) {
- startRowIndx = this.templFrozen.getElement().rows[0].index;
+ startRowIndx = this._getRowIndex(this.templFrozen.getElement().rows[0].id);
startIndex = range.start;
countToLoad = range.end - range.start;
}
@@ -389,7 +385,7 @@
switchType = 1;
countToLoad = range.start - this.currRange.start;
if(countToLoad > 0) {
- startRowIndx = frozenTbl.rows[0].index;
+ startRowIndx = this._getRowIndex(frozenTbl.rows[0].id);
startIndex = this.currRange.end;
}
}
@@ -399,7 +395,7 @@
if(countToLoad > 0) {
startIndex = this.currRange.end;
var restCount = this.rowsCount - countToLoad;
- startRowIndx = frozenTbl.rows[restCount].index;
+ startRowIndx = this._getRowIndex(frozenTbl.rows[restCount].id);
}
}
else {
@@ -408,7 +404,7 @@
if(countToLoad > 0) {
startIndex = range.start;
var restCount = this.rowsCount - countToLoad;
- startRowIndx = frozenTbl.rows[restCount].index;
+ startRowIndx = this._getRowIndex(frozenTbl.rows[restCount].id);
}
}
}
@@ -430,6 +426,7 @@
this.taskDefineTime = (new Date()).getTime();
this.showSplash();
+ this.container.hide();
var options = {
index: startIndex,
@@ -437,13 +434,18 @@
startRow: startRowIndx,
switchType: switchType
};
+ var opt = {
+ index: options.index,
+ count: options.count,
+ startRow: options.startRow,
+ switchType: options.switchType
+ };
options = this.processCashedValues(options);
if(options.count > 0) {
// Make timer to handle quick clicks on scrollbar arrows
setTimeout(function() {
// 4. start data loading
- this.container.hide();
this.updateInterval = screen.updateInterval;
screen.updateInterval = 1000;
@@ -451,6 +453,7 @@
}.bind(this), 10);
}
else {
+ this.invalidate(opt);
this.updateStarted = false;
}
}
@@ -596,10 +599,10 @@
setTimeout(function () {
this.rearrangeRows(options, true, true);
+ this.container.show();
this.splash.hide();
this.updateStarted = false;
-
}.bind(this), 10);
/*if(this.processedPos != this.currentPos) {
@@ -626,55 +629,90 @@
}
return this.cash;
},
+ _restoreFromCash: function(options) {
+ var count = options.count;
+ var index = options.index;
+ var startRow = options.startRow;
+ var cash = this.getCash();
+ var frows = this.templFrozen.getElement().rows;
+ var nrows = this.templNormal.getElement().rows;
+
+ var row, rowU, i=0;
+ var rowC = cash.getRow(index);
+ do {
+ row = frows[startRow];
+ rowU = row.cloneNode(true);
+ rowU.innerHTML = rowC.f;
+ row.parentNode.replaceChild(rowU, row);
+
+ row = nrows[startRow];
+ rowU = row.cloneNode(true);
+ rowU.innerHTML = rowC.n;
+ row.parentNode.replaceChild(rowU, row);
+
+ i++;
+ startRow++;
+ if(startRow >= this.rowsCount) startRow = 0;
+ rowC = cash.getRow(index + i);
+ } while(i<count && rowC);
+
+ setTimeout(function () {
+ this.rearrangeRows(options);
+ this.container.show();
+ this.splash.hide();
+ this.updateStarted = false;
+
+ }.bind(this), 10);
+ },
processCashedValues: function(options) {
return options;
+ var opt = {switchType: options.switchType };
var cash = this.getCash();
- var opt = {};
- var frows = this.templFrozen.getElement().rows;
- var nrows = this.templNormal.getElement().rows;
+ var count = options.count;
+ var index = options.index;
+ var startRow = options.startRow;
+
+ var i = 0;
+ var rowC;
- var i = 0;
- var count = opt.count;
- var index = opt.index;
- var startRow = opt.startRow;
- var rowC, row, rowU;
- while(i<count && !(rowC = cash.getRow(index + i))) i++;
- if(i<count) {
- if(i > 0) {
- options.count = i;
- }
- opt.count = count - i;
- opt.index = index + i;
- startRow += i;
- if(startRow >= this.rowsCount) startRow -= this.rowsCount;
+ while(i<count && (rowC = cash.getRow(index + i))!=null) i++;
+ if(i>0) { // there are cashed rows from start
+ opt.count = i;
+ opt.index = index;
opt.startRow = startRow;
+ this._restoreFromCash(opt);
- do {
- row = frows[startRow];
- rowU = row.cloneNode(true);
- rowU.innerHTML = rowC.f;
- row.parentNode.replaceChild(rowU, row);
-
- row = nrows[startRow];
- rowU = row.cloneNode(true);
- rowU.innerHTML = rowC.n;
- row.parentNode.replaceChild(rowU, row);
+ options.count -= i;
+ options.index = index+i;
+ options.startRow = startRow+i;
+ if(options.startRow >= this.rowsCount) options.startRow -= this.rowsCount;
+ }
+
+ var cnt = 0;
+ while(i<count && !(rowC = cash.getRow(index + i))) { i++; cnt++; }
+ if(i<count) { // there are cashed rows at the end of range
+ opt.count = options.count - cnt;
+ opt.index = index+i;
+ opt.startRow = startRow+i;
+ if(opt.startRow >= this.rowsCount) opt.startRow -= this.rowsCount;
+ this._restoreFromCash(opt);
- i++;
- startRow++;
- if(startRow >= this.rowsCount) startRow = 0;
- rowC = cash.getRow(index + i);
- } while(i<count && rowC);
-
- if(i<=count) {
- options.count = count - i;
- options.index = index + i;
- opt.count = i;
- }
- this.rearrangeRows(opt);
+ options.count = cnt;
+ options.index = index+(i-cnt);
+ options.startRow = startRow+(i-cnt);
+ if(options.startRow >= this.rowsCount) options.startRow -= this.rowsCount;
}
return options;
+ },
+ _getRowIndex: function(rowId) {
+ // prefix:row_2
+ var index = -1;
+ var match, pattern = /\:row_(\d*)/i;
+ if (match = rowId.match(pattern)) {
+ index = parseFloat(match[1]);
+ }
+ return index;
}
});
Deleted:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js
===================================================================
---
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js 2007-05-31
17:21:16 UTC (rev 962)
+++
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js 2007-05-31
17:21:30 UTC (rev 963)
@@ -1,437 +0,0 @@
-/*
- * TODO: Copyright (c) 2007 Denis Morozov <dmorozov(a)exadel.com>
- *
- * ...
- */
-ClientUILib.declarePackage("ClientUI.controls.grid.GridHeader");
-
-ClientUILib.requireClass("ClientUI.common.box.Box");
-ClientUILib.requireClass("ClientUI.common.box.InlineBox");
-
-/*
- * GridHeader.js - Grid control header pane
- * TODO: add comments
- */
-ClientUI.controls.grid.GridHeader = Class.create({
- CLASSDEF: {
- name: 'ClientUI.controls.grid.GridHeader',
- parent: ClientUI.common.box.Box,
- sepStyleClass: "ClientUI_Grid_HSep"
- }
-
-});
-
-Object.extend(ClientUI.controls.grid.GridHeader.prototype, {
- // internal variables
- _columns: [],
-
- // constructor
- initialize: function(template, grid) {
- this.grid = grid;
-
- ClientUI.controls.grid.GridHeader.parentClass.constructor().call(this, template);
-
- // register event handlers
- this.eventSepDblClick = this.OnSepDblClick.bindAsEventListener(this);
- this.eventSepMouseDown = this.OnSepMouseDown.bindAsEventListener(this);
- this.eventSepMouseUp = this.OnSepMouseUp.bindAsEventListener(this);
- this.eventSepMouseMove = this.OnSepMouseMove.bindAsEventListener(this);
- this.eventCellMouseDown = this.OnCellMouseDown.bindAsEventListener(this);
- Event.observe(document, 'mousemove', this.eventSepMouseMove, true);
- Event.observe(document, 'mouseup', this.eventSepMouseUp, true);
-
- this.createControl(template);
- },
-
- // create grid header control
- createControl: function(template) {
- var errMsg = "";
- if(!template) {
- errMsg = "Invalid template specified for GridHeader.";
- ClientUILib.log(ClientUILogger.ERROR, errMsg);
- throw(errMsg);
- }
-
- if(!this.parseTemplate(template)) {
- errMsg = "Unable to parse template. GridHeader requires template specified over
table element with one row.";
- ClientUILib.log(ClientUILogger.ERROR, errMsg);
- throw(errMsg);
- }
-
- // Set dimensions
- this.setHeight(this.defaultHeight);
- this.setWidth(this.defaultWidth);
- this.controlCreated = true;
- this.updateLayout();
- this.hide();
- this.show();
- },
- parseTemplate: function(template) {
- if(!template) {
- return false;
- }
-
- var childs = template.childNodes;
- for(var i=0; i<childs.length; i++) {
- if(childs[i].tagName && childs[i].tagName.toLowerCase() == "div") {
- this.container = $(childs[i]);
- break;
- }
- }
-
- var normal = null, frozen = null;
- var childs = this.container.childNodes;
- for(var i=0; i<childs.length; i++) {
- if(childs[i].id && childs[i].id.indexOf("FrozenBox")>=0) {
- frozen = childs[i];
- }
- else if(childs[i].id && childs[i].id.indexOf("NormalBox")>=0){
- normal = childs[i];
- }
- }
-
- if(!normal || !frozen) {
- errMsg = "Unable to parse template for GridHeader. Unable to find FrozenBox or
NormalBox.";
- ClientUILib.log(ClientUILogger.ERROR, errMsg);
- throw(errMsg);
- }
- this.contentBox = new ClientUI.common.box.Box(normal);
- this.contentBox.makeAbsolute();
- this.frozenContentBox = new ClientUI.common.box.Box(frozen);
- this.frozenContentBox.makeAbsolute();
-
- // create row template
- var ch = this.contentBox.getElement().firstChild;
- while(ch) {
- if(ch.tagName && ch.tagName.toLowerCase()=="table") {
- this.headerRow = new ClientUI.common.box.Box($(ch), null, true);
- break;
- }
- ch = ch.nextSibling;
- }
- ch = this.frozenContentBox.getElement().firstChild;
- while(ch) {
- if(ch.tagName && ch.tagName.toLowerCase()=="table") {
- this.headerFrozenRow = new ClientUI.common.box.Box($(ch), null, true);
- break;
- }
- ch = ch.nextSibling;
- }
-
- this.helpObj = new ClientUI.common.box.Box(this.frozenContentBox.getElement(), null,
true);
-
- var columns = [];
- var defaultWidth = 0;
- var defaultHeight = 0;
-
- var eventCellMouseDown = this.eventCellMouseDown.bind(this);
-
- // Get columns information
- var i = 0, h;
- var cells = $A(this.headerFrozenRow.getElement().rows[0].cells);
- cells.each(function(cell) {
- columns[i] = {
- width: Element.getWidth(cell),
- innerHTML: cell.innerHTML,
- styleClass: cell.className,
- id: cell.id,
- align: cell.align,
- valign: cell.vAlign,
- title: cell.title,
- minWidth: 10,
- frozen: true,
- fixedWidth: Validators.getBoolean(cell.getAttribute("fixedWidth"), false),
- sortable: Validators.getBoolean(cell.getAttribute("sortable"), true),
- sorted: Validators.getBoolean(cell.getAttribute("sorted"),
"desc")
- };
-
- if(columns[i].sortable)
- Event.observe(cell, 'click', eventCellMouseDown);
- h = Element.getHeight(cell);
- if(h > defaultHeight) defaultHeight = h;
- defaultWidth += columns[i].width;
- columns[i].object = new ClientUI.common.box.InlineBox(cell, null, true);
- columns[i].sortDesc = document.getElementsByClassName("sort-desc",
cell)[0];
- columns[i].sortAsc = document.getElementsByClassName("sort-asc", cell)[0];
- if(ClientUILib.isIE && columns[i].sortDesc) {
- Element.setStyle(columns[i].sortDesc, {left: "-10px"});
- Element.setStyle(columns[i].sortAsc, {left: "-10px"});
- }
- i++;
- });
-
- cells = $A(this.headerRow.getElement().rows[0].cells);
- cells.each(function(cell) {
- columns[i] = {
- width: Element.getWidth(cell),
- innerHTML: cell.innerHTML,
- styleClass: cell.className,
- id: cell.id,
- align: cell.align,
- valign: cell.vAlign,
- title: cell.title,
- minWidth: 10,
- frozen: false,
- fixedWidth: Validators.getBoolean(cell.getAttribute("fixedWidth"), false),
- sortable: Validators.getBoolean(cell.getAttribute("sortable"), true),
- sorted: Validators.getBoolean(cell.getAttribute("sorted"),
"desc")
- };
-
- if(columns[i].sortable)
- Event.observe(cell, 'click', eventCellMouseDown);
- h = Element.getHeight(cell);
- if(h > defaultHeight) defaultHeight = h;
- defaultWidth += columns[i].width;
- columns[i].object = new ClientUI.common.box.InlineBox(cell, null, true);
- columns[i].sortDesc = document.getElementsByClassName("sort-desc",
cell)[0];
- columns[i].sortAsc = document.getElementsByClassName("sort-asc", cell)[0];
- if(ClientUILib.isIE && columns[i].sortDesc) {
- Element.setStyle(columns[i].sortDesc, {left: "-10px"});
- Element.setStyle(columns[i].sortAsc, {left: "-10px"});
- }
- i++;
- });
-
- columns.pop(); // remove last fake column
- this._columns = columns;
- this.defaultHeight = defaultHeight;
- this.defaultWidth = defaultWidth;
- if(ClientUILib.isGecko) {
- this.defaultWidth -= this.getBorderWidth("lr") +
this.getPadding("lr");
- this.defaultHeight -= this.getBorderWidth("tb") +
this.getPadding("tb");
- }
-
- var sep, column;
- var seps = document.getElementsByClassName("ClientUI_Grid_HSep",
this.getElement());
- for(i = 0; i<seps.length; i++) {
- sep = seps[i];
- column = parseInt(sep.getAttribute("column"));
- this._columns[column].sep = new ClientUI.common.box.InlineBox(sep, null, true);
- sep.columnIndex = column;
- if(!this._columns[column].fixedWidth) {
- Event.observe(sep, 'dblclick', this.eventSepDblClick);
- Event.observe(sep, 'mousedown', this.eventSepMouseDown);
- }
- else {
- sep.setStyle({cursor: 'auto'});
- }
- }
- this.agjustSeparators();
-
- if(ClientUILib.isIE) {
- this.frozenSubstrate = new ClientUI.common.box.Substrate(null, this.getElement());
- this.frozenSubstrate.getElement().name = this.getElement().id + "HRFrm";
- Element.addClassName(this.frozenSubstrate.getElement(), "ClientUI_HRFrm");
- this.frozenSubstrate.setHeight(this.headerRow.getViewportHeight());
- }
-
- return true;
- },
- agjustSeparators: function() {
- var offset = 0;
- var fcnt = this.headerFrozenRow.getElement().rows[0].cells.length;
- for(var i=0; i<this._columns.length - 1; i++) {
- if(i == fcnt) offset = 0;
- offset += this._columns[i].width;
- this._columns[i].sep.moveToX(offset - 4);
- }
- },
- updateLayout: function() {
- if(!this.controlCreated || !this.grid.controlCreated) {
- return;
- }
- ClientUI.controls.grid.GridHeader.parentClass.method("updateLayout").call(this);
- var height = this.getViewportHeight();
- var totalWidth = this.grid.getColumnsTotalWidth();
- var frozenContentWidth = this.grid.getColumnsFrozenWidth();
-
- this.contentBox.setWidth(Math.max(this.getWidth(), totalWidth));
- this.contentBox.setHeight(height);
- this.contentBox.moveTo(frozenContentWidth, 0);
- this.frozenContentBox.setWidth(frozenContentWidth);
- this.frozenContentBox.setHeight(height);
- this.frozenContentBox.moveTo(0, 0);
- if(ClientUILib.isIE)
- this.frozenSubstrate.setWidth(frozenContentWidth);
- },
- getColumns: function() {
- return this._columns;
- },
- // lets implement column resizer
- OnSepMouseDown: function(event) {
- this.dragColumnInfo = {
- srcElement: Event.element(event),
- dragStarted: false,
- mouseDown: true,
- startX: Event.pointerX(event),
- originalX: 0
- };
- this.dragColumnInfo.object =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].object;
- this.dragColumnInfo.sep =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].sep;
- this.dragColumnInfo.minWidth =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].minWidth;
-
- Event.stop(event);
- },
- OnSepMouseUp: function(event) {
- if(this.dragColumnInfo && this.dragColumnInfo.dragStarted) {
- this.dragColumnInfo.dragStarted = false;
- this.dragColumnInfo.mouseDown = false;
- var delta = Event.pointerX(event) - this.dragColumnInfo.startX;
- var newWidth = this.dragColumnInfo.object.getWidth() + delta;
- setTimeout(function() {
- this.grid.adjustColumnWidth(this.dragColumnInfo.srcElement.columnIndex, newWidth);
- }.bind(this), 10);
- }
- this._hideSplitter();
- },
- OnSepMouseMove: function(event) {
- if(this.dragColumnInfo && this.dragColumnInfo.mouseDown) {
- if(!this.dragColumnInfo.dragStarted) {
- this.dragColumnInfo.dragStarted = true;
- this._showSplitter(this.dragColumnInfo.srcElement.columnIndex);
- }
- else {
- var delta = Event.pointerX(event) - this.dragColumnInfo.startX;
- var minColumnWidth = this.dragColumnInfo.object.getWidth() -
this.dragColumnInfo.minWidth;
- if(delta >= -minColumnWidth) {
- var x = this.dragColumnInfo.originalX + delta;
- this.columnSplitter.moveToX(x - 6);
- }
- }
- Event.stop(event);
- }
- },
- OnSepDblClick: function(event) {
- ClientUILib.log(ClientUILogger.INFO, "OnSepDblClick");
- },
- _showSplitter: function(index) {
- if(!this.columnSplitter) {
- this._createSplitter();
- }
-
- var pos = this.dragColumnInfo.sep.getX();
- if(!this.getColumns()[index].frozen) {
- pos += this.grid.getColumnsFrozenWidth() - this.grid.getScrollOffset();
- }
- this.dragColumnInfo.originalX = pos;
- this.columnSplitter.show();
- this.columnSplitter.setHeight(this.defaultHeight +
this.grid.getBody().contentBox.getHeight());
- this.columnSplitter.moveTo(pos, 0);
- },
- _hideSplitter: function() {
- if(this.columnSplitter) {
- this.columnSplitter.hide();
- }
- },
- _createSplitter: function() {
- this.columnSplitter = new ClientUI.common.box.Box(null, this.grid.getElement());
- this.columnSplitter.makeAbsolute();
- this.columnSplitter.getElement().addClassName("ClientUI_Grid_HSplit");
- this.columnSplitter.setWidth(10);
- this.columnSplitter.getElement().setStyle({backgroundColor: ''});
- this.columnSplitter.getElement().setStyle({zIndex: '100'});
- this.columnSplitter.hide();
- },
- adjustScrollPosition: function(pos) {
- this.contentBox.moveToX(this.grid.getColumnsFrozenWidth()-pos);
- },
- OnCellMouseDown: function(event) {
- var el = Event.element(event);
- while(el && !Element.hasClassName(el, "ClientUI_Grid_HC")) {
- el = el.parentNode;
- }
-
- if(el) {
- var index = parseInt(el.getAttribute("columnIndex"));
- if(index>=0) {
- var dir = this.getColumns()[index].sorted;
- dir = (dir == "asc") ? "desc" : "asc";
- this.getColumns()[index].sorted = dir;
-
- for(var i = 0, len = this.getColumns().length; i < len; i++) {
- var h = this.getColumns()[i];
- if(i != index) {
- Element.setStyle(h.sortDesc, {display: 'none'});
- Element.setStyle(h.sortAsc, {display: 'none'});
- } else{
- Element.setStyle(h.sortDesc, {display: (dir == 'desc' ? 'block' :
'none')});
- Element.setStyle(h.sortAsc, {display: (dir == 'asc' ? 'block' :
'none')});
- }
- }
-
- this.grid.eventOnSort.fire({
- column: index,
- order: dir,
- startRow: this.grid.getBody().templFrozen.getElement().rows[0].index,
- index: this.grid.getBody().currRange.start
- });
- Event.stop(event);
- }
- }
- },
- _getVisibleHeaderControls: function() {
- var controls = [];
- var columns = this.getColumns();
- columns.each(function(column){
- var ctrls = column.object.getElement().getElementsByTagName("select");
- if(ctrls && ctrls.length>0) {
- ctrls = $A(ctrls);
- ctrls.each(function(ctrl){
- if(Element.visible(ctrl)) {
- controls.push(ctrl);
- }
- });
- }
- });
- return controls;
- },
- adjustColumnWidth: function(column, width) {
- var w = width, ch;
- var frozenColumns = this.headerFrozenRow.getElement().rows[0].cells.length;
- var realColumn = column;
- var table = null;
- if(column < frozenColumns) {
- table = this.headerFrozenRow.getElement();
- }
- else {
- table = this.headerRow.getElement();
- realColumn -= frozenColumns;
- }
-
- // Hide controls in IE that flipped in other case
- var ctrlsIE = [];
- if(ClientUILib.isIE) {
- ctrlsIE = this._getVisibleHeaderControls();
- ctrlsIE.each(function(ctrl){
- Element.hide(ctrl);
- });
- }
-
- var childs = table.rows[0].cells[realColumn].childNodes;
- this.helpObj.element = $(table.rows[0].cells[realColumn]);
- var delta = 0;
- if(ClientUILib.isGecko) {
- delta = this.helpObj.getBorderWidth("lr") +
this.helpObj.getPadding("lr");
- }
- this.helpObj.setWidth(width - delta);
- delta *= 2;
-
- for (var j=0; j<childs.length; j++) {
- ch = childs[j];
- if(ch.tagName && ch.tagName.toLowerCase() == "span") {
- this.helpObj.element = $(ch);
- this.helpObj.setWidth(width - delta);
- break;
- }
- }
-
- if(ClientUILib.isIE) {
- ctrlsIE.each(function(ctrl){
- Element.show(ctrl);
- });
- }
-
- this._columns[column].width = width;
- this.agjustSeparators();
- }
-});
Added:
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js
===================================================================
---
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js
(rev 0)
+++
trunk/sandbox/scrollable-grid/src/main/javascript/ClientUI/controls/grid/GridHeader2.js 2007-05-31
17:21:30 UTC (rev 963)
@@ -0,0 +1,437 @@
+/*
+ * TODO: Copyright (c) 2007 Denis Morozov <dmorozov(a)exadel.com>
+ *
+ * ...
+ */
+ClientUILib.declarePackage("ClientUI.controls.grid.GridHeader");
+
+ClientUILib.requireClass("ClientUI.common.box.Box");
+ClientUILib.requireClass("ClientUI.common.box.InlineBox");
+
+/*
+ * GridHeader.js - Grid control header pane
+ * TODO: add comments
+ */
+ClientUI.controls.grid.GridHeader = Class.create({
+ CLASSDEF: {
+ name: 'ClientUI.controls.grid.GridHeader',
+ parent: ClientUI.common.box.Box,
+ sepStyleClass: "ClientUI_Grid_HSep"
+ }
+
+});
+
+Object.extend(ClientUI.controls.grid.GridHeader.prototype, {
+ // internal variables
+ _columns: [],
+
+ // constructor
+ initialize: function(template, grid) {
+ this.grid = grid;
+
+ ClientUI.controls.grid.GridHeader.parentClass.constructor().call(this, template);
+
+ // register event handlers
+ this.eventSepDblClick = this.OnSepDblClick.bindAsEventListener(this);
+ this.eventSepMouseDown = this.OnSepMouseDown.bindAsEventListener(this);
+ this.eventSepMouseUp = this.OnSepMouseUp.bindAsEventListener(this);
+ this.eventSepMouseMove = this.OnSepMouseMove.bindAsEventListener(this);
+ this.eventCellMouseDown = this.OnCellMouseDown.bindAsEventListener(this);
+ Event.observe(document, 'mousemove', this.eventSepMouseMove, true);
+ Event.observe(document, 'mouseup', this.eventSepMouseUp, true);
+
+ this.createControl(template);
+ },
+
+ // create grid header control
+ createControl: function(template) {
+ var errMsg = "";
+ if(!template) {
+ errMsg = "Invalid template specified for GridHeader.";
+ ClientUILib.log(ClientUILogger.ERROR, errMsg);
+ throw(errMsg);
+ }
+
+ if(!this.parseTemplate(template)) {
+ errMsg = "Unable to parse template. GridHeader requires template specified over
table element with one row.";
+ ClientUILib.log(ClientUILogger.ERROR, errMsg);
+ throw(errMsg);
+ }
+
+ // Set dimensions
+ this.setHeight(this.defaultHeight);
+ this.setWidth(this.defaultWidth);
+ this.controlCreated = true;
+ this.updateLayout();
+ this.hide();
+ this.show();
+ },
+ parseTemplate: function(template) {
+ if(!template) {
+ return false;
+ }
+
+ var childs = template.childNodes;
+ for(var i=0; i<childs.length; i++) {
+ if(childs[i].tagName && childs[i].tagName.toLowerCase() == "div") {
+ this.container = $(childs[i]);
+ break;
+ }
+ }
+
+ var normal = null, frozen = null;
+ var childs = this.container.childNodes;
+ for(var i=0; i<childs.length; i++) {
+ if(childs[i].id && childs[i].id.indexOf("FrozenBox")>=0) {
+ frozen = childs[i];
+ }
+ else if(childs[i].id && childs[i].id.indexOf("NormalBox")>=0){
+ normal = childs[i];
+ }
+ }
+
+ if(!normal || !frozen) {
+ errMsg = "Unable to parse template for GridHeader. Unable to find FrozenBox or
NormalBox.";
+ ClientUILib.log(ClientUILogger.ERROR, errMsg);
+ throw(errMsg);
+ }
+ this.contentBox = new ClientUI.common.box.Box(normal);
+ this.contentBox.makeAbsolute();
+ this.frozenContentBox = new ClientUI.common.box.Box(frozen);
+ this.frozenContentBox.makeAbsolute();
+
+ // create row template
+ var ch = this.contentBox.getElement().firstChild;
+ while(ch) {
+ if(ch.tagName && ch.tagName.toLowerCase()=="table") {
+ this.headerRow = new ClientUI.common.box.Box($(ch), null, true);
+ break;
+ }
+ ch = ch.nextSibling;
+ }
+ ch = this.frozenContentBox.getElement().firstChild;
+ while(ch) {
+ if(ch.tagName && ch.tagName.toLowerCase()=="table") {
+ this.headerFrozenRow = new ClientUI.common.box.Box($(ch), null, true);
+ break;
+ }
+ ch = ch.nextSibling;
+ }
+
+ this.helpObj = new ClientUI.common.box.Box(this.frozenContentBox.getElement(), null,
true);
+
+ var columns = [];
+ var defaultWidth = 0;
+ var defaultHeight = 0;
+
+ var eventCellMouseDown = this.eventCellMouseDown.bind(this);
+
+ // Get columns information
+ var i = 0, h;
+ var cells = $A(this.headerFrozenRow.getElement().rows[0].cells);
+ cells.each(function(cell) {
+ columns[i] = {
+ width: Element.getWidth(cell),
+ innerHTML: cell.innerHTML,
+ styleClass: cell.className,
+ id: cell.id,
+ align: cell.align,
+ valign: cell.vAlign,
+ title: cell.title,
+ minWidth: 10,
+ frozen: true,
+ fixedWidth: Validators.getBoolean(cell.getAttribute("fixedWidth"), false),
+ sortable: Validators.getBoolean(cell.getAttribute("sortable"), false),
+ sorted: Validators.getBoolean(cell.getAttribute("sorted"),
"desc")
+ };
+
+ if(columns[i].sortable)
+ Event.observe(cell, 'click', eventCellMouseDown);
+ h = Element.getHeight(cell);
+ if(h > defaultHeight) defaultHeight = h;
+ defaultWidth += columns[i].width;
+ columns[i].object = new ClientUI.common.box.InlineBox(cell, null, true);
+ columns[i].sortDesc = document.getElementsByClassName("sort-desc",
cell)[0];
+ columns[i].sortAsc = document.getElementsByClassName("sort-asc", cell)[0];
+ if(ClientUILib.isIE && columns[i].sortDesc) {
+ Element.setStyle(columns[i].sortDesc, {left: "-10px"});
+ Element.setStyle(columns[i].sortAsc, {left: "-10px"});
+ }
+ i++;
+ });
+
+ cells = $A(this.headerRow.getElement().rows[0].cells);
+ cells.each(function(cell) {
+ columns[i] = {
+ width: Element.getWidth(cell),
+ innerHTML: cell.innerHTML,
+ styleClass: cell.className,
+ id: cell.id,
+ align: cell.align,
+ valign: cell.vAlign,
+ title: cell.title,
+ minWidth: 10,
+ frozen: false,
+ fixedWidth: Validators.getBoolean(cell.getAttribute("fixedWidth"), false),
+ sortable: Validators.getBoolean(cell.getAttribute("sortable"), false),
+ sorted: Validators.getBoolean(cell.getAttribute("sorted"),
"desc")
+ };
+
+ if(columns[i].sortable)
+ Event.observe(cell, 'click', eventCellMouseDown);
+ h = Element.getHeight(cell);
+ if(h > defaultHeight) defaultHeight = h;
+ defaultWidth += columns[i].width;
+ columns[i].object = new ClientUI.common.box.InlineBox(cell, null, true);
+ columns[i].sortDesc = document.getElementsByClassName("sort-desc",
cell)[0];
+ columns[i].sortAsc = document.getElementsByClassName("sort-asc", cell)[0];
+ if(ClientUILib.isIE && columns[i].sortDesc) {
+ Element.setStyle(columns[i].sortDesc, {left: "-10px"});
+ Element.setStyle(columns[i].sortAsc, {left: "-10px"});
+ }
+ i++;
+ });
+
+ columns.pop(); // remove last fake column
+ this._columns = columns;
+ this.defaultHeight = defaultHeight;
+ this.defaultWidth = defaultWidth;
+ if(ClientUILib.isGecko) {
+ this.defaultWidth -= this.getBorderWidth("lr") +
this.getPadding("lr");
+ this.defaultHeight -= this.getBorderWidth("tb") +
this.getPadding("tb");
+ }
+
+ var sep, column;
+ var seps = document.getElementsByClassName("ClientUI_Grid_HSep",
this.getElement());
+ for(i = 0; i<seps.length; i++) {
+ sep = seps[i];
+ column = parseInt(sep.getAttribute("column"));
+ this._columns[column].sep = new ClientUI.common.box.InlineBox(sep, null, true);
+ sep.columnIndex = column;
+ if(!this._columns[column].fixedWidth) {
+ Event.observe(sep, 'dblclick', this.eventSepDblClick);
+ Event.observe(sep, 'mousedown', this.eventSepMouseDown);
+ }
+ else {
+ sep.setStyle({cursor: 'auto'});
+ }
+ }
+ this.agjustSeparators();
+
+ if(ClientUILib.isIE) {
+ this.frozenSubstrate = new ClientUI.common.box.Substrate(null, this.getElement());
+ this.frozenSubstrate.getElement().name = this.getElement().id + "HRFrm";
+ Element.addClassName(this.frozenSubstrate.getElement(), "ClientUI_HRFrm");
+ this.frozenSubstrate.setHeight(this.headerRow.getViewportHeight());
+ }
+
+ return true;
+ },
+ agjustSeparators: function() {
+ var offset = 0;
+ var fcnt = this.headerFrozenRow.getElement().rows[0].cells.length;
+ for(var i=0; i<this._columns.length; i++) {
+ if(i == fcnt) offset = 0;
+ offset += this._columns[i].width;
+ this._columns[i].sep.moveToX(offset - 4);
+ }
+ },
+ updateLayout: function() {
+ if(!this.controlCreated || !this.grid.controlCreated) {
+ return;
+ }
+ ClientUI.controls.grid.GridHeader.parentClass.method("updateLayout").call(this);
+ var height = this.getViewportHeight();
+ var totalWidth = this.grid.getColumnsTotalWidth();
+ var frozenContentWidth = this.grid.getColumnsFrozenWidth();
+
+ this.contentBox.setWidth(Math.max(this.getWidth(), totalWidth));
+ this.contentBox.setHeight(height);
+ this.contentBox.moveTo(frozenContentWidth, 0);
+ this.frozenContentBox.setWidth(frozenContentWidth);
+ this.frozenContentBox.setHeight(height);
+ this.frozenContentBox.moveTo(0, 0);
+ if(ClientUILib.isIE)
+ this.frozenSubstrate.setWidth(frozenContentWidth);
+ },
+ getColumns: function() {
+ return this._columns;
+ },
+ // lets implement column resizer
+ OnSepMouseDown: function(event) {
+ this.dragColumnInfo = {
+ srcElement: Event.element(event),
+ dragStarted: false,
+ mouseDown: true,
+ startX: Event.pointerX(event),
+ originalX: 0
+ };
+ this.dragColumnInfo.object =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].object;
+ this.dragColumnInfo.sep =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].sep;
+ this.dragColumnInfo.minWidth =
this.getColumns()[this.dragColumnInfo.srcElement.columnIndex].minWidth;
+
+ Event.stop(event);
+ },
+ OnSepMouseUp: function(event) {
+ if(this.dragColumnInfo && this.dragColumnInfo.dragStarted) {
+ this.dragColumnInfo.dragStarted = false;
+ this.dragColumnInfo.mouseDown = false;
+ var delta = Event.pointerX(event) - this.dragColumnInfo.startX;
+ var newWidth = this.dragColumnInfo.object.getWidth() + delta;
+ setTimeout(function() {
+ this.grid.adjustColumnWidth(this.dragColumnInfo.srcElement.columnIndex, newWidth);
+ }.bind(this), 10);
+ }
+ this._hideSplitter();
+ },
+ OnSepMouseMove: function(event) {
+ if(this.dragColumnInfo && this.dragColumnInfo.mouseDown) {
+ if(!this.dragColumnInfo.dragStarted) {
+ this.dragColumnInfo.dragStarted = true;
+ this._showSplitter(this.dragColumnInfo.srcElement.columnIndex);
+ }
+ else {
+ var delta = Event.pointerX(event) - this.dragColumnInfo.startX;
+ var minColumnWidth = this.dragColumnInfo.object.getWidth() -
this.dragColumnInfo.minWidth;
+ if(delta >= -minColumnWidth) {
+ var x = this.dragColumnInfo.originalX + delta;
+ this.columnSplitter.moveToX(x - 6);
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ OnSepDblClick: function(event) {
+ ClientUILib.log(ClientUILogger.INFO, "OnSepDblClick");
+ },
+ _showSplitter: function(index) {
+ if(!this.columnSplitter) {
+ this._createSplitter();
+ }
+
+ var pos = this.dragColumnInfo.sep.getX();
+ if(!this.getColumns()[index].frozen) {
+ pos += this.grid.getColumnsFrozenWidth() - this.grid.getScrollOffset();
+ }
+ this.dragColumnInfo.originalX = pos;
+ this.columnSplitter.show();
+ this.columnSplitter.setHeight(this.defaultHeight +
this.grid.getBody().contentBox.getHeight());
+ this.columnSplitter.moveTo(pos, 0);
+ },
+ _hideSplitter: function() {
+ if(this.columnSplitter) {
+ this.columnSplitter.hide();
+ }
+ },
+ _createSplitter: function() {
+ this.columnSplitter = new ClientUI.common.box.Box(null, this.grid.getElement());
+ this.columnSplitter.makeAbsolute();
+ this.columnSplitter.getElement().addClassName("ClientUI_Grid_HSplit");
+ this.columnSplitter.setWidth(10);
+ this.columnSplitter.getElement().setStyle({backgroundColor: ''});
+ this.columnSplitter.getElement().setStyle({zIndex: '100'});
+ this.columnSplitter.hide();
+ },
+ adjustScrollPosition: function(pos) {
+ this.contentBox.moveToX(this.grid.getColumnsFrozenWidth()-pos);
+ },
+ OnCellMouseDown: function(event) {
+ var el = Event.element(event);
+ while(el && !Element.hasClassName(el, "ClientUI_Grid_HC")) {
+ el = el.parentNode;
+ }
+
+ if(el) {
+ var index = parseInt(el.getAttribute("columnIndex"));
+ if(index>=0) {
+ var dir = this.getColumns()[index].sorted;
+ dir = (dir == "asc") ? "desc" : "asc";
+ this.getColumns()[index].sorted = dir;
+
+ for(var i = 0, len = this.getColumns().length; i < len; i++) {
+ var h = this.getColumns()[i];
+ if(i != index) {
+ Element.setStyle(h.sortDesc, {display: 'none'});
+ Element.setStyle(h.sortAsc, {display: 'none'});
+ } else{
+ Element.setStyle(h.sortDesc, {display: (dir == 'desc' ? 'block' :
'none')});
+ Element.setStyle(h.sortAsc, {display: (dir == 'asc' ? 'block' :
'none')});
+ }
+ }
+
+ this.grid.eventOnSort.fire({
+ column: index,
+ order: dir,
+ startRow:
this.grid.getBody()._getRowIndex(this.grid.getBody().templFrozen.getElement().rows[0].id),
+ index: this.grid.getBody().currRange.start
+ });
+ Event.stop(event);
+ }
+ }
+ },
+ _getVisibleHeaderControls: function() {
+ var controls = [];
+ var columns = this.getColumns();
+ columns.each(function(column){
+ var ctrls = column.object.getElement().getElementsByTagName("select");
+ if(ctrls && ctrls.length>0) {
+ ctrls = $A(ctrls);
+ ctrls.each(function(ctrl){
+ if(Element.visible(ctrl)) {
+ controls.push(ctrl);
+ }
+ });
+ }
+ });
+ return controls;
+ },
+ adjustColumnWidth: function(column, width) {
+ var w = width, ch;
+ var frozenColumns = this.headerFrozenRow.getElement().rows[0].cells.length;
+ var realColumn = column;
+ var table = null;
+ if(column < frozenColumns) {
+ table = this.headerFrozenRow.getElement();
+ }
+ else {
+ table = this.headerRow.getElement();
+ realColumn -= frozenColumns;
+ }
+
+ // Hide controls in IE that flipped in other case
+ var ctrlsIE = [];
+ if(ClientUILib.isIE) {
+ ctrlsIE = this._getVisibleHeaderControls();
+ ctrlsIE.each(function(ctrl){
+ Element.hide(ctrl);
+ });
+ }
+
+ var childs = table.rows[0].cells[realColumn].childNodes;
+ this.helpObj.element = $(table.rows[0].cells[realColumn]);
+ var delta = 0;
+ if(ClientUILib.isGecko) {
+ delta = this.helpObj.getBorderWidth("lr") +
this.helpObj.getPadding("lr");
+ }
+ this.helpObj.setWidth(width - delta);
+ delta *= 2;
+
+ for (var j=0; j<childs.length; j++) {
+ ch = childs[j];
+ if(ch.tagName && ch.tagName.toLowerCase() == "span") {
+ this.helpObj.element = $(ch);
+ this.helpObj.setWidth(width - delta);
+ break;
+ }
+ }
+
+ if(ClientUILib.isIE) {
+ ctrlsIE.each(function(ctrl){
+ Element.show(ctrl);
+ });
+ }
+
+ this._columns[column].width = width;
+ this.agjustSeparators();
+ }
+});