2 * Copyright 2010-2013 Ben Birch
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this software except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 ( function( $, app ) {
18 var ui = app.ns("ui");
20 ui.Table = ui.AbstractWidget.extend({
22 store: null, // (required) implements interface app.data.DataSourceInterface
27 init: function(parent) {
29 this.initElements(parent);
30 this.config.store.on("data", this._data_handler);
32 attach: function(parent) {
38 initElements: function(parent) {
39 this.el = $.joey(this._main_template());
40 this.body = this.el.find(".uiTable-body");
41 this.headers = this.el.find(".uiTable-headers");
42 this.tools = this.el.find(".uiTable-tools");
43 this.attach( parent );
45 _data_handler: function(store) {
46 this.tools.text(store.summary);
47 this.headers.empty().append(this._header_template(store.columns));
48 this.body.empty().append(this._body_template(store.data, store.columns));
52 var firstCol = this.body.find("TR:first TH.uiTable-header-cell > DIV"),
53 headers = this.headers.find("TR:first TH.uiTable-header-cell > DIV");
54 for(var i = 0; i < headers.length; i++) {
55 $(headers[i]).width( $(firstCol[i]).width() );
57 this._scroll_handler();
59 _scroll_handler: function(ev) {
60 this.el.find(".uiTable-headers").scrollLeft(this.body.scrollLeft());
62 _dataClick_handler: function(ev) {
63 var row = $(ev.target).closest("TR");
65 this.fire("rowClick", this, { row: row } );
68 _headerClick_handler: function(ev) {
69 var header = $(ev.target).closest("TH.uiTable-header-cell");
71 this.fire("headerClick", this, { header: header, column: header.data("column"), dir: header.data("dir") });
74 _main_template: function() {
75 return { tag: "DIV", id: this.id(), css: { width: this.config.width + "px" }, cls: this._baseCls, children: [
76 { tag: "DIV", cls: "uiTable-tools" },
77 { tag: "DIV", cls: "uiTable-headers", onclick: this._headerClick_handler },
78 { tag: "DIV", cls: "uiTable-body",
79 onclick: this._dataClick_handler,
80 onscroll: this._scroll_handler,
81 css: { height: this.config.height + "px", width: this.config.width + "px" }
85 _header_template: function(columns) {
86 var ret = { tag: "TABLE", children: [ this._headerRow_template(columns) ] };
87 ret.children[0].children.push(this._headerEndCap_template());
90 _headerRow_template: function(columns) {
91 return { tag: "TR", cls: "uiTable-header-row", children: columns.map(function(column) {
92 var dir = ((this.config.store.sort.column === column) && this.config.store.sort.dir) || "none";
93 return { tag: "TH", data: { column: column, dir: dir }, cls: "uiTable-header-cell" + ((dir !== "none") ? " uiTable-sort" : ""), children: [
94 { tag: "DIV", children: [
95 { tag: "DIV", cls: "uiTable-headercell-menu", text: dir === "asc" ? "\u25b2" : "\u25bc" },
96 { tag: "DIV", cls: "uiTable-headercell-text", text: column }
101 _headerEndCap_template: function() {
102 return { tag: "TH", cls: "uiTable-headerEndCap", children: [ { tag: "DIV" } ] };
104 _body_template: function(data, columns) {
105 return { tag: "TABLE", children: []
106 .concat(this._headerRow_template(columns))
107 .concat(data.map(function(row) {
108 return { tag: "TR", data: { row: row }, cls: "uiTable-row", children: columns.map(function(column){
109 return { tag: "TD", cls: "uiTable-cell", children: [ { tag: "DIV", text: (row[column] || "").toString() } ] };
117 })( this.jQuery, this.app );