blob: 95facee2be82e4a6a2e4a086f2fbd6de5b0b4f55 [file] [log] [blame]
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.widget.SortableTable");
dojo.deprecated("SortableTable will be removed in favor of FilteringTable.", "0.5");
dojo.require("dojo.lang.common");
dojo.require("dojo.date.format");
dojo.require("dojo.html.*");
dojo.require("dojo.html.selection");
dojo.require("dojo.html.util");
dojo.require("dojo.html.style");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.widget.defineWidget("dojo.widget.SortableTable", dojo.widget.HtmlWidget, function () {
this.data = [];
this.selected = [];
this.columns = [];
}, {enableMultipleSelect:false, maximumNumberOfSelections:0, enableAlternateRows:false, minRows:0, defaultDateFormat:"%D", sortIndex:0, sortDirection:0, valueField:"Id", headClass:"", tbodyClass:"", headerClass:"", headerSortUpClass:"selected", headerSortDownClass:"selected", rowClass:"", rowAlternateClass:"alt", rowSelectedClass:"selected", columnSelected:"sorted-column", isContainer:false, templatePath:null, templateCssPath:null, getTypeFromString:function (s) {
var parts = s.split("."), i = 0, obj = dj_global;
do {
obj = obj[parts[i++]];
} while (i < parts.length && obj);
return (obj != dj_global) ? obj : null;
}, compare:function (o1, o2) {
for (var p in o1) {
if (!(p in o2)) {
return false;
}
if (o1[p].valueOf() != o2[p].valueOf()) {
return false;
}
}
return true;
}, isSelected:function (o) {
for (var i = 0; i < this.selected.length; i++) {
if (this.compare(this.selected[i], o)) {
return true;
}
}
return false;
}, removeFromSelected:function (o) {
var idx = -1;
for (var i = 0; i < this.selected.length; i++) {
if (this.compare(this.selected[i], o)) {
idx = i;
break;
}
}
if (idx >= 0) {
this.selected.splice(idx, 1);
}
}, getSelection:function () {
return this.selected;
}, getValue:function () {
var a = [];
for (var i = 0; i < this.selected.length; i++) {
if (this.selected[i][this.valueField]) {
a.push(this.selected[i][this.valueField]);
}
}
return a.join();
}, reset:function () {
this.columns = [];
this.data = [];
this.resetSelections(this.domNode.getElementsByTagName("tbody")[0]);
}, resetSelections:function (body) {
this.selected = [];
var idx = 0;
var rows = body.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
if (rows[i].parentNode == body) {
rows[i].removeAttribute("selected");
if (this.enableAlternateRows && idx % 2 == 1) {
rows[i].className = this.rowAlternateClass;
} else {
rows[i].className = "";
}
idx++;
}
}
}, getObjectFromRow:function (row) {
var cells = row.getElementsByTagName("td");
var o = {};
for (var i = 0; i < this.columns.length; i++) {
if (this.columns[i].sortType == "__markup__") {
o[this.columns[i].getField()] = cells[i].innerHTML;
} else {
var text = dojo.html.renderedTextContent(cells[i]);
var val = text;
if (this.columns[i].getType() != String) {
var val = new (this.columns[i].getType())(text);
}
o[this.columns[i].getField()] = val;
}
}
if (dojo.html.hasAttribute(row, "value")) {
o[this.valueField] = dojo.html.getAttribute(row, "value");
}
return o;
}, setSelectionByRow:function (row) {
var o = this.getObjectFromRow(row);
var b = false;
for (var i = 0; i < this.selected.length; i++) {
if (this.compare(this.selected[i], o)) {
b = true;
break;
}
}
if (!b) {
this.selected.push(o);
}
}, parseColumns:function (node) {
this.reset();
var row = node.getElementsByTagName("tr")[0];
var cells = row.getElementsByTagName("td");
if (cells.length == 0) {
cells = row.getElementsByTagName("th");
}
for (var i = 0; i < cells.length; i++) {
var o = {field:null, format:null, noSort:false, sortType:"String", dataType:String, sortFunction:null, label:null, align:"left", valign:"middle", getField:function () {
return this.field || this.label;
}, getType:function () {
return this.dataType;
}};
if (dojo.html.hasAttribute(cells[i], "align")) {
o.align = dojo.html.getAttribute(cells[i], "align");
}
if (dojo.html.hasAttribute(cells[i], "valign")) {
o.valign = dojo.html.getAttribute(cells[i], "valign");
}
if (dojo.html.hasAttribute(cells[i], "nosort")) {
o.noSort = dojo.html.getAttribute(cells[i], "nosort") == "true";
}
if (dojo.html.hasAttribute(cells[i], "sortusing")) {
var trans = dojo.html.getAttribute(cells[i], "sortusing");
var f = this.getTypeFromString(trans);
if (f != null && f != window && typeof (f) == "function") {
o.sortFunction = f;
}
}
if (dojo.html.hasAttribute(cells[i], "field")) {
o.field = dojo.html.getAttribute(cells[i], "field");
}
if (dojo.html.hasAttribute(cells[i], "format")) {
o.format = dojo.html.getAttribute(cells[i], "format");
}
if (dojo.html.hasAttribute(cells[i], "dataType")) {
var sortType = dojo.html.getAttribute(cells[i], "dataType");
if (sortType.toLowerCase() == "html" || sortType.toLowerCase() == "markup") {
o.sortType = "__markup__";
o.noSort = true;
} else {
var type = this.getTypeFromString(sortType);
if (type) {
o.sortType = sortType;
o.dataType = type;
}
}
}
o.label = dojo.html.renderedTextContent(cells[i]);
this.columns.push(o);
if (dojo.html.hasAttribute(cells[i], "sort")) {
this.sortIndex = i;
var dir = dojo.html.getAttribute(cells[i], "sort");
if (!isNaN(parseInt(dir))) {
dir = parseInt(dir);
this.sortDirection = (dir != 0) ? 1 : 0;
} else {
this.sortDirection = (dir.toLowerCase() == "desc") ? 1 : 0;
}
}
}
}, parseData:function (data) {
this.data = [];
this.selected = [];
for (var i = 0; i < data.length; i++) {
var o = {};
for (var j = 0; j < this.columns.length; j++) {
var field = this.columns[j].getField();
if (this.columns[j].sortType == "__markup__") {
o[field] = String(data[i][field]);
} else {
var type = this.columns[j].getType();
var val = data[i][field];
var t = this.columns[j].sortType.toLowerCase();
if (type == String) {
o[field] = val;
} else {
if (val != null) {
o[field] = new type(val);
} else {
o[field] = new type();
}
}
}
}
if (data[i][this.valueField] && !o[this.valueField]) {
o[this.valueField] = data[i][this.valueField];
}
this.data.push(o);
}
}, parseDataFromTable:function (tbody) {
this.data = [];
this.selected = [];
var rows = tbody.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
if (dojo.html.getAttribute(rows[i], "ignoreIfParsed") == "true") {
continue;
}
var o = {};
var cells = rows[i].getElementsByTagName("td");
for (var j = 0; j < this.columns.length; j++) {
var field = this.columns[j].getField();
if (this.columns[j].sortType == "__markup__") {
o[field] = cells[j].innerHTML;
} else {
var type = this.columns[j].getType();
var val = dojo.html.renderedTextContent(cells[j]);
if (type == String) {
o[field] = val;
} else {
if (val != null) {
o[field] = new type(val);
} else {
o[field] = new type();
}
}
}
}
if (dojo.html.hasAttribute(rows[i], "value") && !o[this.valueField]) {
o[this.valueField] = dojo.html.getAttribute(rows[i], "value");
}
this.data.push(o);
if (dojo.html.getAttribute(rows[i], "selected") == "true") {
this.selected.push(o);
}
}
}, showSelections:function () {
var body = this.domNode.getElementsByTagName("tbody")[0];
var rows = body.getElementsByTagName("tr");
var idx = 0;
for (var i = 0; i < rows.length; i++) {
if (rows[i].parentNode == body) {
if (dojo.html.getAttribute(rows[i], "selected") == "true") {
rows[i].className = this.rowSelectedClass;
} else {
if (this.enableAlternateRows && idx % 2 == 1) {
rows[i].className = this.rowAlternateClass;
} else {
rows[i].className = "";
}
}
idx++;
}
}
}, render:function (bDontPreserve) {
var data = [];
var body = this.domNode.getElementsByTagName("tbody")[0];
if (!bDontPreserve) {
this.parseDataFromTable(body);
}
for (var i = 0; i < this.data.length; i++) {
data.push(this.data[i]);
}
var col = this.columns[this.sortIndex];
if (!col.noSort) {
var field = col.getField();
if (col.sortFunction) {
var sort = col.sortFunction;
} else {
var sort = function (a, b) {
if (a[field] > b[field]) {
return 1;
}
if (a[field] < b[field]) {
return -1;
}
return 0;
};
}
data.sort(sort);
if (this.sortDirection != 0) {
data.reverse();
}
}
while (body.childNodes.length > 0) {
body.removeChild(body.childNodes[0]);
}
for (var i = 0; i < data.length; i++) {
var row = document.createElement("tr");
dojo.html.disableSelection(row);
if (data[i][this.valueField]) {
row.setAttribute("value", data[i][this.valueField]);
}
if (this.isSelected(data[i])) {
row.className = this.rowSelectedClass;
row.setAttribute("selected", "true");
} else {
if (this.enableAlternateRows && i % 2 == 1) {
row.className = this.rowAlternateClass;
}
}
for (var j = 0; j < this.columns.length; j++) {
var cell = document.createElement("td");
cell.setAttribute("align", this.columns[j].align);
cell.setAttribute("valign", this.columns[j].valign);
dojo.html.disableSelection(cell);
if (this.sortIndex == j) {
cell.className = this.columnSelected;
}
if (this.columns[j].sortType == "__markup__") {
cell.innerHTML = data[i][this.columns[j].getField()];
for (var k = 0; k < cell.childNodes.length; k++) {
var node = cell.childNodes[k];
if (node && node.nodeType == dojo.html.ELEMENT_NODE) {
dojo.html.disableSelection(node);
}
}
} else {
if (this.columns[j].getType() == Date) {
var format = this.defaultDateFormat;
if (this.columns[j].format) {
format = this.columns[j].format;
}
cell.appendChild(document.createTextNode(dojo.date.strftime(data[i][this.columns[j].getField()], format)));
} else {
cell.appendChild(document.createTextNode(data[i][this.columns[j].getField()]));
}
}
row.appendChild(cell);
}
body.appendChild(row);
dojo.event.connect(row, "onclick", this, "onUISelect");
}
var minRows = parseInt(this.minRows);
if (!isNaN(minRows) && minRows > 0 && data.length < minRows) {
var mod = 0;
if (data.length % 2 == 0) {
mod = 1;
}
var nRows = minRows - data.length;
for (var i = 0; i < nRows; i++) {
var row = document.createElement("tr");
row.setAttribute("ignoreIfParsed", "true");
if (this.enableAlternateRows && i % 2 == mod) {
row.className = this.rowAlternateClass;
}
for (var j = 0; j < this.columns.length; j++) {
var cell = document.createElement("td");
cell.appendChild(document.createTextNode("\xa0"));
row.appendChild(cell);
}
body.appendChild(row);
}
}
}, onSelect:function (e) {
}, onUISelect:function (e) {
var row = dojo.html.getParentByType(e.target, "tr");
var body = dojo.html.getParentByType(row, "tbody");
if (this.enableMultipleSelect) {
if (e.metaKey || e.ctrlKey) {
if (this.isSelected(this.getObjectFromRow(row))) {
this.removeFromSelected(this.getObjectFromRow(row));
row.removeAttribute("selected");
} else {
this.setSelectionByRow(row);
row.setAttribute("selected", "true");
}
} else {
if (e.shiftKey) {
var startRow;
var rows = body.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
if (rows[i].parentNode == body) {
if (rows[i] == row) {
break;
}
if (dojo.html.getAttribute(rows[i], "selected") == "true") {
startRow = rows[i];
}
}
}
if (!startRow) {
startRow = row;
for (; i < rows.length; i++) {
if (dojo.html.getAttribute(rows[i], "selected") == "true") {
row = rows[i];
break;
}
}
}
this.resetSelections(body);
if (startRow == row) {
row.setAttribute("selected", "true");
this.setSelectionByRow(row);
} else {
var doSelect = false;
for (var i = 0; i < rows.length; i++) {
if (rows[i].parentNode == body) {
rows[i].removeAttribute("selected");
if (rows[i] == startRow) {
doSelect = true;
}
if (doSelect) {
this.setSelectionByRow(rows[i]);
rows[i].setAttribute("selected", "true");
}
if (rows[i] == row) {
doSelect = false;
}
}
}
}
} else {
this.resetSelections(body);
row.setAttribute("selected", "true");
this.setSelectionByRow(row);
}
}
} else {
this.resetSelections(body);
row.setAttribute("selected", "true");
this.setSelectionByRow(row);
}
this.showSelections();
this.onSelect(e);
e.stopPropagation();
e.preventDefault();
}, onHeaderClick:function (e) {
var oldIndex = this.sortIndex;
var oldDirection = this.sortDirection;
var source = e.target;
var row = dojo.html.getParentByType(source, "tr");
var cellTag = "td";
if (row.getElementsByTagName(cellTag).length == 0) {
cellTag = "th";
}
var headers = row.getElementsByTagName(cellTag);
var header = dojo.html.getParentByType(source, cellTag);
for (var i = 0; i < headers.length; i++) {
if (headers[i] == header) {
if (i != oldIndex) {
this.sortIndex = i;
this.sortDirection = 0;
headers[i].className = this.headerSortDownClass;
} else {
this.sortDirection = (oldDirection == 0) ? 1 : 0;
if (this.sortDirection == 0) {
headers[i].className = this.headerSortDownClass;
} else {
headers[i].className = this.headerSortUpClass;
}
}
} else {
headers[i].className = this.headerClass;
}
}
this.render();
}, postCreate:function () {
var thead = this.domNode.getElementsByTagName("thead")[0];
if (this.headClass.length > 0) {
thead.className = this.headClass;
}
dojo.html.disableSelection(this.domNode);
this.parseColumns(thead);
var header = "td";
if (thead.getElementsByTagName(header).length == 0) {
header = "th";
}
var headers = thead.getElementsByTagName(header);
for (var i = 0; i < headers.length; i++) {
if (!this.columns[i].noSort) {
dojo.event.connect(headers[i], "onclick", this, "onHeaderClick");
}
if (this.sortIndex == i) {
if (this.sortDirection == 0) {
headers[i].className = this.headerSortDownClass;
} else {
headers[i].className = this.headerSortUpClass;
}
}
}
var tbody = this.domNode.getElementsByTagName("tbody")[0];
if (this.tbodyClass.length > 0) {
tbody.className = this.tbodyClass;
}
this.parseDataFromTable(tbody);
this.render(true);
}});