5 ui.Table = ui.AbstractWidget.extend({
7 store: null, // (required) implements interface app.data.DataSourceInterface
12 init: function(parent) {
14 this.initElements(parent);
15 this.config.store.on("data", this._data_handler);
17 attach: function(parent) {
23 initElements: function(parent) {
24 this.el = $.joey(this._main_template());
25 this.body = this.el.find(".uiTable-body");
26 this.headers = this.el.find(".uiTable-headers");
27 this.tools = this.el.find(".uiTable-tools");
28 this.attach( parent );
30 _data_handler: function(store) {
31 this.tools.text(store.summary);
32 this.headers.empty().append(this._header_template(store.columns));
33 this.body.empty().append(this._body_template(store.data, store.columns));
37 var firstCol = this.body.find("TR:first TH.uiTable-header-cell > DIV"),
38 headers = this.headers.find("TR:first TH.uiTable-header-cell > DIV");
39 for(var i = 0; i < headers.length; i++) {
40 $(headers[i]).width( $(firstCol[i]).width() );
42 this._scroll_handler();
44 _scroll_handler: function(ev) {
45 this.el.find(".uiTable-headers").scrollLeft(this.body.scrollLeft());
47 _dataClick_handler: function(ev) {
48 var row = $(ev.target).closest("TR");
50 this.fire("rowClick", this, { row: row } );
53 _headerClick_handler: function(ev) {
54 var header = $(ev.target).closest("TH.uiTable-header-cell");
56 this.fire("headerClick", this, { header: header, column: header.data("column"), dir: header.data("dir") });
59 _main_template: function() {
60 return { tag: "DIV", id: this.id(), css: { width: this.config.width + "px" }, cls: this._baseCls, children: [
61 { tag: "DIV", cls: "uiTable-tools" },
62 { tag: "DIV", cls: "uiTable-headers", onclick: this._headerClick_handler },
63 { tag: "DIV", cls: "uiTable-body",
64 onclick: this._dataClick_handler,
65 onscroll: this._scroll_handler,
66 css: { height: this.config.height + "px", width: this.config.width + "px" }
70 _header_template: function(columns) {
71 var ret = { tag: "TABLE", children: [ this._headerRow_template(columns) ] };
72 ret.children[0].children.push(this._headerEndCap_template());
75 _headerRow_template: function(columns) {
76 return { tag: "TR", cls: "uiTable-header-row", children: columns.map(function(column) {
77 var dir = ((this.config.store.sort.column === column) && this.config.store.sort.dir) || "none";
78 return { tag: "TH", data: { column: column, dir: dir }, cls: "uiTable-header-cell" + ((dir !== "none") ? " uiTable-sort" : ""), children: [
79 { tag: "DIV", children: [
80 { tag: "DIV", cls: "uiTable-headercell-menu", text: dir === "asc" ? "\u25b2" : "\u25bc" },
81 { tag: "DIV", cls: "uiTable-headercell-text", text: column }
86 _headerEndCap_template: function() {
87 return { tag: "TH", cls: "uiTable-headerEndCap", children: [ { tag: "DIV" } ] };
89 _body_template: function(data, columns) {
90 return { tag: "TABLE", children: []
91 .concat(this._headerRow_template(columns))
92 .concat(data.map(function(row) {
93 return { tag: "TR", data: { row: row }, cls: "uiTable-row", children: columns.map(function(column){
94 return { tag: "TD", cls: "uiTable-cell", children: [ { tag: "DIV", text: (row[column] || "").toString() } ] };
102 })( this.jQuery, this.app );