Skip to content

Commit d03ba59

Browse files
drilldown, resize fixes, other improvements
1 parent 1c8bc67 commit d03ba59

7 files changed

Lines changed: 518 additions & 79 deletions

File tree

example/index.html

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,31 @@
1111
<script type="text/javascript" src="../source/js/DataSource.js"></script>
1212
<script type="text/javascript" src="../source/js/PivotView.js"></script>
1313
<script type="text/javascript" src="../source/js/DataController.js"></script>
14+
<script type="text/javascript" src="../source/js/MDXParser.js"></script>
1415
<!-- endbuild -->
16+
<style>
17+
a {
18+
text-decoration: underline;
19+
color: blue;
20+
cursor: pointer;
21+
}
22+
</style>
1523
</head>
1624
<body>
17-
<div id="pivot" style="position: fixed; left: 20%; top: 20%; width: 60%; height: 60%;">
25+
<div id="pivot" style="position: fixed; left: 20%; top: 30%; width: 60%; height: 60%;">
1826

1927
</div>
2028
<div>Variants:
21-
<a href="#0" onclick="rSoon()">0</a>,
22-
<a href="#1" onclick="rSoon()">1</a>,
23-
<a href="#2" onclick="rSoon()">2</a>,
24-
<a href="#3" onclick="rSoon()">3</a>,
25-
<a href="#4" onclick="rSoon()">4</a>,
26-
<a href="#5" onclick="rSoon()">5</a>,
27-
<a href="#6" onclick="rSoon()">6</a>,
28-
<a href="#7" onclick="rSoon()">7</a>,
29-
<a href="#8" onclick="rSoon()">8</a>
29+
<a onclick="rSoon(this)">0</a>,
30+
<a onclick="rSoon(this)">1</a>,
31+
<a onclick="rSoon(this)">2</a>,
32+
<a onclick="rSoon(this)">3</a>,
33+
<a onclick="rSoon(this)">4</a>,
34+
<a onclick="rSoon(this)">5</a>,
35+
<a onclick="rSoon(this)">6</a>,
36+
<a onclick="rSoon(this)">7</a>,
37+
<a onclick="rSoon(this)">8</a>,
38+
<a onclick="rSoon(this)">9</a>
3039
</div>
3140
<div id="mdx"></div>
3241
<form id="mdxForm" onsubmit="return false;">
@@ -38,7 +47,10 @@
3847
<script type="text/javascript">
3948

4049
// reloads the page.
41-
var rSoon = function () { setTimeout(function () { window.location.reload(true); }, 1); };
50+
var rSoon = function (o) {
51+
location.hash = "#" + o.textContent;
52+
setTimeout(function () { window.location.reload(true); }, 1);
53+
};
4254

4355
var mdxTo = document.getElementById("mdx"),
4456
v = parseInt(location.hash.slice(1)) || 0,
@@ -51,7 +63,8 @@
5163
"SELECT {[Measures].[%COUNT]} ON 0 FROM [HoleFoods] %FILTER [Measures].[%COUNT]",
5264
"SELECT NON EMPTY [Product].[P1].[Product Category].Members ON 0,{[Measures].[%COUNT]} ON 1 FROM [HoleFoods] %FILTER [Measures].[%COUNT]",
5365
"SELECT NON EMPTY [Product].[P1].[Product Category].Members ON 0, NON EMPTY [Outlet].[H1].[Region].Members ON 1 FROM [HoleFoods]",
54-
"SELECT NON EMPTY [Product].[P1].[Product Category].Members ON 0,NON EMPTY [DateOfSale].[Actual].[YearSold].&[2010].children ON 1 FROM [HoleFoods] %FILTER [DateOfSale].[Actual].[YearSold].&[2010] %FILTER [Measures].[%COUNT]"
66+
"SELECT NON EMPTY [Product].[P1].[Product Category].Members ON 0,NON EMPTY [DateOfSale].[Actual].[YearSold].&[2010].children ON 1 FROM [HoleFoods] %FILTER [DateOfSale].[Actual].[YearSold].&[2010] %FILTER [Measures].[%COUNT]",
67+
"SELECT NON EMPTY [Product].[P1].[Product Category].Members ON 0,NON EMPTY [DateOfSale].[Actual].[YearSold].Members ON 1 FROM [HoleFoods]"
5568
][v];
5669

5770
if (location.hash.slice(1, 3) === "q=") {
@@ -68,7 +81,7 @@
6881

6982
});
7083

71-
mdxTo.innerHTML = "<b>MDX:</b> <i>" + req + "</i>";
84+
mdxTo.innerHTML = "<b>Basic MDX:</b> <i>" + req + "</i>";
7285

