3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.3.1
11 * Copyright(c) 2006-2010 Sencha Inc.
12 * licensing@sencha.com
13 * http://www.sencha.com/license
15 <div id="cls-Ext.grid.PivotAxis"></div>/**
16 * @class Ext.grid.PivotAxis
17 * @extends Ext.Component
18 * <p>PivotAxis is a class that supports a {@link Ext.grid.PivotGrid}. Each PivotGrid contains two PivotAxis instances - the left
19 * axis and the top axis. Each PivotAxis defines an ordered set of dimensions, each of which should correspond to a field in a
20 * Store's Record (see {@link Ext.grid.PivotGrid} documentation for further explanation).</p>
21 * <p>Developers should have little interaction with the PivotAxis instances directly as most of their management is performed by
22 * the PivotGrid. An exception is the dynamic reconfiguration of axes at run time - to achieve this we use PivotAxis's
23 * {@link #setDimensions} function and refresh the grid:</p>
25 var pivotGrid = new Ext.grid.PivotGrid({
26 //some PivotGrid config here
29 //change the left axis dimensions
30 pivotGrid.leftAxis.setDimensions([
43 pivotGrid.view.refresh(true);
45 * This clears the previous dimensions on the axis and redraws the grid with the new dimensions.
47 Ext.grid.PivotAxis = Ext.extend(Ext.Component, {
48 <div id="cfg-Ext.grid.PivotAxis-orientation"></div>/**
49 * @cfg {String} orientation One of 'vertical' or 'horizontal'. Defaults to horizontal
51 orientation: 'horizontal',
53 <div id="cfg-Ext.grid.PivotAxis-defaultHeaderWidth"></div>/**
54 * @cfg {Number} defaultHeaderWidth The width to render each row header that does not have a width specified via
55 {@link #getRowGroupHeaders}. Defaults to 80.
57 defaultHeaderWidth: 80,
61 * @cfg {Number} paddingWidth The amount of padding used by each cell.
62 * TODO: From 4.x onwards this can be removed as it won't be needed. For now it is used to account for the differences between
63 * the content box and border box measurement models
67 <div id="method-Ext.grid.PivotAxis-setDimensions"></div>/**
68 * Updates the dimensions used by this axis
69 * @param {Array} dimensions The new dimensions
71 setDimensions: function(dimensions) {
72 this.dimensions = dimensions;
77 * Builds the html table that contains the dimensions for this axis. This branches internally between vertical
78 * and horizontal orientations because the table structure is slightly different in each case
80 onRender: function(ct, position) {
81 var rows = this.orientation == 'horizontal'
82 ? this.renderHorizontalRows()
83 : this.renderVerticalRows();
85 this.el = Ext.DomHelper.overwrite(ct.dom, {tag: 'table', cn: rows}, true);
90 * Specialised renderer for horizontal oriented axes
91 * @return {Object} The HTML Domspec for a horizontal oriented axis
93 renderHorizontalRows: function() {
94 var headers = this.buildHeaders(),
95 rowCount = headers.length,
97 cells, cols, colCount, i, j;
99 for (i = 0; i < rowCount; i++) {
101 cols = headers[i].items;
102 colCount = cols.length;
104 for (j = 0; j < colCount; j++) {
107 html: cols[j].header,
108 colspan: cols[j].span
123 * Specialised renderer for vertical oriented axes
124 * @return {Object} The HTML Domspec for a vertical oriented axis
126 renderVerticalRows: function() {
127 var headers = this.buildHeaders(),
128 colCount = headers.length,
131 rowCount, col, row, colWidth, i, j;
133 for (i = 0; i < colCount; i++) {
135 colWidth = col.width || 80;
136 rowCount = col.items.length;
138 for (j = 0; j < rowCount; j++) {
141 rowCells[row.start] = rowCells[row.start] || [];
142 rowCells[row.start].push({
146 width : Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
151 rowCount = rowCells.length;
152 for (i = 0; i < rowCount; i++) {
164 * Returns the set of all unique tuples based on the bound store and dimension definitions.
165 * Internally we construct a new, temporary store to make use of the multi-sort capabilities of Store. In
166 * 4.x this functionality should have been moved to MixedCollection so this step should not be needed.
167 * @return {Array} All unique tuples
169 getTuples: function() {
170 var newStore = new Ext.data.Store({});
172 newStore.data = this.store.data.clone();
173 newStore.fields = this.store.fields;
176 dimensions = this.dimensions,
177 length = dimensions.length,
180 for (i = 0; i < length; i++) {
182 field : dimensions[i].dataIndex,
183 direction: dimensions[i].direction || 'ASC'
187 newStore.sort(sorters);
189 var records = newStore.data.items,
192 recData, hash, info, data, key;
194 length = records.length;
196 for (i = 0; i < length; i++) {
197 info = this.getRecordInfo(records[i]);
202 hash += data[key] + '---';
205 if (hashes.indexOf(hash) == -1) {
219 getRecordInfo: function(record) {
220 var dimensions = this.dimensions,
221 length = dimensions.length,
223 dimension, dataIndex, i;
225 //get an object containing just the data we are interested in based on the configured dimensions
226 for (i = 0; i < length; i++) {
227 dimension = dimensions[i];
228 dataIndex = dimension.dataIndex;
230 data[dataIndex] = record.get(dataIndex);
233 //creates a specialised matcher function for a given tuple. The returned function will return
234 //true if the record passed to it matches the dataIndex values of each dimension in this axis
235 var createMatcherFunction = function(data) {
236 return function(record) {
237 for (var dataIndex in data) {
238 if (record.get(dataIndex) != data[dataIndex]) {
249 matcher: createMatcherFunction(data)
255 * Uses the calculated set of tuples to build an array of headers that can be rendered into a table using rowspan or
256 * colspan. Basically this takes the set of tuples and spans any cells that run into one another, so if we had dimensions
257 * of Person and Product and several tuples containing different Products for the same Person, those Products would be
259 * @return {Array} The headers
261 buildHeaders: function() {
262 var tuples = this.getTuples(),
263 rowCount = tuples.length,
264 dimensions = this.dimensions,
265 colCount = dimensions.length,
267 tuple, rows, currentHeader, previousHeader, span, start, isLast, changed, i, j;
269 for (i = 0; i < colCount; i++) {
270 dimension = dimensions[i];
275 for (j = 0; j < rowCount; j++) {
277 isLast = j == (rowCount - 1);
278 currentHeader = tuple.data[dimension.dataIndex];
281 * 'changed' indicates that we need to create a new cell. This should be true whenever the cell
282 * above (previousHeader) is different from this cell, or when the cell on the previous dimension
283 * changed (e.g. if the current dimension is Product and the previous was Person, we need to start
284 * a new cell if Product is the same but Person changed, so we check the previous dimension and tuple)
286 changed = previousHeader != undefined && previousHeader != currentHeader;
287 if (i > 0 && j > 0) {
288 changed = changed || tuple.data[dimensions[i-1].dataIndex] != tuples[j-1].data[dimensions[i-1].dataIndex];
293 header: previousHeader,
304 header: currentHeader,
313 previousHeader = currentHeader;
319 width: dimension.width || this.defaultHeaderWidth
322 previousHeader = undefined;