Skip to content

Commit 49b51f7

Browse files
drillthrough, strings sort & little fixes
1 parent d03ba59 commit 49b51f7

File tree

6 files changed

+216
-40
lines changed

6 files changed

+216
-40
lines changed

source/css/LightPivot.css

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
}
1818

1919
.lpt .backButton {
20-
padding-left: 1.25em !important;
20+
width: 14px;
21+
height: 14px;
22+
top: 1px;
23+
padding: 2px;
24+
vertical-align: middle;
25+
display: inline-block;
26+
position: relative;
2127
}
2228

2329
.lpt .backButton:before, .lpt .backButton:after {
@@ -27,7 +33,7 @@
2733
display: block;
2834
height: 0.25em;
2935
position: absolute;
30-
left: .5em;
36+
left: 0;
3137
top: 50%;
3238
width: .8em;
3339
transition: background .4s ease;
@@ -57,8 +63,53 @@
5763
background: #C768FF;
5864
}
5965

60-
.lpt .backButton:hover {
66+
.lpt table tr:first-child th:first-child {
67+
position: relative;
68+
white-space: nowrap;
69+
}
70+
71+
.lpt .drillDownIcon {
72+
position: relative;
73+
display: inline-block;
74+
vertical-align: middle;
75+
width: 15px;
76+
height: 14px;
77+
border: 2px solid #000000;
78+
border-radius: 4px;
79+
margin-right: .3em;
80+
transition: all .4s ease;
81+
}
82+
83+
.lpt .drillDownIcon:hover {
6184
background: #e2c8ff;
85+
border-color: #C768FF;
86+
}
87+
88+
.lpt .drillDownIcon:after {
89+
content: "";
90+
width: 10px;
91+
height: 2px;
92+
background-color: #000000;
93+
border-radius: 4px;
94+
position: absolute;
95+
top: 2px;
96+
left: 2px;
97+
box-shadow: 0 8px 0 #000000;
98+
}
99+
100+
.lpt .drillDownIcon:before {
101+
content: "";
102+
width: 8px;
103+
height: 2px;
104+
background-color: #000000;
105+
border-radius: 4px;
106+
position: absolute;
107+
top: 6px;
108+
left: 2px;
109+
}
110+
111+
.lpt .drillDownIcon:hover:before {
112+
background-color: #C768FF;
62113
}
63114

64115
.lpt .central > div {

source/js/DataController.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ DataController.prototype.isValidData = function (data) {
2222
return data.dimensions instanceof Array
2323
&& data.dimensions[0] instanceof Array
2424
&& data.dimensions[0].length > 0
25-
&& data.dimensions[1].length > 0
25+
//&& data.dimensions[1].length > 0
2626
&& data.dimensions[0][0].hasOwnProperty("caption")
27-
&& data.dimensions[1][0].hasOwnProperty("caption")
27+
//&& data.dimensions[1][0].hasOwnProperty("caption")
2828
&& data.dataArray instanceof Array
2929
&& typeof data["info"] === "object"
3030
&& data["info"]["cubeName"];
@@ -140,13 +140,13 @@ DataController.prototype.resetRawData = function () {
140140

141141
};
142142

143-
dim0raw(rd0, data.dimensions[0]);
144-
dim1raw(rd1, data.dimensions[1]);
143+
if (data.dimensions[0].length) dim0raw(rd0, data.dimensions[0]);
144+
if (data.dimensions[1].length) dim1raw(rd1, data.dimensions[1]);
145145

146-
var xw = rd0[0].length,
147-
yh = rd1.length,
148-
xh = rd0.length,
149-
yw = rd1[0].length;
146+
var xw = (rd0[0] || []).length,
147+
yh = rd1.length || data.info.rowCount || 0,
148+
xh = rd0.length || data.info.colCount || 0,
149+
yw = (rd1[0] || []).length;
150150

151151
// render columns, rows and data
152152
for (var y = 0; y < xh + yh; y++) {
@@ -222,7 +222,9 @@ DataController.prototype.sortByColumn = function (columnIndex) {
222222
order = -order;
223223

224224
newRawData.sort(function (a, b) {
225-
return order*b[xIndex].value - order*a[xIndex].value;
225+
if (b[xIndex].value > a[xIndex].value) return order;
226+
if (b[xIndex].value < a[xIndex].value) return -order;
227+
return 0;
226228
});
227229

228230
data.rawData = data._rawDataOrigin.slice(0, data.info.topHeaderRowsNumber)

source/js/DataSource.js

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ var DataSource = function (config) {
1313

1414
this.BASIC_MDX = config.basicMDX;
1515

16+
this.ACTION = config.action || "MDX";
17+
1618
};
1719

1820
/**
@@ -29,7 +31,7 @@ DataSource.prototype._post = function (url, data, callback) {
2931
if (xhr.readyState === 4 && xhr.status === 200) {
3032
callback((function () {
3133
try {
32-
return JSON.parse(xhr.responseText)
34+
return JSON.parse(xhr.responseText) || {}
3335
} catch (e) {
3436
return {
3537
error: "<h1>Unable to parse server response</h1><p>" + xhr.responseText
@@ -81,12 +83,57 @@ DataSource.prototype._convert = function (data) {
8183
*/
8284
DataSource.prototype.getCurrentData = function (callback) {
8385

84-
var _ = this;
86+
var _ = this,
87+
__ = this._convert;
8588

86-
this._post(this.SOURCE_URL + "/MDX", {
89+
this._post(this.SOURCE_URL + "/" + this.ACTION, {
8790
MDX: this.BASIC_MDX
8891
}, function (data) {
89-
callback(_._convert(data));
92+
(data.Info || {}).action = _.ACTION;
93+
if (_.ACTION === "MDXDrillthrough") {
94+
callback((function (data) {
95+
96+
var arr = data["children"] || [],
97+
headers = [],
98+
obj, i, u;
99+
100+
if (!arr.length) return {
101+
error: "No DrillThrough data."
102+
};
103+
104+
for (i in arr[0]) {
105+
headers.push({ caption: i });
106+
}
107+
108+
obj = {
109+
Cols: [ { tuples: headers }, { tuples: [] } ],
110+
Data: [],
111+
Info: {
112+
colCount: 8,
113+
cubeClass: "No cube class",
114+
cubeName: "No cube name",
115+
leftHeaderColumnsNumber: 0,
116+
rowCount: arr.length,
117+
topHeaderRowsNumber: headers.length,
118+
action: _.ACTION
119+
}
120+
};
121+
122+
for (i in arr) {
123+
for (u in arr[i]) {
124+
obj.Data.push(arr[i][u]);
125+
}
126+
}
127+
128+
return __(obj);
129+
130+
})(data));
131+
} else if (_.ACTION = "MDX") {
132+
callback(_._convert(data));
133+
} else {
134+
console.error("Not implemented URL action: " + _.ACTION);
135+
callback({ error: "Not implemented URL action: " + data || true });
136+
}
90137
});
91138

92139
};

source/js/LightPivotTable.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ LightPivotTable.prototype.tryDrillDown = function (filter) {
7373
var _ = this,
7474
ds = {};
7575

76-
// clone
76+
// clone dataSource config object
7777
for (var i in _.CONFIG.dataSource) { ds[i] = _.CONFIG.dataSource[i]; }
7878
ds.basicMDX = this.mdxParser.drillDown(ds.basicMDX, filter) || ds.basicMDX;
7979

@@ -91,6 +91,30 @@ LightPivotTable.prototype.tryDrillDown = function (filter) {
9191

9292
};
9393

94+
LightPivotTable.prototype.showDrillThrough = function () {
95+
96+
var _ = this,
97+
ds = {};
98+
99+
// clone dataSource config object
100+
for (var i in _.CONFIG.dataSource) { ds[i] = _.CONFIG.dataSource[i]; }
101+
ds.action = "MDXDrillthrough";
102+
ds.basicMDX = this.mdxParser.drillThrough(ds.basicMDX) || ds.basicMDX;
103+
104+
this.pushDataSource(ds);
105+
106+
this.dataSource.getCurrentData(function (data) {
107+
if (_.dataController.isValidData(data) && data.dataArray.length > 0) {
108+
_.pivotView.pushTable();
109+
_.dataController.pushData();
110+
_.dataController.setData(data);
111+
} else {
112+
_.popDataSource();
113+
}
114+
});
115+
116+
};
117+
94118
LightPivotTable.prototype.init = function () {
95119

96120
this.refresh();

source/js/MDXParser.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,39 @@ MDXParser.prototype.drillDown = function (basicMDX, filter) {
2323
oldPath[2] = clearFilter + ".children";
2424
parts[2] = oldPath.join("");
2525

26-
return "\n\n\n" + parts.join("") + " %FILTER " + filterParts.join("");
26+
return parts.join("") + " %FILTER " + filterParts.join("");
2727

2828
} catch (e) {
2929

30+
console.error("Unable to get DrillDown statement from", basicMDX, "with filter", filter);
3031
return "";
3132

3233
}
3334

3435
};
36+
37+
/**
38+
* Returns DrillThrough query for given MDX query.
39+
*
40+
* @param {string} basicMDX
41+
* @returns {string}
42+
*/
43+
MDXParser.prototype.drillThrough = function (basicMDX) {
44+
45+
try {
46+
47+
var statement = ["DRILLTHROUGH SELECT "]
48+
.concat(basicMDX.split(/(\s+ON\s+0,\s*)(.*)(\s+ON\s+1\s*)/).slice(2)).join("");
49+
50+
console.log("DRILLTHROUGH STATEMENT:", statement);
51+
52+
return statement === "DRILLTHROUGH SELECT " ? "" : statement;
53+
54+
} catch (e) {
55+
56+
console.error("Unable to get DrillThrough statement from", basicMDX);
57+
return "";
58+
59+
}
60+
61+
};

source/js/PivotView.js

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ PivotView.prototype._backClickHandler = function () {
141141

142142
};
143143

144+
PivotView.prototype._drillThroughClickHandler = function (event) {
145+
146+
this.controller.showDrillThrough();
147+
148+
event.cancelBubble = true;
149+
event.stopPropagation();
150+
151+
};
152+
144153
PivotView.prototype.fixSizes = function (baseElement, elementToFix) {
145154

146155
if (!elementToFix.style) return false;
@@ -304,6 +313,17 @@ PivotView.prototype.renderRawData = function (data) {
304313
headColsNum = 0, headLeftColsNum = 0,
305314
headRowsNum = 0, headLeftRowsNum = 0;
306315

316+
var addTrigger = function (element, event, trigger) {
317+
318+
element["triggerFunction"] = {
319+
event: event,
320+
trigger: trigger
321+
};
322+
323+
element.addEventListener(event, trigger);
324+
325+
};
326+
307327
// compute headColsNum & headLeftColsNum
308328
for (y = 0; y < data.length; y++) {
309329
for (x = 0; x < data[y].length; x++) {
@@ -357,13 +377,12 @@ PivotView.prototype.renderRawData = function (data) {
357377
})(data[y][x].group);
358378

359379
if (x === 0 && y === 0 && _.tablesStack.length > 1) {
360-
td.className += " backButton";
361-
td.addEventListener("click", (td["triggerFunction"] = {
362-
trigger: function () {
363-
_._backClickHandler.call(_);
364-
},
365-
event: "click"
366-
}).trigger);
380+
var elt = document.createElement("div");
381+
elt.className = "backButton";
382+
addTrigger(elt, "click", function () {
383+
_._backClickHandler.call(_);
384+
});
385+
td.insertBefore(elt, td.childNodes[td.childNodes.length - 1] || null);
367386
}
368387

369388
}
@@ -375,34 +394,40 @@ PivotView.prototype.renderRawData = function (data) {
375394
if (td && x >= headLeftColsNum && y === headColsNum - 1) {
376395
// clickable cells (sort option)
377396
(function (x) {
378-
td.addEventListener("click", (td["triggerFunction"] = {
379-
trigger: function () {
380-
var colNum = x - headLeftColsNum;
381-
_._columnClickHandler.call(_, colNum);
382-
},
383-
event: "click"
384-
}).trigger);
397+
addTrigger(td, "click", function () {
398+
var colNum = x - headLeftColsNum;
399+
_._columnClickHandler.call(_, colNum);
400+
});
385401
})(x);
386402
}
387403

388404
// add _rowClickHandler to th's last column
389405
if (td && x === headLeftColsNum - 1 && y >= headRowsNum) {
390406
(function (y, x) {
391-
td.addEventListener("click", (td["triggerFunction"] = {
392-
trigger: function () {
393-
var rowNum = y - headRowsNum;
394-
_._rowClickHandler.call(_, rowNum, data[y][x]);
395-
},
396-
event: "click"
397-
}).trigger);
407+
addTrigger(td, "click", function () {
408+
var rowNum = y - headRowsNum;
409+
_._rowClickHandler.call(_, rowNum, data[y][x]);
410+
});
398411
})(y, x);
399412
}
400413

401414
if (td) {
402-
td.textContent = data[y][x].value;
415+
var span = document.createElement("span");
416+
span.textContent = data[y][x].value;
417+
td.appendChild(span);
418+
//td.textContent = ;
403419
tr.appendChild(td);
404420
}
405421

422+
if (x === 0 && y === 0 && _.controller.dataController.getData().info.action === "MDX") {
423+
var element = document.createElement("div");
424+
element.className = "drillDownIcon";
425+
addTrigger(element, "click", function (event) {
426+
_._drillThroughClickHandler.call(_, event);
427+
});
428+
td.insertBefore(element, td.childNodes[td.childNodes.length - 1] || null);
429+
}
430+
406431
}
407432
(y < headColsNum ? thead : tbody).appendChild(tr);
408433
}

0 commit comments

Comments
 (0)