7386
var lp = new LightPivotTable({
7487
container: document.getElementById("pivot"), // HTMLElement which will contain table.

source/css/LightPivot.css

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,71 @@
44
height: 100%;
55
box-shadow: 0 0 30px rgb(136, 160, 255);
66
border-radius: 5px;
7+
overflow: hidden;
8+
}
9+
10+
.lpt .central {
11+
position: absolute;
12+
left: 0;
13+
top: 0;
14+
width: 100%;
15+
height: 100%;
16+
display: table;
17+
}
18+
19+
.lpt .backButton {
20+
padding-left: 1.25em !important;
21+
}
22+
23+
.lpt .backButton:before, .lpt .backButton:after {
24+
background: #333;
25+
border-radius: 0.25em;
26+
content: "";
27+
display: block;
28+
height: 0.25em;
29+
position: absolute;
30+
left: .5em;
31+
top: 50%;
32+
width: .8em;
33+
transition: background .4s ease;
34+
}
35+
36+
.lpt .backButton:before{
37+
-moz-transform: rotate(45deg);
38+
-ms-transform: rotate(45deg);
39+
-o-transform: rotate(45deg);
40+
-webkit-transform: rotate(45deg);
41+
transform: rotate(45deg)
42+
}
43+
44+
.lpt .backButton:after{
45+
-moz-transform: rotate(-45deg);
46+
-ms-transform: rotate(-45deg);
47+
-o-transform: rotate(-45deg);
48+
-webkit-transform: rotate(-45deg);
49+
transform: rotate(-45deg)
50+
}
51+
52+
.lpt .backButton:after {
53+
margin-top: -.36em;
54+
}
55+
56+
.lpt .backButton:hover:before,.lpt .backButton:hover:after {
57+
background: #C768FF;
58+
}
59+
60+
.lpt .backButton:hover {
61+
background: #e2c8ff;
62+
}
63+
64+
.lpt .central > div {
65+
display: table-cell;
66+
vertical-align: middle;
67+
text-align: center;
68+
}
69+
70+
.lpt .central > div > div {
71+
display: inline-block;
772
}
873

974
.lpt table {
@@ -19,9 +84,14 @@
1984
}
2085

2186
.lpt > .tableContainer {
87+
position: absolute;
2288
overflow: auto;
2389
width: 100%;
2490
height: 100%;
91+
-webkit-transition: left .5s ease;
92+
-moz-transition: left .5s ease;
93+
-o-transition: left .5s ease;
94+
transition: left .5s ease;
2595
}
2696

2797
.lpt > .tableContainer > table {
@@ -33,6 +103,11 @@
33103
.lpt > .tableContainer td, .lpt > .tableContainer th {
34104
border-radius: 3px;
35105
padding: .5em;
106+
text-align: center;
107+
}
108+
109+
.lpt > .tableContainer tbody.fixedHeader th:last-child:hover {
110+
background: #e2c8ff;
36111
}
37112

38113
.lpt th {
@@ -42,6 +117,9 @@
42117
.lpt thead tr:last-child th {
43118
cursor: pointer;
44119
-webkit-transition: all .3s ease;
120+
-moz-transition: all .3s ease;
121+
-o-transition: all .3s ease;
122+
transition: all .3s ease;
45123
}
46124

47125
.lpt thead tr:last-child th:first-child ~ th:hover {

source/js/DataController.js

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,90 @@ var DataController = function (dataSource, dataChangeTrigger) {
44
throw new Error("dataChangeTrigger parameter must be a function");
55
}
66

7-
this.data = null;
8-
this.SORT_STATE = {
9-
column: null,
10-
order: -1
11-
};
7+
this._dataStack = [];
8+
9+
this.pushData();
1210
this.dataChangeTrigger = dataChangeTrigger;
1311

1412
};
1513

14+
/**
15+
* Performs check if data is valid.
16+
*
17+
* @param {{ dimensions: Object[], dataArray: Array, info: Object }} data
18+
* @returns boolean
19+
*/
20+
DataController.prototype.isValidData = function (data) {
21+
22+
return data.dimensions instanceof Array
23+
&& data.dimensions[0] instanceof Array
24+
&& data.dimensions[0].length > 0
25+
&& data.dimensions[1].length > 0
26+
&& data.dimensions[0][0].hasOwnProperty("caption")
27+
&& data.dimensions[1][0].hasOwnProperty("caption")
28+
&& data.dataArray instanceof Array
29+
&& typeof data["info"] === "object"
30+
&& data["info"]["cubeName"];
31+
32+
};
33+
34+
DataController.prototype.pushData = function () {
35+
36+
var d;
37+
38+
this._dataStack.push(d = {
39+
data: null,
40+
SORT_STATE: {
41+
column: null,
42+
order: -1
43+
}
44+
});
45+
46+
//this.data = d.data;
47+
this.SORT_STATE = d.SORT_STATE;
48+
49+
};
50+
51+
DataController.prototype.popData = function () {
52+
53+
if (this._dataStack.length < 2) return;
54+
55+
var d = this._dataStack[this._dataStack.length - 2];
56+
57+
this._dataStack.pop();
58+
59+
//this.data = d.data;
60+
this.SORT_STATE = d.SORT_STATE;
61+
62+
};
63+
1664
DataController.prototype.getData = function () {
1765

18-
return this.data;
66+
return this._dataStack[this._dataStack.length - 1].data;
1967

2068
};
2169

2270
DataController.prototype.setData = function (data) {
2371

24-
this.data = data;
72+
if (!this.isValidData(data)) {
73+
console.error("Invalid data to set.", data);
74+
return;
75+
}
76+
77+
this._dataStack[this._dataStack.length - 1].data = data;
78+
//this.data = data;
2579
this.resetRawData();
2680

2781
this._trigger();
28-
return this.data;
82+
return data;
2983

3084
};
3185

3286
DataController.prototype.resetRawData = function () {
3387

34-
if (!this.data) {
88+
var data;
89+
90+
if (!(data = this._dataStack[this._dataStack.length - 1].data)) {
3591
console.error("Unable to create raw data for given data set.");
3692
return;
3793
}
@@ -84,14 +140,15 @@ DataController.prototype.resetRawData = function () {
84140

85141
};
86142

87-
dim0raw(rd0, this.data.dimensions[0]);
88-
dim1raw(rd1, this.data.dimensions[1]);
143+
dim0raw(rd0, data.dimensions[0]);
144+
dim1raw(rd1, data.dimensions[1]);
89145

90146
var xw = rd0[0].length,
91147
yh = rd1.length,
92148
xh = rd0.length,
93149
yw = rd1[0].length;
94150

151+
// render columns, rows and data
95152
for (var y = 0; y < xh + yh; y++) {
96153
if (!rawData[y]) rawData[y] = [];
97154
for (var x = 0; x < yw + xw; x++) {
@@ -100,7 +157,7 @@ DataController.prototype.resetRawData = function () {
100157
rawData[y][x] = {
101158
group: 1,
102159
isCaption: true,
103-
value: (this.data["info"] || {})["cubeName"] || ""
160+
value: (data["info"] || {})["cubeName"] || ""
104161
};
105162
} else {
106163
rawData[y][x] = rd1[y-xh][x];
@@ -110,18 +167,18 @@ DataController.prototype.resetRawData = function () {
110167
rawData[y][x] = rd0[y][x-yw];
111168
} else {
112169
rawData[y][x] = {
113-
value: this.data.dataArray[(xw)*(y - xh) + x - yw] || ""
170+
value: data.dataArray[(xw)*(y - xh) + x - yw] || ""
114171
};
115172
}
116173
}
117174
}
118175
}
119176

120-
this.data.info.topHeaderRowsNumber = xh;
121-
this.data.info.leftHeaderColumnsNumber = yw;
122-
this.data.rawData = this.data._rawDataOrigin = rawData;
177+
data.info.topHeaderRowsNumber = xh;
178+
data.info.leftHeaderColumnsNumber = yw;
179+
data.rawData = data._rawDataOrigin = rawData;
123180

124-
return this.data.rawData;
181+
return data.rawData;
125182

126183
};
127184

@@ -143,19 +200,21 @@ DataController.prototype._trigger = function () {
143200
*/
144201
DataController.prototype.sortByColumn = function (columnIndex) {
145202

203+
var data = this._dataStack[this._dataStack.length - 1].data;
204+
146205
if (this.SORT_STATE.column !== columnIndex) {
147206
order = this.SORT_STATE.order = 0;
148207
}
149208

150-
var newRawData = this.data._rawDataOrigin.slice(this.data.info.topHeaderRowsNumber),
151-
xIndex = this.data.info.leftHeaderColumnsNumber + columnIndex,
209+
var newRawData = data._rawDataOrigin.slice(data.info.topHeaderRowsNumber),
210+
xIndex = data.info.leftHeaderColumnsNumber + columnIndex,
152211
order = this.SORT_STATE.order === -1 ? 1 : this.SORT_STATE.order === 1 ? 0 : -1;
153212

154213
this.SORT_STATE.order = order;
155214
this.SORT_STATE.column = columnIndex;
156215

157216
if (order === 0) {
158-
this.data.rawData = this.data._rawDataOrigin;
217+
data.rawData = data._rawDataOrigin;
159218
this._trigger();
160219
return;
161220
}
@@ -166,7 +225,7 @@ DataController.prototype.sortByColumn = function (columnIndex) {
166225
return order*b[xIndex].value - order*a[xIndex].value;
167226
});
168227

169-
this.data.rawData = this.data._rawDataOrigin.slice(0, this.data.info.topHeaderRowsNumber)
228+
data.rawData = data._rawDataOrigin.slice(0, data.info.topHeaderRowsNumber)
170229
.concat(newRawData);
171230

172231
this._trigger();

0 commit comments

Comments
 (0)