Saiku设置展示table数据不隐藏空的行数据信息
saiku有个 非空的字段 按钮,点击这个后,会自动的把空的行数据信息给隐藏掉,这里我们来设置一下让其行数据不隐藏,为空的就为空。
主要更改两个文件
1. Query.js 文件路径: /saiku-ui/js/saiku/models/Query.js (如果是编译好的saiku,请找到 saiku-server\tomcat\webapps\ROOT\js\saiku\models\Query.js )
2. SaikuTableRenderer.js 文件路径: /saiku-ui/js/saiku/render/SaikuTableRenderer.js (如果是编译好的saiku,请找到 saiku-server\tomcat\webapps\ROOT\js\saiku\render\SaikuTableRenderer.js )
这里我们是在做KPI汇总信息的是遇到这样的需求,具体还是看用户需求去改动哦哈哈哈~ 我们这边是要求为空的数据列信息也要展示空的数据信息。
1.首先我们为了保证后台能传回完整的数据,需要在Query.js 的 run 方法中设定参数信息 行数据非空也展示 (ps: 为了避免影响到其他数据的展示,我们将需要行数据为空也展示的数据单独拿出来判断,通过cube名来判断!)
var exModel = this.helper.model(); // 这条是run 方法里面原有的数据哦
主要代码: exModel.queryModel.axes.ROWS.nonEmpty=false;//設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data 这是新加的
//針對Summary數據做出更改 當行數據為空的時候 也需要展示出來
var cubename = exModel.cube.name ;
if(cubename == "SummaryKPI_2018_ext" ||cubename == "SummaryKPI_2019_ext" ||cubename == "SummaryKPI_2019_Dynamic" ) {
exModel.queryModel.axes.ROWS.nonEmpty=false;//設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}else{
exModel.queryModel.axes.ROWS.nonEmpty=true;
}
2.然后我们再在table渲染页面设定数据项为空也展示就可以啦!!! SaikuTableRenderer.js 的 internalRender 方法
更改rowWithOnlyEmptyCells 的默认值为 false , (ps: 为了避免影响到其他数据的展示,我们将需要行数据为空也展示的数据单独拿出来判断,通过cube名来判断!)
//rowWithOnlyEmptyCells = true; //默认行数据为空时不展展示,如果需要不展示改回来 将此条值置为true即可
主要代码: rowWithOnlyEmptyCells = false; //設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
rowWithOnlyEmptyCells = true; //默认行数据为空时不展展示,如果改回来 将此条值置为true即可
if(cubename == "SummaryKPI_2018_ext" ||cubename == "SummaryKPI_2019_ext" ||cubename == "SummaryKPI_2019_Dynamic"){
rowWithOnlyEmptyCells = false; //設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}
这样就可以了哦。
>>> 下面提供完整的js文件
Query.js
/*
* Copyright 2012 OSBI Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Workspace query
*/
var Query = Backbone.Model.extend({
formatter: Settings.CELLSET_FORMATTER,
properties: null,
/*初始化方法*/
initialize: function(args, options) {
if(args != null && args != undefined && args != "" && args.flag == "resultForstatisdate"){
this.get_all_statisdate(args);
}else{
// Save cube
_.extend(this, options);
// Bind `this`
_.bindAll(this, "run");
// Generate a unique query id
this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function (c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}).toUpperCase();
this.model = _.extend({ name: this.uuid }, SaikuOlapQueryTemplate);
if (args.cube) {
this.model.cube = args.cube;
}
this.helper = new SaikuOlapQueryHelper(this);
// Initialize properties, action handler, and result handler
this.action = new QueryAction({}, { query: this });
this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
this.scenario = new QueryScenario({}, { query: this });
// A flag to tell who changed selection members
this.updatedSelectionFromModal = false;
}
},
parse: function(response) {
// Assign id so Backbone knows to PUT instead of POST
this.id = this.uuid;
if (response.name) {
this.id = response.name;
this.uuid = response.name;
}
this.model = _.extend(this.model, response);
this.model.properties = _.extend({}, Settings.QUERY_PROPERTIES, this.model.properties);
},
setProperty: function(key, value) {
this.model.properties[key] = value;
},
getProperty: function(key) {
return this.model.properties[key];
},
syncSelectionsModalAndUpdateParameters: function() {
if (this.updatedSelectionFromModal) {
var mParameters = this.helper.model().parameters;
for (var mKey in mParameters) {
var mVal = mParameters[mKey];
var selections = this.helper.getSelectionsForParameter(mKey);
mVal = selections.map(function(sel) { return sel.caption; }).join();
mParameters[mKey] = mVal;
}
} else {
var mParameters = this.helper.model().parameters;
for (var mKey in mParameters) {
var mVal = mParameters[mKey];
var mLevel = this.helper.getLevelForParameter(mKey);
var selections = this.helper.getSelectionsForParameter(mKey);
if (mVal !== null && mVal !== undefined) {
this.helper.setSelectionsForParameter(mKey, _.filter(selections, function(sel) {
var containsParam = false;
_.each(mVal.split(','), function (v) {
if (sel.caption === v) {
containsParam = true;
return false;
}
});
return containsParam;
}));
}
}
}
this.updatedSelectionFromModal = false;
},
/*执行查询的方法*/
run: function(force, mdx) {
this.syncSelectionsModalAndUpdateParameters();
var self = this;
// Check for automatic execution
Saiku.ui.unblock();
if (typeof this.model.properties != "undefined" && this.model.properties['saiku.olap.query.automatic_execution'] === false &&
(force === false || force === undefined || force === null)) {
return;
}
this.workspace.unblock();
$(this.workspace.el).find(".workspace_results_info").empty();
this.workspace.trigger('query:run');
this.result.result = null;
var validated = false;
var errorMessage = '<span class="i18n">Query Validation failed!</span>';
var exModel = this.helper.model();
//針對Summary數據做出更改 當行數據為空的時候 也需要展示出來
var cubename = exModel.cube.name ;
if(cubename == "SummaryKPI_2018_ext" ||cubename == "SummaryKPI_2019_ext" ||cubename == "SummaryKPI_2019_Dynamic" ) {
exModel.queryModel.axes.ROWS.nonEmpty=false;//設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}else{
exModel.queryModel.axes.ROWS.nonEmpty=true;
}
for(var k in this.attributes) {
var att = this.attributes[k];
if(k.substring(0,5)==="PARAM"){
var p = k.substring(5, k.length);
exModel.parameters[p] = att;
}
}
if (exModel.queryType == "OLAP") {
if (exModel.type == "QUERYMODEL") {
var columnsOk = Object.keys(exModel.queryModel.axes.COLUMNS.hierarchies).length > 0;
var rowsOk = Object.keys(exModel.queryModel.axes.ROWS.hierarchies).length > 0;
var detailsOk = exModel.queryModel.details.axis == 'COLUMNS' && exModel.queryModel.details.measures.length > 0;
if (!rowsOk || !columnsOk || !detailsOk) {
errorMessage = "";
}
if (!columnsOk && !detailsOk) {
errorMessage += '<span class="i18n">You need to include at least one measure or a level on columns for a valid query.</span>';
}
if(!rowsOk) {
errorMessage += '<span class="i18n">You need to include at least one level on rows for a valid query.</span>';
}
if ( (columnsOk || detailsOk) && rowsOk) {
validated = true;
}
} else if (exModel.type == "MDX") {
validated = (exModel.mdx && exModel.mdx.length > 0);
if (!validated) {
errorMessage = '<span class="i18n">You need to enter some MDX statement to execute.</span>';
}
}
}
if (!validated) {
this.workspace.table.clearOut();
$(this.workspace.processing).html(errorMessage).show();
this.workspace.adjust();
Saiku.i18n.translate();
return;
}
// Run it
this.workspace.table.clearOut();
$(this.workspace.processing).html('<span class="processing_image"> </span> <span class="i18n">Running query...</span> [ <a class="cancel i18n" href="#cancel">Cancel</a> ]').show();
this.workspace.adjust();
this.workspace.trigger('query:fetch');
Saiku.i18n.translate();
var message = '<span class="processing_image"> </span> <span class="i18n">Running query...</span> [ <a class="cancel i18n" href="#cancel">Cancel</a> ]';
this.workspace.block(message);
/*
TODO: i wonder if we should clean up the model (name and captions etc.)
delete this.model.queryModel.axes['FILTER'].name;
*/
/**根据ROWS中的statisdate字段过滤!*/
//根據用戶輸入的開始日期與結束日期查詢範圍數據
/*
var dimensionArr = exModel.queryModel.axes.ROWS.hierarchies; //取出行信息中的所有维度信息 dimension,用一个数组接收
var statisdateFlag = "no";
for(var i=0;i<dimensionArr.length;i++){
//判断维度信息中是否有statisdate这个时间维度(这是固定的)
if(dimensionArr[i]!=null && ((dimensionArr[i].dimension == "statisdate")||(dimensionArr[i].levels.statisdate != null)) ){
var paramsURI = Saiku.URLParams.paramsURI(); //get the param from url
//判断参数是否为空
if(paramsURI.startdate != null && paramsURI.startdate != undefined && paramsURI.startdate != ""&&
paramsURI.enddate != null && paramsURI.enddate != undefined && paramsURI.enddate != ""){
statisdateFlag = "yes";
this.startdateThis=null;
this.enddateThis=null;
var key="statisdateSpec";
(new SelectionsModal({
key: key,
exModel: exModel,
result: this.result,
workspace: this.workspace
}));
}
}
}
*/
/**根据Fliter中的statisdate字段过滤!*/
var dimensionArr = exModel.queryModel.axes.FILTER.hierarchies; //取出FILTER信息中的所有维度信息 dimension,用一个数组接收
var statisdateFlag = "no";
for(var i=0;i<dimensionArr.length;i++){
//判断维度信息中是否有statisdate这个时间维度(这是固定的)
if(dimensionArr[i]!=null && ((dimensionArr[i].dimension == "statisdate")||(dimensionArr[i].levels.statisdate != null)) ){
var paramsURI = Saiku.URLParams.paramsURI(); //get the param from url
//判断参数是否为空
if(paramsURI.startdate != null && paramsURI.startdate != undefined && paramsURI.startdate != ""&&
paramsURI.enddate != null && paramsURI.enddate != undefined && paramsURI.enddate != ""){
statisdateFlag = "yes";
this.startdateThis=null;
this.enddateThis=null;
var key="statisdateSpec";
(new SelectionsModal({
key: key,
exModel: exModel,
result: this.result,
workspace: this.workspace
}));
}
}
}
//根据入参是否有statisdate字段来判断是否执行以下查询
if(statisdateFlag == 'no'){
this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
Saiku.ui.unblock();
var errorMessage = '<span class="i18n">Error executing query. Please check the server logs or contact your administrator!</span>';
self.workspace.table.clearOut();
$(self.workspace.processing).html(errorMessage).show();
self.workspace.adjust();
Saiku.i18n.translate();
} });
}
},
//得到返回的所有statisdate參數信息
get_all_statisdate: function(args){
var response = args.response;
this.result = args.result;
//var exModel = args.exModel;
var statisdateArr= new Array();
for(var i=0;i<response.length;i++){
statisdateArr[i]=response[i].name;
}
//this.helper = new SaikuOlapQueryHelper(this);
var exModel = args.exModel;
var paramsURI = Saiku.URLParams.paramsURI(); //get the param from url
var startdate=null;
var enddate=null;
if(this.startdateThis != null){
startdate=this.dateToStr(this.startdateThis); //获取修正后的开始日期
}else{
startdate=paramsURI.startdate;//开始日期(参数中的)
}
if(this.enddateThis != null){
enddate=this.dateToStr(this.enddateThis); //获取修正后的结束日期
}else{
enddate=paramsURI.enddate;//结束日期(参数中的)
}
//startdate = this.dateToStr(startdate); // 日期格式化
//enddate = this.dateToStr(enddate); // 日期格式化
if(statisdateArr.indexOf(startdate) > -1){// 这里是判断开始日期是否属于statisdateArr
if(statisdateArr.indexOf(enddate) > -1){// 这里是判断结束日期是否属于statisdateArr
//var dimensionArr = exModel.queryModel.axes.ROWS.hierarchies; //根据ROWS
var dimensionArr = exModel.queryModel.axes.FILTER.hierarchies; //根据Filter
for(var i=0;i<dimensionArr.length;i++){
if(dimensionArr[i]!=null && (dimensionArr[i].dimension == "statisdate" || dimensionArr[i].levels.statisdate != null ) ){
//更改level下的mdx表达式(使用開始日期與結束日期來控制過濾數據)
dimensionArr[i].levels.statisdate.mdx="[statisdate].[statisdate].[statisdate].["+startdate+"]:[statisdate].[statisdate].[statisdate].["+enddate+"]";
//需要清除之前默認展示本週數據的過濾腳本信息
//exModel.queryModel.axes.ROWS.filters=[];//在ROWS中定义了过滤表达式时,清除此表达式
exModel.queryModel.axes.FILTER.filters=[];//在Filter中定义了过滤表达式时,清除此表达式
}
}
this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
Saiku.ui.unblock();
var errorMessage = '<span class="i18n">Error executing query. Please check the server logs or contact your administrator!</span>';
self.workspace.table.clearOut();
$(self.workspace.processing).html(errorMessage).show();
self.workspace.adjust();
Saiku.i18n.translate();
} });
}else{//结束日期不存在时:如果结束日期大于开始日期,将结束日期往前减一天
var tmpStartdate = this.strToDate(startdate);//StringToDate方法不存在
var tmpEnddate = this.strToDate(enddate);
if(tmpEnddate>=tmpStartdate){
tmpEnddate = tmpEnddate.valueOf();
tmpEnddate = tmpEnddate - 1*24*60*60*1000;
tmpEnddate = new Date(tmpEnddate);
//这里改变paramURL中的结束日期参数值,然后回调当前函数 get_all_statisdate
this.enddateThis=tmpEnddate;
this.get_all_statisdate(args);
}else{ //否则的话直接执行查询,直接无数据返回
var dimensionArr = exModel.queryModel.axes.FILTER.hierarchies;
for(var i=0;i<dimensionArr.length;i++){
if(dimensionArr[i]!=null && (dimensionArr[i].dimension == "statisdate" || dimensionArr[i].levels.statisdate != null ) ){
enddate = this.dateToStr(tmpStartdate)
//更改level下的mdx表达式(使用開始日期與結束日期來控制過濾數據)
dimensionArr[i].levels.statisdate.mdx="[statisdate].[statisdate].[statisdate].["+enddate+"]:[statisdate].[statisdate].[statisdate].["+enddate+"]";
//需要清除之前默認展示本週數據的過濾腳本信息
//exModel.queryModel.axes.ROWS.filters=[];//在ROWS中定义了过滤表达式时,清除此表达式
exModel.queryModel.axes.FILTER.filters=[];//在Filter中定义了过滤表达式时,清除此表达式
}
}
this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
Saiku.ui.unblock();
var errorMessage = '<span class="i18n">Error executing query. Please check the server logs or contact your administrator!</span>';
self.workspace.table.clearOut();
$(self.workspace.processing).html(errorMessage).show();
self.workspace.adjust();
Saiku.i18n.translate();
} });
}
}
}else{ //开始日期不存在时: 如果开始日期小于结束日期,将开始日期往后加一天
var tmpStartdate = this.strToDate(startdate);
var tmpEnddate = this.strToDate(enddate);
if(tmpStartdate<=tmpEnddate){
tmpStartdate = tmpStartdate.valueOf();
tmpStartdate = tmpStartdate + 1*24*60*60*1000;
tmpStartdate = new Date(tmpStartdate);
//这里改变paramURL中的结束日期参数值,然后回调当前函数get_all_statisdate
this.startdateThis=tmpStartdate;
this.get_all_statisdate(args);
}else{ //否则的话直接执行查询,直接无数据返回
var dimensionArr = exModel.queryModel.axes.FILTER.hierarchies;
for(var i=0;i<dimensionArr.length;i++){
if(dimensionArr[i]!=null && (dimensionArr[i].dimension == "statisdate" || dimensionArr[i].levels.statisdate != null ) ){
startdate = this.dateToStr(tmpEnddate)
//更改level下的mdx表达式(使用開始日期與結束日期來控制過濾數據)
dimensionArr[i].levels.statisdate.mdx="[statisdate].[statisdate].[statisdate].["+startdate+"]:[statisdate].[statisdate].[statisdate].["+startdate+"]";
//需要清除之前默認展示本週數據的過濾腳本信息
//exModel.queryModel.axes.ROWS.filters=[];//在ROWS中定义了过滤表达式时,清除此表达式
exModel.queryModel.axes.FILTER.filters=[];//在Filter中定义了过滤表达式时,清除此表达式
}
}
this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
Saiku.ui.unblock();
var errorMessage = '<span class="i18n">Error executing query. Please check the server logs or contact your administrator!</span>';
self.workspace.table.clearOut();
$(self.workspace.processing).html(errorMessage).show();
self.workspace.adjust();
Saiku.i18n.translate();
} });
}
}
},
/*將string類型的數據轉換為date類型*/
strToDate: function(strDate){
strDate = strDate.toLocaleString();
strDate = strDate.substring(-1,10);
var convert = Date.parse(strDate);
var tmpdate = new Date(convert);
return tmpdate;
},
/*将Date类型转换为String类型 格式为:2019-03-03*/
dateToStr: function(dateStr){
//dateStr = this.strToDate(dateStr);
var tmpYear= dateStr.getFullYear();
var tmpMonth = dateStr.getMonth()+1;
var tmpDay = dateStr.getDate();
if(tmpMonth < 10){ tmpMonth = "0"+tmpMonth;}
if(tmpDay < 10){ tmpDay = "0"+tmpDay;}
var tmpdate = tmpYear+"-"+tmpMonth+"-"+tmpDay;
return tmpdate;
},
enrich: function() {
var self = this;
this.workspace.query.action.post("/../enrich", {
contentType: "application/json",
data: JSON.stringify(self.model),
async: false,
success: function(response, model) {
self.model = model;
}
});
},
url: function() {
return "api/query/" + encodeURI(this.uuid);
}
/**
get_statisdate_members: function() {
var path = "/result/metadata/hierarchies/%5Bstatisdate%5D.%5Bstatisdate%5D/levels/statisdate";
* gett isn't a typo, although someone should probably rename that method to avoid confusion.
this.workspace.query.action.gett(path, {
success: this.fetch_statisdate_members,
error: function() {
alert("error");
},
data: {result: true, searchlimit: 30000 }});
},
得到獲取statisdate字段的結果信息然後處理
fetch_statisdate_members: function(model, response) {
if (response && response.length > 0) {
alert("Fetch_statisdate_member++++++++++++"+response);
}
},
*/
});
SaikuTableRenderer.js
function SaikuTableRenderer(data, options) {
this._data = data;
this._options = _.extend({}, SaikuRendererOptions, options);
}
function getAxisLevelsName(data, axisName) {
var queryData = data.query.queryModel.axes[axisName].hierarchies;
var len = queryData.length;
var arrLevels = [];
for (var i = 0; i < len; i++) {
for (var level in queryData[i].levels) {
if (queryData[i].levels.hasOwnProperty(level)) {
if (Settings.COLUMN_TITLE_TABLE_USE_LEVEL_CAPTION_NAME) {
arrLevels.push(queryData[i].levels[level].caption);
}
else {
arrLevels.push(level);
}
}
}
}
return arrLevels;
}
function setStyleNegativeNumber(value) {
var className = '';
if (Settings.STYLE_NEGATIVE_NUMBER && parseFloat(value) < 0) {
className = ' style_negative_number ';
}
return className;
}
function getAxisSize(data, axisName) {
var queryData = data.query.queryModel.axes[axisName].hierarchies;
var len = queryData.length;
var axisSize = 0;
for (var i = 0; i < len; i++) {
axisSize += _.size(queryData[i].levels);
}
return axisSize;
}
function getDomColumnsLevelsName(htmlObject) {
var $htmlObject = $(htmlObject.closest('.workspace')
.find('.workspace_fields')
.find('.columns.axis_fields')
.find('.hierarchy')
.find('.d_level'));
var arrLevels = [];
$.each($htmlObject, function(key, level) {
if ($(level).attr('style') === 'display: list-item;') {
if (Settings.COLUMN_TITLE_TABLE_USE_LEVEL_CAPTION_NAME) {
arrLevels.push($(level).find('.level').attr('title'));
}
else {
arrLevels.push($(level).find('.level').attr('level'));
}
}
});
return arrLevels;
}
/*table render method*/
SaikuTableRenderer.prototype.render = function(data, options) {
var self = this;
if (data) {
this._data = data;
}
if (options) {
this._options = _.extend({}, SaikuRendererOptions, options);
}
if (typeof this._data == "undefined") {
return;
}
if (this._data != null && this._data.error != null) {
return;
}
if (this._data == null || (this._data.cellset && this._data.cellset.length === 0)) {
return;
}
this.hideEmpty = this._options.hideEmpty;
if (this._options.htmlObject) {
// $(this._options.htmlObject).stickyTableHeaders("destroy");
// in case we have some left over scrollers
if (self._options.hasOwnProperty('batch')) {
$(self._options.htmlObject).parent().parent().unbind('scroll');
}
_.defer(function(that) {
if (self._options.hasOwnProperty('batch') && !self._options.hasOwnProperty('batchSize')) {
self._options['batchSize'] = 1000;
}
// the key method to render data by table form. 20190423
var html = self.internalRender(self._data, self._options);
$(self._options.htmlObject).html(html);
// Render the totals summary
$('#totals_summary').remove(); // Remove one previous totals div, if present
$(self._options.htmlObject).after(self.renderSummary(data)); // Render the new summary
// $(self._options.htmlObject).stickyTableHeaders( { container: self._options.htmlObject.parent().parent(), fixedOffset: self._options.htmlObject.parent().parent().offset().top });
_.defer(function(that) {
if (self._options.hasOwnProperty('batch') && self._options.hasBatchResult) {
var batchRow = 0;
var batchIsRunning = false;
var batchIntervalSize = self._options.hasOwnProperty('batchIntervalSize') ? self._options.batchIntervalSize : 20;
var batchIntervalTime = self._options.hasOwnProperty('batchIntervalTime') ? self._options.batchIntervalTime : 20;
var len = self._options.batchResult.length;
var batchInsert = function() {
// maybe add check for reach table bottom - ($('.workspace_results').scrollTop() , $('.workspace_results table').height()
if (!batchIsRunning && len > 0 && batchRow < len) {
batchIsRunning = true;
var batchContent = "";
var startb = batchRow;
for (var i = 0; batchRow < len && i < batchIntervalSize ; i++, batchRow++) {
batchContent += self._options.batchResult[batchRow];
}
if (batchRow > startb) {
$(self._options.htmlObject).append( $(batchContent));
}
batchIsRunning = false;
}
if (batchRow >= len) {
$(self._options.htmlObject).parent().parent().unbind('scroll');
}
};
var lazyBatchInsert = _.debounce(batchInsert, batchIntervalTime);
$(self._options.htmlObject).parent().parent().scroll(function () {
lazyBatchInsert();
});
}
});
return html;
});
} else {
var html = this.internalRender(this._data, self._options);
return html;
}
};
SaikuTableRenderer.prototype.clear = function(data, options) {
var self = this;
if (this._options && this._options.htmlObject && this._options.hasOwnProperty('batch')) {
$(self._options.htmlObject).parent().parent().unbind('scroll');
}
};
SaikuTableRenderer.prototype.processData = function(data, options) {
this._hasProcessed = true;
};
function genTotalDataCells(currentIndex, cellIndex, scanSums, scanIndexes, lists) {
var contents = '';
var lists = lists[ROWS];
for (var i = scanSums.length - 1; i >= 0; i--) {
if (currentIndex == scanSums[i]) {
var currentListNode = lists[i][scanIndexes[i]];
for (var m = 0; m < currentListNode.cells.length; m++) {
contents += '<td class="data total">' + currentListNode.cells[m][cellIndex].value + '</td>';
}
scanIndexes[i]++;
if (scanIndexes[i] < lists[i].length)
scanSums[i] += lists[i][scanIndexes[i]].width;
}
}
return contents;
}
function genTotalHeaderCells(currentIndex, bottom, scanSums, scanIndexes, lists, wrapContent) {
var contents = '';
for (var i = bottom; i >= 0; i--) {
if (currentIndex == scanSums[i]) {
var currentListNode = lists[i][scanIndexes[i]];
var cssClass;
if (i == 0 && bottom == 1)
cssClass = "col";
else if (i == bottom)
cssClass = "col_total_corner";
else if (i == bottom - 1 && currentListNode.captions)
cssClass = "col_total_first";
else cssClass = "col_null";
for (var m = 0; m < currentListNode.cells.length; m++) {
var text = ' ';
if (bottom == lists.length - 1) {
if (currentListNode.captions) {
text = lists[i][scanIndexes[i]].captions[m];
}
if (i == 0 && scanIndexes[i] == 0) {
if (currentListNode.captions)
text += " ";
else text = "";
text += (wrapContent ? "<span class='i18n'>Grand Total</span>" : "Grand Total");
}
}
contents += '<th class="' + cssClass + '">'
+ (wrapContent ? '<div>' + text + '</div>' : text ) + '</th>';
}
scanIndexes[i]++;
if (scanIndexes[i] < lists[i].length)
scanSums[i] += lists[i][scanIndexes[i]].width;
}
}
return contents;
}
function totalIntersectionCells(currentIndex, bottom, scanSums, scanIndexes, lists) {
var contents = '';
for (var i = bottom; i >= 0; i--) {
if (currentIndex == scanSums[i]) {
var currentListNode = lists[i][scanIndexes[i]];
var cssClass = "data total";
for (var m = 0; m < currentListNode.cells.length; m++) {
var text = ' ';
contents += '<td class="' + cssClass + '">' + text + '</td>';
}
scanIndexes[i]++;
if (scanIndexes[i] < lists[i].length)
scanSums[i] += lists[i][scanIndexes[i]].width;
}
}
return contents;
}
function isNextTotalsRow(currentIndex, scanSums, scanIndexes, totalsLists, wrapContent) {
var colLists = totalsLists[COLUMNS];
var colScanSums = scanSums[COLUMNS];
var colScanIndexes = scanIndexes[COLUMNS];
var bottom = colLists.length - 2;
var contents = -1;
for (var i = bottom; i >= 0; i--) {
if (currentIndex == colScanSums[i]) {
for (var m = 0; m < colLists[i][colScanIndexes[i]].cells.length; m++) {
contents += '<tr>';
for (var j = 0; j <= bottom; j++) {
var cssClass;
var text = ' ';
if (i == 0 && j == 0)
cssClass = 'row';
else if (i == j + 1){
cssClass = 'row_total_corner';
return j;
}
else if (i == j && colLists[i][colScanIndexes[i]].captions) {
cssClass = 'row_total_first';
} else if (i < j + 1)
cssClass = 'row_total';
else
cssClass = 'row_null';
if (j == bottom ) {
if (colLists[i][colScanIndexes[i]].captions) {
text = colLists[i][colScanIndexes[i]].captions[m];
}
if (i == 0 && colScanIndexes[i] == 0) {
if (colLists[i][colScanIndexes[i]].captions)
text += " ";
else text = "";
text += (wrapContent ? "<span class='i18n'>Grand Total</span>" : "Grand Total");
}
}
}
}
}
}
return -1;
}
function genTotalHeaderRowCells(currentIndex, scanSums, scanIndexes, totalsLists, wrapContent) {
var colLists = totalsLists[COLUMNS];
var colScanSums = scanSums[COLUMNS];
var colScanIndexes = scanIndexes[COLUMNS];
var bottom = colLists.length - 2;
var contents = '';
for (var i = bottom; i >= 0; i--) {
if (currentIndex == colScanSums[i]) {
for (var m = 0; m < colLists[i][colScanIndexes[i]].cells.length; m++) {
contents += '<tr>';
for (var j = 0; j <= bottom; j++) {
var cssClass;
var text = ' ';
if (i == 0 && j == 0)
cssClass = 'row';
else if (i == j + 1)
cssClass = 'row_total_corner';
else if (i == j && colLists[i][colScanIndexes[i]].captions) {
cssClass = 'row_total_first';
} else if (i < j + 1)
cssClass = 'row_total';
else
cssClass = 'row_null';
if (j == bottom ) {
if (colLists[i][colScanIndexes[i]].captions) {
text = colLists[i][colScanIndexes[i]].captions[m];
}
if (i == 0 && colScanIndexes[i] == 0) {
if (colLists[i][colScanIndexes[i]].captions)
text += " ";
else text = "";
text += (wrapContent ? "<span class='i18n'>Grand Total</span>" : "Grand Total");
}
}
contents += '<th class="' + cssClass + '">'
+ (wrapContent ? '<div>' + text + '</div>' : text ) + '</th>';
}
var scanIndexes = {};
var scanSums = {};
if (totalsLists[ROWS]) {
for (var z = 0; z < totalsLists[ROWS].length; z++) {
scanIndexes[z] = 0;
scanSums[z] = totalsLists[ROWS][z][scanIndexes[z]].width;
}
}
for (var k = 0; k < colLists[i][colScanIndexes[i]].cells[m].length; k++) {
contents += '<td class="data total">' + colLists[i][colScanIndexes[i]].cells[m][k].value + '</td>';
if (totalsLists[ROWS]) {
contents += totalIntersectionCells(k + 1, totalsLists[ROWS].length - 1, scanSums, scanIndexes, totalsLists[ROWS]);
}
}
contents += '</tr>';
}
colScanIndexes[i]++;
if (colScanIndexes[i] < colLists[i].length) {
colScanSums[i] += colLists[i][colScanIndexes[i]].width;
}
}
}
return contents;
}
var ROWS = "ROWS";
var COLUMNS = "COLUMNS";
function nextParentsDiffer(data, row, col) {
while (row-- > 0) {
if (data[row][col].properties.uniquename != data[row][col + 1].properties.uniquename)
return true;
}
return false;
}
function topParentsDiffer(data, row, col) {
while (col-- > 0)
if (data[row][col].properties.uniquename != data[row - 1][col].properties.uniquename)
return true;
return false;
}
/**
* This function is intended to traverse the totals arrays and cleanup empty
* totals. This will optimize the query result on screen, displaying just the
* needed cells.
* @param dirs The direction array ['ROWS', 'COLUMNS']
* @param totalsLists The totals from allData.rowTotalsLists and allData.colTotalsLists.
*/
function cleanupTotals(dirs, totalsLists) {
// For each direction (ROWS/COLUMNS)
for (var dirIndex = 0; dirIndex < dirs.length; dirIndex++) {
var dir = dirs[dirIndex];
// If there are defined totals
if (totalsLists[dir]) {
var isEmpty = true; // A flag to indicate if this total is empty
for (var row = 0; row < totalsLists[dir].length; row++) {
var totalsInfoArray = totalsLists[dir][row];
for (var totalIndex = 0; totalIndex < totalsInfoArray.length; totalIndex++) {
var cells = totalsLists[dir][row][totalIndex].cells;
for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
var cellArray = cells[cellIndex];
// For each total cell
for (var i = 0; i < cellArray.length; i++) {
var cell = cellArray[i];
// If it contains a value different from empty
if (cell.value !== '-') {
isEmpty = false; // So, this total is not empty
}
}
}
}
}
if (isEmpty) { // If this total is empty
totalsLists[dir] = null; // Remove it
}
}
}
}
/*the main method to render data by table form. 20190423*/
SaikuTableRenderer.prototype.internalRender = function(allData, options) {
var tableContent = "";
var rowContent = "";
var data = allData.cellset;
var newRowContent = '';
var arrRowData = [];
var objRowData = [];
var table = data ? data : [];
var colSpan;
var colValue;
var isHeaderLowestLvl;
var isBody = false;
var firstColumn;
var isLastColumn, isLastRow;
var nextHeader;
var processedRowHeader = false;
var lowestRowLvl = 0;
var rowGroups = [];
var batchSize = null;
var batchStarted = false;
var isColHeader = false, isColHeaderDone = false;
var resultRows = [];
var wrapContent = true;
if (options) {
batchSize = options.hasOwnProperty('batchSize') ? options.batchSize : null;
wrapContent = options.hasOwnProperty('wrapContent') ? options.wrapContent : true;
}
var totalsLists = {};
totalsLists[COLUMNS] = allData.rowTotalsLists;
totalsLists[ROWS] = allData.colTotalsLists;
var scanSums = {};
var scanIndexes = {};
var dirs = [ROWS, COLUMNS];
var hasMeasures = allData.query && allData.query.queryModel && allData.query.queryModel.details
? allData.query.queryModel.details.measures.length
: 0;
if (typeof this._options.htmlObject === 'object' &&
Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE &&
hasMeasures > 0 &&
allData.query.type === 'QUERYMODEL' &&
allData.query.queryModel.details.axis === 'COLUMNS' &&
allData.query.queryModel.details.location === 'BOTTOM') {
var arrColumnTitleTable = getAxisLevelsName(allData, COLUMNS);
var arrDomColumnTitleTable = getDomColumnsLevelsName(this._options.htmlObject);
var colspanColumnTitleTable = getAxisSize(allData, ROWS);
var auxColumnTitleTable = 0;
if (arrColumnTitleTable.length === arrDomColumnTitleTable.length) {
arrColumnTitleTable = arrDomColumnTitleTable;
}
else {
arrColumnTitleTable = _.intersection(arrDomColumnTitleTable, arrColumnTitleTable);
}
}
for (var i = 0; i < dirs.length; i++) {
scanSums[dirs[i]] = new Array();
scanIndexes[dirs[i]] = new Array();
}
// Here we cleaup the empty totals
cleanupTotals(dirs, totalsLists);
if (totalsLists[COLUMNS]) {
for (var i = 0; i < totalsLists[COLUMNS].length; i++) {
scanIndexes[COLUMNS][i] = 0;
scanSums[COLUMNS][i] = totalsLists[COLUMNS][i][scanIndexes[COLUMNS][i]].width;
}
}
var headerFlag=true;// add this flag to solve the bug when same data to merge。 20190423
var cubename = allData.query.cube.name;
for (var row = 0, rowLen = table.length; row < rowLen; row++) {
var rowShifted = row - allData.topOffset;
colSpan = 1;
colValue = "";
isHeaderLowestLvl = false;
isLastColumn = false;
isLastRow = false;
isColHeader = false;
var headerSame = false;
if (totalsLists[ROWS]) {
for (var i = 0; i < totalsLists[ROWS].length; i++) {
scanIndexes[ROWS][i] = 0;
scanSums[ROWS][i] = totalsLists[ROWS][i][scanIndexes[ROWS][i]].width;
}
}
rowWithOnlyEmptyCells = true; //默认行数据为空时不展展示,如果改回来 将此条值置为true即可
if(cubename == "SummaryKPI_2018_ext" ||cubename == "SummaryKPI_2019_ext" ||cubename == "SummaryKPI_2019_Dynamic"){
rowWithOnlyEmptyCells = false; //設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}
rowContent = "<tr>";
var header = null;
if (row === 0) {
rowContent = "<thead>" + rowContent;
}
if (typeof this._options.htmlObject === 'object' &&
Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE &&
hasMeasures > 0 &&
allData.query.type === 'QUERYMODEL' &&
allData.query.queryModel.details.axis === 'COLUMNS' &&
allData.query.queryModel.details.location === 'BOTTOM' &&
auxColumnTitleTable < arrColumnTitleTable.length) {
rowContent += '<th class="row_header" style="text-align: right;" colspan="' + colspanColumnTitleTable + '" title="' + arrColumnTitleTable[auxColumnTitleTable] + '">'
+ (wrapContent ? '<div>' + arrColumnTitleTable[auxColumnTitleTable] + '</div>' : arrColumnTitleTable[auxColumnTitleTable])
+ '</th>';
auxColumnTitleTable += 1;
}
for (var col = 0, colLen = table[row].length; col < colLen; col++) {
var colShifted = col - allData.leftOffset;
header = data[row][col];
if (header.type === "COLUMN_HEADER") {
isColHeader = true;
}
// If the cell is a column header and is null (top left of table)
if (header.type === "COLUMN_HEADER" && header.value === "null" && (firstColumn == null || col < firstColumn)) {
if (((!Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE || (Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE && allData.query.queryModel.details.location !== 'BOTTOM')) || hasMeasures === 0) ||
allData.query.type === 'MDX') {
rowContent += '<th class="all_null"> </th>';
}
} // If the cell is a column header and isn't null (column header of table)
else if (header.type === "COLUMN_HEADER") {
if (firstColumn == null) {
firstColumn = col;
}
if (table[row].length == col+1)
isLastColumn = true;
else
nextHeader = data[row][col+1];
if (isLastColumn) {
// Last column in a row...
if (header.value == "null") {
rowContent += '<th class="col_null"> </th>';
} else {
if (totalsLists[ROWS])
colSpan = totalsLists[ROWS][row + 1][scanIndexes[ROWS][row + 1]].span;
rowContent += '<th class="col" style="text-align: center;" colspan="' + colSpan + '" title="' + header.value + '">'
+ (wrapContent ? '<div rel="' + row + ":" + col +'">' + header.value + '</div>' : header.value)
+ '</th>';
}
} else {
// All the rest...
var groupChange = (col > 1 && row > 1 && !isHeaderLowestLvl && col > firstColumn) ?
data[row-1][col+1].value != data[row-1][col].value || data[row-1][col+1].properties.uniquename != data[row-1][col].properties.uniquename
: false;
var maxColspan = colSpan > 999 ? true : false;
if (header.value != nextHeader.value || nextParentsDiffer(data, row, col) || isHeaderLowestLvl || groupChange || maxColspan) {
if (header.value == "null") {
rowContent += '<th class="col_null" colspan="' + colSpan + '"> </th>';
} else {
if (totalsLists[ROWS])
colSpan = totalsLists[ROWS][row + 1][scanIndexes[ROWS][row + 1]].span;
rowContent += '<th class="col" style="text-align: center;" colspan="' + (colSpan == 0 ? 1 : colSpan) + '" title="' + header.value + '">'
+ (wrapContent ? '<div rel="' + row + ":" + col +'">' + header.value + '</div>' : header.value)
+ '</th>';
}
colSpan = 1;
} else {
colSpan++;
}
}
if (totalsLists[ROWS])
rowContent += genTotalHeaderCells(col - allData.leftOffset + 1, row + 1, scanSums[ROWS], scanIndexes[ROWS], totalsLists[ROWS], wrapContent);
} // If the cell is a row header and is null (grouped row header)
else if (header.type === "ROW_HEADER" && header.value === "null") {
rowContent += '<th class="row_null"> </th>';
} // If the cell is a row header and isn't null (last row header)
else if (header.type === "ROW_HEADER") {
if (lowestRowLvl == col)
isHeaderLowestLvl = true;
else
nextHeader = data[row][col+1];
var previousRow = data[row - 1];
var nextRow = data[row + 1];
// when same set fixed value is false ,It means the same data will not merge。table data will show row by row.20190423
//var same=false;
/*judge the current value and previousRow value,
if equals ,all set comeback,set the headerFlag is true,
we can judge the data as usual. 20190423*/
if(header.value !== previousRow[col].value){
headerFlag =true;
}
/*judge the tableContent include value or not, if include ,
set the headerFlag value is true to avoid repeat datas showed in table.20190423*/
if(tableContent.indexOf(header.value) > -1 ){
headerFlag =true;
}
/*add headerFlag to judge the data is same ,then control the data merge wheather or not.20190423 */
var same = !headerSame && !isHeaderLowestLvl && (col == 0 || !topParentsDiffer(data, row, col)) && header.value === previousRow[col].value && headerFlag;
headerSame = !same;
var sameAsPrevValue = false;
if(Settings.ALLOW_TABLE_DATA_COLLAPSE){
if (row > 0 && row < rowLen - 1) {
if (totalsLists[ROWS] == null || (col <= colLen - totalsLists[ROWS].length - 1)) {
var checkOther = true;
if (totalsLists[COLUMNS] && rowShifted >= 0 && col <= isNextTotalsRow(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent)) {
sameAsPrevValue = true;
checkOther = false;
}
if (checkOther && nextRow[col].value == header.value) {
if (col > 0) {
for (var j = 0; j < col; j++) {
if (nextRow[j].value == data[row][j].value) {
sameAsPrevValue = true;
} else {
sameAsPrevValue = false;
break;
}
}
} else {
sameAsPrevValue = true;
}
}
}
} else if(row > 0 && row == rowLen - 1) {
if (totalsLists[COLUMNS] && rowShifted >= 0 && col <= isNextTotalsRow(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent)) {
sameAsPrevValue = true;
}
}
}
var value = (same ? "<div> </div>" : '<div rel="' + row + ":" + col + '">'
+ (sameAsPrevValue && Settings.ALLOW_TABLE_DATA_COLLAPSE ? '<span class="expander expanded" style="cursor: pointer;">▼</span>' : '' ) + header.value + '</div>');
if (!wrapContent) {
value = (same ? " " : header.value );
}
var tipsy = "";
/* var tipsy = ' original-title="';
if (!same && header.metaproperties) {
for (key in header.metaproperties) {
if (key.substring(0,1) != "$" && key.substring(1,2).toUpperCase() != key.substring(1,2)) {
tipsy += "<b>" + safe_tags_replace(key) + "</b> : " + safe_tags_replace(header.metaproperties[key]) + "<br>";
}
}
}
tipsy += '"';
*/
var cssclass = (same ? "row_null" : "row");
var colspan = 0;
if (!isHeaderLowestLvl && (typeof nextHeader == "undefined" || nextHeader.value === "null")) {
colspan = 1;
var group = header.properties.dimension;
var level = header.properties.level;
var groupWidth = (group in rowGroups ? rowGroups[group].length - rowGroups[group].indexOf(level) : 1);
for (var k = col + 1; colspan < groupWidth && k <= (lowestRowLvl+1) && data[row][k] !== "null"; k++) {
colspan = k - col;
}
col = col + colspan -1;
}
/*when the content is to long ,we will set new line to show it.*/
// eg value: <div rel="3:0">新業務及保單行政部</div>
if(cssclass == "row" && value.length>0){
var startPos = value.indexOf('>'); //find start position of the tag. eg: <div rel="3:0">
var endPos = value.lastIndexOf('<'); //find end position of the tag. eg: </div>
var tmpValue = value.substr( startPos+1 ,endPos-startPos-1); // get the content value. eg: 新業務及保單行政部
//将value值每隔40个字自动加上换行符
//each 40 character add one <br> tag to get new line.
if(tmpValue.length>120){
tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,40)+"<br/>"+tmpValue.substr(80,40)+"<br/>"+tmpValue.substr(120,tmpValue.length-120);
}else if(tmpValue.length>80){
tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,40)+"<br/>"+tmpValue.substr(80,tmpValue.length-80);
}else if(tmpValue.length>40){
tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,tmpValue.length-40);
}
// compared with old value, this value only add <br> tag for show data in table more beautiful.
value = value.substr(0,startPos+1) + tmpValue + value.substr(endPos,value.length-endPos);
}
rowContent += '<th class="' + cssclass + '" ' + (colspan > 0 ? ' colspan="' + colspan + '"' : "") + tipsy + '>' + value + '</th>';
}
else if (header.type === "ROW_HEADER_HEADER") {
var hierName = function(data) {
var hier = data.properties.hierarchy;
var name = hier.replace(/[\[\]]/gi, '').split('.')[1]
? hier.replace(/[\[\]]/gi, '').split('.')[1]
: hier.replace(/[\[\]]/gi, '').split('.')[0];
return name;
};
var arrPosRowData = [];
if (_.contains(arrRowData, header.value)) {
for (var i = 0; i < arrRowData.length; i++) {
if (arrRowData[i] === header.value) {
arrPosRowData.push(i);
}
}
arrPosRowData.push(col);
}
rowContent += '<th class="row_header">' + (wrapContent ? '<div>' + header.value + '</div>' : header.value) + '</th>';
arrRowData.push(header.value);
objRowData.push({
name: header.value,
hierName: hierName(header) + '/' + header.value
});
isHeaderLowestLvl = true;
processedRowHeader = true;
lowestRowLvl = col;
if (header.properties.hasOwnProperty("dimension")) {
var group = header.properties.dimension;
if (!(group in rowGroups)) {
rowGroups[group] = [];
}
rowGroups[group].push(header.properties.level);
}
if (arrPosRowData.length > 0) {
var aux = 0;
rowContent = '<tr>';
if (row === 0) {
rowContent = '<thead>' + rowContent;
}
for (var i = 0; i < objRowData.length; i++) {
if (arrPosRowData[aux] === i) {
newRowContent += '<th class="row_header">' + (wrapContent ? '<div>' + objRowData[i].hierName + '</div>' : objRowData[i].hierName) + '</th>';
aux += 1;
}
else {
newRowContent += '<th class="row_header">' + (wrapContent ? '<div>' + objRowData[i].name + '</div>' : objRowData[i].name) + '</th>';
}
}
rowContent += newRowContent;
}
} // If the cell is a normal data cell
else if (header.type === "DATA_CELL") {
batchStarted = true;
var color = "";
var val = _.isEmpty(header.value) ? Settings.EMPTY_VALUE_CHARACTER : header.value;
var arrow = "";
if (header.properties.hasOwnProperty('image')) {
var img_height = header.properties.hasOwnProperty('image_height') ? " height='" + header.properties.image_height + "'" : "";
var img_width = header.properties.hasOwnProperty('image_width') ? " width='" + header.properties.image_width + "'" : "";
val = "<img " + img_height + " " + img_width + " style='padding-left: 5px' src='" + header.properties.image + "' border='0'>";
}
// Just apply formatting to non-empty cells
if (val !== '-' && val !== '' && header.properties.hasOwnProperty('style')) {
color = " style='background-color: " + header.properties.style + "' ";
}
if (header.properties.hasOwnProperty('link')) {
val = "<a target='__blank' href='" + header.properties.link + "'>" + val + "</a>";
}
if (header.properties.hasOwnProperty('arrow')) {
arrow = "<img height='10' width='10' style='padding-left: 5px' src='./images/arrow-" + header.properties.arrow + ".gif' border='0'>";
}
if (val !== '-' && val !== '') {
rowWithOnlyEmptyCells = false;
}
rowContent += '<td class="data" ' + color + '>'
+ (wrapContent ? '<div class="datadiv '+ setStyleNegativeNumber(header.properties.raw) + '" alt="' + header.properties.raw + '" rel="' + header.properties.position + '">' : "")
+ val + arrow
+ (wrapContent ? '</div>' : '') + '</td>';
if (totalsLists[ROWS])
rowContent += genTotalDataCells(colShifted + 1, rowShifted, scanSums[ROWS], scanIndexes[ROWS], totalsLists, wrapContent);
}
}
rowContent += "</tr>";
// Change it to let hideEmpty true by default
if (options.hideEmpty && header.type === "DATA_CELL" && rowWithOnlyEmptyCells) {
/*when data_cell is null,set the headerFlag is false ,
to fix the problem data merge inccrrect.
*/
headerFlag=false;
rowContent = '';
}
var totals = "";
if (totalsLists[COLUMNS] && rowShifted >= 0) {
totals += genTotalHeaderRowCells(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent);
}
if (batchStarted && batchSize) {
if (row <= batchSize) {
if (!isColHeader && !isColHeaderDone) {
tableContent += "</thead><tbody>";
isColHeaderDone = true;
}
tableContent += rowContent;
if (totals.length > 0) {
tableContent += totals;
}
} else {
resultRows.push(rowContent);
if (totals.length > 0) {
resultRows.push(totals);
}
}
} else {
if (!isColHeader && !isColHeaderDone) {
tableContent += "</thead><tbody>";
isColHeaderDone = true;
}
tableContent += rowContent;
if (totals.length > 0) {
tableContent += totals;
}
}
}
if (options) {
options['batchResult'] = resultRows;
options['hasBatchResult'] = resultRows.length > 0;
}
return "<table>" + tableContent + "</tbody></table>";
};
SaikuTableRenderer.prototype.renderSummary = function(data) {
if (data && data.query) {
var hasSomethingToRender = false;
var measures = data.query.queryModel.details
? data.query.queryModel.details.measures
: [];
var summaryData = {};
for (var i = 0; i < measures.length; i++) {
var m = measures[i];
if (m.aggregators) {
for (var j = 0; j < m.aggregators.length; j++) {
var a = m.aggregators[j];
if (a.indexOf('_') > 0) {
var tokens = a.split('_');
var aggregator = tokens[0];
var axis = tokens[1];
if (aggregator !== 'nil' && aggregator !== 'not') {
hasSomethingToRender = true;
aggregator = aggregator.capitalizeFirstLetter();
if (!(axis in summaryData)) summaryData[axis] = [];
summaryData[axis].push(m.name + ": " + aggregator);
}
}
}
}
}
if (hasSomethingToRender) {
var summary = "<div id='totals_summary'><br/>";
$.each(summaryData, function(key, aggregators) {
summary += "<h3>" + key.capitalizeFirstLetter();
for (var i = 0; i < aggregators.length; i++) {
summary += "<br/> " + aggregators[i];
}
summary += "</h3>";
});
return summary + "</div>";
}
}
return "";
};
String.prototype.capitalizeFirstLetter = function() {
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
}
=====================二次更新=显示空的行数据========start================
最近又遇到了需要不隐藏的空的行数据的报表,笔者想了想用参数去处理此类问题会更好些吧
所以我们就在请求上URL添加参数 showEmptyRows=yes
之前判断具体cubename的部分 用参数来判定!!!
var paramsURI = Saiku.URLParams.paramsURI();
if( paramsURI .showEmptyRows=='yes') {
exModel.queryModel.axes.ROWS.nonEmpty=false;//設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}
视图渲染也根据入参如判断即可
var paramsURI = Saiku.URLParams.paramsURI();
if( paramsURI .showEmptyRows=='yes') {
rowWithOnlyEmptyCells = false; //設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
}
ps: 请求url上记得添加参数 showEmptyRows=yes
感觉用参数会更加方便些,以后有添加其它报表的时候添加参数即可!!!(建议不直接判断cubename哦,哈哈哈哈哈哈 用此方式会更好些~)
=====================二次更新=显示空的行数据=======end=================