├── Ext.ux.TouchGridPanel.css
├── Ext.ux.TouchGridPanel.js
├── LICENSE
├── README
├── index.html
├── main.js
├── sort_asc.gif
└── sort_desc.gif
/Ext.ux.TouchGridPanel.css:
--------------------------------------------------------------------------------
1 | .x-grid-header {
2 | width: 100%;
3 |
4 | margin-right: 4px;
5 |
6 | background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #9aa7b2), color-stop(2%, #647482), color-stop(100%, #434d57));
7 | }
8 | .x-grid-row {
9 | border-top: 1px solid #000;
10 | border-bottom: 1px solid #000;
11 | }
12 | .x-grid-row:nth-child(even) {
13 | background-color: #ffffff;
14 | }
15 | .x-grid-row:nth-child(odd) {
16 | background-color: #f0f0f0;
17 | }
18 | .x-grid-hd-cell {
19 | text-align: center;
20 | color: #FFF;
21 | text-shadow: rgba(0, 0, 0, 0.5) 0 -0.08em 0;
22 | }
23 | .x-grid-hd-cell[sort$=ASC] {
24 | background: url('sort_asc.gif') no-repeat right center;
25 | }
26 | .x-grid-hd-cell[sort$=DESC] {
27 | background: url('sort_desc.gif') no-repeat right center;
28 | }
29 | .x-grid-cell {
30 | line-height:15px;
31 | vertical-align:middle;
32 | line-height: 2em;
33 | font-size: 1em;
34 | font-weight: bold;
35 | border-left: 1px solid #000;
36 | border-right: 1px solid #000;
37 | }
38 | .x-grid-cell-no-of {
39 | overflow:hidden;
40 | text-overflow: ellipsis;
41 | white-space: nowrap;
42 | }
43 | .x-grid-cell-del-btn {
44 | padding-top: 1px;
45 | padding-left: 0.5em;
46 | }
47 |
48 | .x-grid-col-hidden {
49 | display: none;
50 | }
51 |
52 | .x-item-selected {
53 | -webkit-transform: translate3d(0, 0, 0);
54 | background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #7fb6e7), color-stop(2%, #2986d6), color-stop(100%, #1d5e96));
55 | background-image: linear-gradient(top, #7fb6e7 0%, #2986d6 2%, #1d5e96 100%);
56 | color: #fff;
57 | border-color: #103656;
58 | text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
59 | }
60 |
--------------------------------------------------------------------------------
/Ext.ux.TouchGridPanel.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Because of limitation of the current WebKit implementation of CSS3 column layout,
3 | * I have decided to revert back to using table.
4 | */
5 |
6 | Ext.ns("Ext.ux");
7 |
8 | Ext.ux.TouchGridPanel = Ext.extend(Ext.Panel, {
9 | layout : "fit",
10 |
11 | multiSelect : false,
12 | scroll : "vertical",
13 |
14 | initComponent : function() {
15 | var me = this;
16 |
17 | me.items = me.dataview = me.buildDataView();
18 |
19 | if (!Ext.isArray(me.dockedItems)) {
20 | me.dockedItems = [];
21 | }
22 |
23 | me.header = new Ext.Component(me.buildHeader());
24 | me.dockedItems.push(me.header);
25 |
26 | Ext.ux.TouchGridPanel.superclass.initComponent.call(me);
27 |
28 | var store = me.store;
29 |
30 | store.on("update", me.dispatchDataChanged, me);
31 | },
32 |
33 | dispatchDataChanged: function(store, rec, operation) {
34 | var me = this;
35 |
36 | me.fireEvent("storeupdate", store, rec, operation);
37 | },
38 |
39 | buildHeader : function() {
40 | var me = this,
41 | colModel = me.colModel,
42 | colNum = me.getColNum(false),
43 | cellWidth = 100/colNum,
44 | colTpl = '
';
62 |
63 | return {
64 | dock : "top",
65 | html : colTpl,
66 | listeners : {
67 | scope : me,
68 | afterrender : me.initHeaderEvents
69 | }
70 | };
71 | },
72 |
73 | initHeaderEvents: function(cmp) {
74 | var me = this,
75 | el = cmp.getEl();
76 |
77 | el.on("click", me.handleHeaderClick, me);
78 | },
79 |
80 | handleHeaderClick: function(e, t) {
81 | e.stopEvent();
82 |
83 | var me = this,
84 | el = Ext.get(t),
85 | mapping = el.getAttribute("mapping");
86 |
87 | if (typeof mapping === "string") {
88 | me.store.sort(mapping);
89 | el.set({
90 | sort : me.store.sortToggle[mapping]
91 | });
92 | }
93 | },
94 |
95 | buildDataView : function() {
96 | var me = this,
97 | colModel = me.colModel,
98 | colNum = me.getColNum(false),
99 | colTpl = '',
100 | cellWidth = 100/colNum;
101 |
102 | for (var i = 0; i < colModel.length; i++) {
103 | var col = colModel[i],
104 | flex = col.flex || 1,
105 | width = flex * cellWidth,
106 | style = (i === colModel.length - 1) ? "padding-right: 10px;" : "",
107 | cls = col.cls || "";
108 |
109 | style += col.style || "";
110 |
111 | if (col.hidden) {
112 | cls += "x-grid-col-hidden";
113 | }
114 |
115 | colTpl += '{' + col.mapping + '} | ';
116 | }
117 | colTpl += '
';
118 |
119 | return new Ext.DataView({
120 | store : me.store,
121 | itemSelector : "tr.x-grid-row",
122 | simpleSelect : me.multiSelect,
123 | scroll : me.scroll,
124 | tpl : new Ext.XTemplate(
125 | '',
126 | '',
127 | colTpl,
128 | '',
129 | '
',
130 | {
131 | isRowDirty: function(dirty, data) {
132 | return dirty ? "x-grid-row-dirty" : "";
133 | },
134 | isCellDirty: function(dirty, data) {
135 | return dirty ? "x-grid-cell-dirty" : "";
136 | }
137 | }
138 | ),
139 | prepareData : function(data, index, record) {
140 | var column,
141 | i = 0,
142 | ln = colModel.length;
143 | var prepare_data = {};
144 | prepare_data.dirtyFields = {};
145 | for (; i < ln; i++) {
146 |
147 | column = colModel[i];
148 | if (typeof column.renderer === "function") {
149 | prepare_data[column.mapping] = column.renderer.apply(me, [data[column.mapping],column, record, index]);
150 | } else {
151 | prepare_data[column.mapping] = data[column.mapping];
152 | }
153 | }
154 |
155 | prepare_data.isDirty = record.dirty;
156 |
157 | prepare_data.rowIndex = index;
158 | return prepare_data;
159 | },
160 | bubbleEvents : [
161 | "beforeselect",
162 | "containertap",
163 | "itemdoubletap",
164 | "itemswipe",
165 | "itemtap",
166 | "selectionchange"
167 | ]
168 | });
169 | },
170 |
171 | // hidden = true to count all columns
172 | getColNum : function(hidden) {
173 | var me = this,
174 | colModel = me.colModel,
175 | colNum = 0;
176 |
177 | for (var i = 0; i < colModel.length; i++) {
178 | var col = colModel[i];
179 | if (!hidden && typeof col.header !== "string") { continue; }
180 | if (!col.hidden) {
181 | colNum += col.flex || 1;
182 | }
183 | }
184 |
185 | return colNum;
186 | },
187 |
188 | getMappings: function() {
189 | var me = this,
190 | mappings = {},
191 | colModel = me.colModel;
192 |
193 | for (var i = 0; i < colModel.length; i++) {
194 | mappings[colModel[i].mapping] = i
195 | }
196 |
197 | return mappings;
198 | },
199 |
200 | toggleColumn: function(index) {
201 | var me = this;
202 |
203 | if (typeof index === "string") {
204 | var mappings = me.getMappings();
205 | index = mappings[index];
206 | }
207 | var el = me.getEl(),
208 | mapping = me.colModel[index].mapping,
209 | cells = el.query("td.x-grid-col-"+mapping);
210 |
211 | for (var c = 0; c < cells.length; c++) {
212 | var cellEl = Ext.get(cells[c]);
213 | if (cellEl.hasCls("x-grid-col-hidden")) {
214 | cellEl.removeCls("x-grid-col-hidden");
215 | this.colModel[index].hidden = false;
216 | } else {
217 | cellEl.addCls("x-grid-col-hidden");
218 | this.colModel[index].hidden = true;
219 | }
220 | }
221 |
222 | me.updateWidths();
223 | },
224 |
225 | updateWidths: function() {
226 | var me = this,
227 | el = me.getEl(),
228 | headerWidth = me.header.getEl().getWidth(),
229 | colModel = me.colModel,
230 | cells = el.query("td.x-grid-cell"),
231 | colNum = me.getColNum(false),
232 | cellWidth = 100 / colNum,
233 | mappings = me.getMappings();
234 |
235 | for (var c = 0; c < cells.length; c++) {
236 | var cellEl = Ext.get(cells[c]),
237 | mapping = cellEl.getAttribute("mapping"),
238 | col = colModel[mappings[mapping]],
239 | flex = col.flex || 1,
240 | width = flex * cellWidth / 100 * headerWidth;
241 |
242 | cellEl.setWidth(width);
243 | }
244 | },
245 |
246 | scrollToRow: function(index) {
247 | var me = this,
248 | el = me.getEl(),
249 | rows = el.query("tr.x-grid-row"),
250 | rowEl = Ext.get(rows[index]),
251 | scroller = me.dataview.scroller;
252 |
253 | var pos = {
254 | x: 0,
255 | y: rowEl.dom.offsetTop
256 | };
257 |
258 | scroller.scrollTo(pos, true);
259 | },
260 |
261 | getView: function() {
262 | var me = this;
263 |
264 | return me.dataview;
265 | },
266 |
267 | bindStore: function(store) {
268 | var me = this,
269 | view = me.getView();
270 |
271 | view.bindStore(store);
272 | },
273 |
274 | getStore: function() {
275 | var me = this,
276 | view = me.getView();
277 |
278 | return view.getStore();
279 | },
280 |
281 | getRow: function(index) {
282 | var me = this;
283 | if (typeof index === "object") {
284 | var store = me.getStore(),
285 | index = store.indexOf(index);
286 | }
287 |
288 | var el = me.getEl(),
289 | rows = el.query("tr");
290 |
291 | return rows[index+1];
292 | }
293 | });
294 |
295 | Ext.reg("touchgridpanel", Ext.ux.TouchGridPanel);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | /*
2 | Author : Mitchell Simoens
3 | Site : http://simoens.org/Sencha-Projects/demos/
4 | Contact Info : mitchellsimoens@gmail.com
5 | Purpose : Creation of a grid for Sencha Touch
6 |
7 | License : MIT (http://www.opensource.org/licenses/mit-license.php)
8 | Warranty : none
9 | Price : free
10 | Version : 2.0b2
11 | Date : 3/22/2011
12 | */
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchellsimoens/Ext.ux.TouchGridPanel/be986e5384157d833ce94f6ce6e1bed731f5b20d/README
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 | Sencha Touch GridPanel
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | Ext.setup({
2 | tabletStartupScreen : "/images/tablet_startup.png",
3 | phoneStartupScreen : "phone_startup.png",
4 | icon : "icon.png",
5 | glossOnIcon : true,
6 | onReady : function() {
7 | var deleteConfirm;
8 | Ext.regModel("TestModel", {
9 | fields : [
10 | "company",
11 | "price",
12 | "change",
13 | "pct",
14 | "updated"
15 | ]
16 | });
17 | var store = new Ext.data.Store({
18 | model : "TestModel",
19 | data : [
20 | { company : "3m Co", price : 71.72, change : 0.02, pct : 0.03, updated : "9/1/2010" },
21 | { company : "Alcoa Inc", price : 29.01, change : 0.42, pct : 1.47, updated : "9/1/2010" },
22 | { company : "Altria Group Inc", price : 83.81, change : 0.28, pct : 0.34, updated : "9/1/2010" },
23 | { company : "American Express Company", price : 52.55, change : 0.01, pct : 0.02, updated : "9/1/2010" },
24 | { company : "American International Group, Inc.", price : 64.13, change : 0.31, pct : 0.49, updated : "9/1/2010" },
25 | { company : "AT&T Inc.", price : 31.61, change : -0.48, pct : -1.54, updated : "9/1/2010" },
26 | { company : "Boeing Co.", price : 75.43, change : 0.53, pct : 0.71, updated : "9/1/2010" },
27 | { company : "Caterpillar Inc.", price : 67.27, change : 0.92, pct : 1.39, updated : "9/1/2010" },
28 | { company : "Citigroup, Inc.", price : 49.37, change : 0.02, pct : 0.04, updated : "9/1/2010" },
29 | { company : "E.I. du Pont de Nemours and Company", price : 40.48, change : 0.51, pct : 1.28, updated : "9/1/2010" },
30 | { company : "Exxon Mobil Corp", price : 68.1, change : -0.43, pct : -0.64, updated : "9/1/2010" },
31 | { company : "General Electric Company", price : 34.14, change : -0.08, pct : -0.23, updated : "9/1/2010" },
32 | { company : "General Motors Corporation", price : 30.27, change : 1.09, pct : 3.74, updated : "9/1/2010" },
33 | { company : "Hewlett-Packard Co.", price : 36.53, change : -0.03, pct : -0.08, updated : "9/1/2010" },
34 | { company : "Honeywell Intl Inc", price : 38.77, change : 0.05, pct : 0.13, updated : "9/1/2010" },
35 | { company : "Intel Corporation", price : 19.88, change : 0.31, pct : 1.58, updated : "9/1/2010" },
36 | { company : "International Business Machines", price : 81.41, change : 0.44, pct : 0.54, updated : "9/1/2010" },
37 | { company : "Johnson & Johnson", price : 64.72, change : 0.06, pct : 0.09, updated : "9/1/2010" },
38 | { company : "JP Morgan & Chase & Co", price : 45.73, change : 0.07, pct : 0.15, updated : "9/1/2010" },
39 | { company : "McDonald's Corporation", price : 36.76, change : 0.86, pct : 2.40, updated : "9/1/2010" },
40 | { company : "Merck & Co., Inc.", price : 40.96, change : 0.41, pct : 1.01, updated : "9/1/2010" },
41 | { company : "Microsoft Corporation", price : 25.84, change : 0.14, pct : 0.54, updated : "9/1/2010" },
42 | { company : "Pfizer Inc", price : 27.96, change : 0.4, pct : 1.45, updated : "9/1/2010" },
43 | { company : "The Coca-Cola Company", price : 45.07, change : 0.26, pct : 0.58, updated : "9/1/2010" },
44 | { company : "The Home Depot, Inc.", price : 34.64, change : 0.35, pct : 1.02, updated : "9/1/2010" },
45 | { company : "The Procter & Gamble Company", price : 61.91, change : 0.01, pct : 0.02, updated : "9/1/2010" },
46 | { company : "United Technologies Corporation", price : 63.26, change : 0.55, pct : 0.88, updated : "9/1/2010" },
47 | { company : "Verizon Communications", price : 35.57, change : 0.39, pct : 1.11, updated : "9/1/2010" },
48 | { company : "Wal-Mart Stores, Inc.", price : 45.45, change : 0.73, pct : 1.63, updated : "9/1/2010" }
49 | ]
50 | });
51 |
52 | var grid = new Ext.ux.TouchGridPanel({
53 | fullscreen : true,
54 | store : store,
55 | multiSelect : false,
56 | dockedItems : [{
57 | xtype : "toolbar",
58 | dock : "top",
59 | title : "Ext.ux.TouchGridPanel by Mitchell Simoens"
60 | }],
61 | colModel : [{
62 | header : "Company",
63 | mapping : "company",
64 | flex : 2
65 | },{
66 | header : "Price",
67 | mapping : "price",
68 | style : "text-align: center;"
69 | },{
70 | header : "Change",
71 | mapping : "change",
72 | cls : "centered-cell",
73 | renderer : function(val) {
74 | var color = (val > 0) ? "00FF00" : "FF0000";
75 | return "" + val + "";
76 | }
77 | /*},{
78 | header : "% Change",
79 | mapping : "pct",
80 | cls : "centered-cell"*/
81 | },{
82 | header : "Last Updated",
83 | mapping : "updated",
84 | hidden : true,
85 | style : "text-align: right;"
86 | }],
87 | listeners: {
88 | beforeselect: function(dataview, nodes, selections) {
89 | console.log(selections);
90 | },
91 | containertap: function(dataview, e) {
92 | console.log(dataview);
93 | },
94 | itemdoubletap: function(dataview, index, el, e) {
95 | console.log(index);
96 | },
97 | itemswipe: function(dataview, index, el, e) {
98 | console.log(index);
99 | },
100 | itemtap: function(dataview, index, el, e) {
101 | console.log(index);
102 | },
103 | selectionchange: function(selectionModel, selections) {
104 | console.log(selections);
105 | }
106 | }
107 | });
108 | }
109 | });
--------------------------------------------------------------------------------
/sort_asc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchellsimoens/Ext.ux.TouchGridPanel/be986e5384157d833ce94f6ce6e1bed731f5b20d/sort_asc.gif
--------------------------------------------------------------------------------
/sort_desc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchellsimoens/Ext.ux.TouchGridPanel/be986e5384157d833ce94f6ce6e1bed731f5b20d/sort_desc.gif
--------------------------------------------------------------------------------