Explorar o código

first check in : reports

TonyKang %!s(int64=8) %!d(string=hai) anos
pai
achega
ef5d4a21bf

+ 202 - 0
modules/reports/rpt_component/JpcEx.js

@@ -0,0 +1,202 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcBand = require('./Jpc_Band');
+var JpcFlowTab = require('./Jpc_FlowTab');
+var JpcBillTab = require('./Jpc_BillTab');
+var JpcCrossTab = require('./Jpc_CrossTab');
+var JpcField = require('./Jpc_Field');
+var JpcParam = require('./Jpc_Param');
+var JpcFunc = require('./Jpc_Function');
+var JpcData = require('./Jpc_Data');
+var JpcCommonHelper = require('./helper/Jpc_Helper_Common');
+var JE = require('./Jpc_RTE'); //Important: for self-define function execution purpose
+
+var JpcExSrv = function(){};
+JpcExSrv.prototype.createNew = function(){
+    function private_buildDftItems(rptTpl, dftCollection, propArray, nodeName) {
+        var rst = {};
+        if (dftCollection) {
+            for (var i = 0; i < dftCollection.length; i++) {
+                var item = {};
+                for (var j = 0; j < propArray.length; j++) {
+                    item[propArray[j]] = dftCollection[i][propArray[j]];
+                }
+                rst[dftCollection[i][JV.PROP_ID]] = item;
+            }
+            if (rptTpl && rptTpl[nodeName] && rptTpl[nodeName].length > 0) {
+                for (var i = 0; i < rptTpl[nodeName].length; i++) {
+                    var rptDftItem = rptTpl[nodeName][i];
+                    if (rst[rptDftItem[JV.PROP_ID]] == undefined) {
+                        var item = {};
+                        for (var j = 0; j < propArray.length; j++) {
+                            item[propArray[j]] = rptDftItem[propArray[j]];
+                        }
+                        rst[rptDftItem[JV.PROP_ID]] = item;
+                    }
+                }
+            }
+        }
+        return rst;
+    }
+    function private_buildDftControls(rptTpl, dftControlCollection) {
+        var rst = private_buildDftItems(rptTpl,dftControlCollection, JV.CONTROL_PROPS, JV.NODE_CONTROL_COLLECTION);
+        return rst;
+    }
+    function private_buildDftFonts(rptTpl, dftFontCollection) {
+        var rst = private_buildDftItems(rptTpl,dftFontCollection, JV.FONT_PROPS, JV.NODE_FONT_COLLECTION);
+        return rst;
+    }
+    function private_buildDftStyles(rptTpl, dftStyleCollection) {
+        var rst = {};
+        if (dftStyleCollection) {
+            for (var i = 0; i < dftStyleCollection.length; i++) {
+                var item = {};
+                if (dftStyleCollection[i][JV.PROP_BORDER_STYLE] && dftStyleCollection[i][JV.PROP_BORDER_STYLE].length > 0) {
+                    for (var j = 0; j < dftStyleCollection[i][JV.PROP_BORDER_STYLE].length; j++) {
+                        var borderItem = {};
+                        for (var k = 0; k < JV.BORDER_STYLE_PROPS.length; k++) {
+                            borderItem[JV.BORDER_STYLE_PROPS[k]] = dftStyleCollection[i][JV.PROP_BORDER_STYLE][j][JV.BORDER_STYLE_PROPS[k]];
+                        }
+                        item[dftStyleCollection[i][JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem;
+                    }
+                }
+                rst[dftStyleCollection[i][JV.PROP_ID]] = item;
+            }
+            if (rptTpl && rptTpl[JV.NODE_STYLE_COLLECTION] && rptTpl[JV.NODE_STYLE_COLLECTION].length > 0) {
+                for (var i = 0; i < rptTpl[JV.NODE_STYLE_COLLECTION].length; i++) {
+                    var rptDftItem = rptTpl[JV.NODE_STYLE_COLLECTION][i];
+                    if (rst[rptDftItem[JV.PROP_ID]] == undefined) {
+                        var item = {};
+                        for (var j = 0; j < rptDftItem[JV.PROP_BORDER_STYLE].length; j++) {
+                            var borderItem = {};
+                            for (var k = 0; k < JV.BORDER_STYLE_PROPS.length; k++) {
+                                borderItem[JV.BORDER_STYLE_PROPS[k]] = rptDftItem[JV.PROP_BORDER_STYLE][j][JV.BORDER_STYLE_PROPS[k]];
+                            }
+                            item[rptDftItem[JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem;
+                        }
+                        rst[rptDftItem[JV.PROP_ID]] = item;
+                    }
+                }
+            }
+        }
+        return rst;
+    }
+    var JpcResult = {};
+    //JpcResult.report_title
+    JpcResult.initialize = function(rptTpl) {
+        var me = this;
+        if (rptTpl[JV.NODE_FLOW_INFO]) {
+            me.flowTab = JpcFlowTab.createNew();
+            me.flowTab.initialize();
+        }
+        if (rptTpl[JV.NODE_BILL_INFO]) {
+            me.billTab = JpcBillTab.createNew();
+            me.billTab.initialize();
+        }
+        //var dt1 = new Date();
+        if (rptTpl[JV.NODE_CROSS_INFO]) {
+            me.crossTab = JpcCrossTab.createNew();
+            me.crossTab.initialize();
+        }
+        me.totalPages = 0;
+        me.runTimePageData = {};
+        me.fields = JpcField.createNew(rptTpl);
+        me.params = JpcParam.createNew(rptTpl);
+        me.formulas = JpcFunc.createNew(rptTpl);
+    };
+
+    JpcResult.analyzeData = function(rptTpl, dataObj, defProperties) {
+        var me = this;
+        //1. data object
+        var dataHelper = JpcData.createNew();
+        dataHelper.analyzeData(rptTpl, dataObj);
+        //2. tab object
+        //pre-condition: the data should be sorted in SQL/NoSQL level!
+        //var dt1 = new Date();
+        if (me.flowTab) {
+            me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0));
+        }
+        if (me.crossTab) {
+            me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0));
+        }
+        //var dt2 = new Date();
+        //alert(dt2 - dt1);
+        //3. formulas
+        me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
+        //4. paging
+        me.paging(rptTpl, dataObj, defProperties);
+        //alert('analyzeData was completed!');
+        //for garbage collection:
+        dataHelper = null;
+    };
+    JpcResult.paging = function(rptTpl, dataObj, defProperties) {
+        var me = this;
+        if (me.flowTab) {
+            me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties);
+        } else if (me.crossTab) {
+            me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties);
+        } else if (me.billTab) {
+            //me.totalPages = billTab.paging();
+        }
+    };
+    JpcResult.executeFormulas = function(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) {
+        var me = this;
+        for (var i = 0; i < me.formulas.length; i++) {
+            if (me.formulas[i][JV.PROP_RUN_TYPE] === runType) {
+                var expression = me.formulas[i][JV.PROP_EXPRESSION];
+                if (expression) {
+                    eval(expression);
+                }
+            }
+        }
+    };
+    JpcResult.outputAsSimpleJSONPageArray = function(rptTpl, dataObj, startPage, endPage, defProperties) {
+        var me = this, rst = {};
+        if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) {
+            rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties == null)?null:defProperties.ctrls);
+            rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties == null)?null:defProperties.styles);
+            rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties == null)?null:defProperties.fonts);
+            rst[JV.NODE_PAGE_INFO] = JpcCommonHelper.getPageSize(rptTpl);
+            rst.items = [];
+            var bands = JpcBand.createNew(rptTpl, defProperties);
+            try {
+                for (var page = startPage; page <= endPage; page++) {
+                    me.runTimePageData.currentPage = page;
+                    me.executeFormulas(JV.RUN_TYPE_BEFORE_OUTPUT, rptTpl, dataObj, me);
+                    rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst[JV.NODE_CONTROL_COLLECTION]));
+                }
+                if (bands[JV.BAND_PROP_MERGE_BAND]) {
+                    var mergedBand = {}, band = bands[JV.BAND_PROP_MERGE_BAND];
+                    mergedBand[JV.PROP_LEFT] = band[JV.PROP_LEFT].toFixed(0);
+                    mergedBand[JV.PROP_RIGHT] = band[JV.PROP_RIGHT].toFixed(0);
+                    mergedBand[JV.PROP_TOP] = band[JV.PROP_TOP].toFixed(0);
+                    mergedBand[JV.PROP_BOTTOM] = band[JV.PROP_BOTTOM].toFixed(0);
+                    mergedBand[JV.BAND_PROP_STYLE] = band[JV.BAND_PROP_STYLE];
+                    rst[JV.BAND_PROP_MERGE_BAND] = mergedBand;
+                }
+            } finally {
+                bands = null;
+            }
+        }
+        return rst;
+    };
+    JpcResult.outputAsSimpleJSONPage = function(rptTpl, dataObj, bands, page, controls) {
+        var me = this, rst = null;
+        if (me.totalPages >= page) {
+            rst = {};
+            rst[JV.PROP_PAGE_SEQ] = page;
+            //rst.cells = [];
+            if (me.flowTab) {
+                rst.cells = me.flowTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me);
+            } else if (me.crossTab) {
+                rst.cells = me.crossTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me);
+            } else if (me.billTab) {
+                //
+            }
+        }
+        return rst;
+    };
+    //JpcEx.rte.currentRptObj = JpcResult;
+    return JpcResult;
+}
+
+module.exports = new JpcExSrv();

+ 52 - 0
modules/reports/rpt_component/Jpc_Band.js

@@ -0,0 +1,52 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcCommonHelper = require('./helper/Jpc_Helper_Common');
+var JpcBandHelper = require('./helper/Jpc_Helper_Band');
+
+var JpcBand = {
+    createNew: function(rptTpl, defProperties) {
+        var me = this;
+        var JpcBandResult = {};
+        if (rptTpl[JV.NODE_BAND_COLLECTION]) {
+            for (var i = 0; i < rptTpl[JV.NODE_BAND_COLLECTION].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_BAND_COLLECTION][i], JpcBandResult, rptTpl, defProperties);
+            }
+        }
+        return JpcBandResult;
+    },
+    createSingle: function(bandNode, parentObj, rptTpl, defProperties) {
+        var me = this;
+        if (bandNode && bandNode[JV.BAND_PROP_NAME]) {
+            var item = {Left:0, Right:0, Top:0, Bottom:0};
+            item[JV.BAND_PROP_STYLE] = JpcCommonHelper.getStyle(bandNode[JV.BAND_PROP_STYLE], defProperties.styles, null);
+            item[JV.BAND_PROP_CONTROL] = JpcCommonHelper.getControl(bandNode[JV.BAND_PROP_CONTROL], defProperties.ctrls, null);
+            if (bandNode[JV.BAND_PROP_HEIGHT]) {
+                item[JV.BAND_PROP_HEIGHT] = 1.0 * bandNode[JV.BAND_PROP_HEIGHT];
+            } else {
+                item[JV.BAND_PROP_HEIGHT] = 0.0;
+            }
+            if (bandNode[JV.BAND_PROP_WIDTH]) {
+                item[JV.BAND_PROP_WIDTH] = 1.0 * bandNode[JV.BAND_PROP_WIDTH];
+            } else {
+                item[JV.BAND_PROP_WIDTH] = 0.0;
+            }
+            item[JV.BAND_PROP_DISPLAY_TYPE] = JpcBandHelper.getBandTypeValByString(bandNode[JV.BAND_PROP_DISPLAY_TYPE]);
+            item[JV.BAND_PROP_ALIGNMENT] = JpcCommonHelper.getLayoutAlignment(bandNode[JV.BAND_PROP_ALIGNMENT]);
+            item[JV.PROP_CALCULATION] = JpcCommonHelper.getPosCalculationType(bandNode[JV.PROP_CALCULATION]);
+
+            if (bandNode[JV.BAND_PROP_MERGE_BORDER]) {
+                item[JV.BAND_PROP_MERGE_BORDER] = bandNode[JV.BAND_PROP_MERGE_BORDER];
+            }
+            if (bandNode[JV.BAND_PROP_SUB_BANDS]) {
+                for (var i = 0; i < bandNode[JV.BAND_PROP_SUB_BANDS].length; i++) {
+                    me.createSingle(bandNode[JV.BAND_PROP_SUB_BANDS][i], parentObj, rptTpl, defProperties);
+                }
+            }
+            parentObj[bandNode[JV.BAND_PROP_NAME]] = item;
+            if (item[JV.BAND_PROP_MERGE_BORDER] != null && item[JV.BAND_PROP_MERGE_BORDER] != undefined && item[JV.BAND_PROP_MERGE_BORDER] == 'T') {
+                parentObj[JV.BAND_PROP_MERGE_BAND] = item;
+            }
+        }
+    }
+}
+
+module.exports = JpcBand;

+ 78 - 0
modules/reports/rpt_component/Jpc_BillTab.js

@@ -0,0 +1,78 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcFieldHelper = require('./helper/Jpc_Helper_Field');
+var JpcBandHelper = require('./helper/Jpc_Helper_Band');
+var JpcBand = require('./Jpc_Band');
+var JpcFlowTabHelper = require('./helper/Jpc_Helper_FlowTab');
+var JpcCommonHelper = require('./helper/Jpc_Helper_Common');
+var JpcDiscreteHelper = require('./helper/Jpc_Helper_Discrete');
+var JpcTextHelper = require('./helper/Jpc_Helper_Text');
+var JpcCommonOutputHelper = require('./helper/Jpc_Helper_CommonOutput');
+var JpcAreaHelper = require('./helper/Jpc_Helper_Area');
+
+var JpcBillTabSrv = function(){};
+JpcBillTabSrv.prototype.createNew = function(){
+    var JpcBillTabResult = {};
+    JpcBillTabResult.initialize = function() {
+        var me = this;
+        me.disp_fields_idx = [];
+    };
+    JpcBillTabResult.sorting = function(rptTpl) {
+        var me = this;
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_BILL_INFO][JV.NODE_BILL_CONTENT][JV.PROP_BILL_FIELDS], null, me.disp_fields_idx);
+    };
+    JpcBillTabResult.outputAsSimpleJSONPage = function (rptTpl, dataObj, page, bands, controls, $CURRENT_RPT) {
+        var me = this, rst = [], tabRstLst = [];
+        //1 calculate the band position
+        var pageStatus = [true, false, false, false, false, false, false, false];
+        JpcBandHelper.setBandArea(bands, rptTpl, pageStatus);
+        //2. start to output detail-part
+        var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        //2.1 output content
+        tabRstLst.push(me.outputContent(rptTpl, dataObj, page, bands, unitFactor, controls, pageStatus));
+        //2.2 output discrete
+        tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[JV.NODE_BILL_INFO][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, pageStatus, page - 1, 1, 0, $CURRENT_RPT));
+    }
+    JpcBillTabResult.outputContent = function(rptTpl, dataObj, page, bands, unitFactor, controls, pageStatus) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_BILL_INFO][JV.NODE_BILL_CONTENT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.PROP_BILL_FIELDS];
+                var data_details = dataObj[JV.DATA_MASTER_DATA];
+                for (var i = 0; i < tab_fields.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = null;
+                    if (me.disp_fields_idx[i] != JV.BLANK_FIELD_INDEX) {
+                        data_field = data_details[me.disp_fields_idx[i]];
+                    } else {
+                        data_field = JE.F(tab_field[JV.PROP_FIELD_ID]);
+                        if (data_field) {
+                            data_field = data_field[JV.PROP_AD_HOC_DATA];
+                        }
+                    }
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        var cellItem = JpcCommonOutputHelper.createCommonOutput(tab_field, JpcFieldHelper.getValue(data_field, page - 1), controls);
+                        cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, 1, 0, true, false);
+                        rst.push(cellItem);
+                    }
+                }
+                if (tab[JV.PROP_TEXT]) {
+                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, 1, 0, 1, 0));
+                }
+                if (tab[JV.PROP_TEXTS]) {
+                    for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                        rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, 1, 0, 1, 0));
+                    }
+                }
+                if (tab[JV.NODE_DISCRETE_INFO]) {
+                    rst = rst.concat(JpcDiscreteHelper.outputDiscreteInfo(tab[JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, pageStatus, page - 1, 1, 0));
+                }
+            }
+        }
+        return rst;
+    }
+    return JpcBillTabResult;
+}
+
+module.exports = new JpcBillTabSrv();

+ 548 - 0
modules/reports/rpt_component/Jpc_CrossTab.js

@@ -0,0 +1,548 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcFieldHelper = require('./helper/Jpc_Helper_Field');
+var JpcBandHelper = require('./helper/Jpc_Helper_Band');
+var JpcBand = require('./Jpc_Band');
+var JpcFlowTabHelper = require('./helper/Jpc_Helper_FlowTab');
+var JpcCrossTabHelper = require('./helper/Jpc_Helper_CrossTab');
+var JpcCommonHelper = require('./helper/Jpc_Helper_Common');
+var JpcDiscreteHelper = require('./helper/Jpc_Helper_Discrete');
+var JpcTextHelper = require('./helper/Jpc_Helper_Text');
+var JpcCommonOutputHelper = require('./helper/Jpc_Helper_CommonOutput');
+var JpcAreaHelper = require('./helper/Jpc_Helper_Area');
+
+var JpcCrossTabSrv = function(){};
+JpcCrossTabSrv.prototype.createNew = function(){
+    function private_addTabValue(tabValuedIdxLst, sortedSequence, segIdx, preRec, nextRec, dispSerialIdxLst, sorted_sum_value_Lst, rst_sum_value_Lst) {
+        if (tabValuedIdxLst) {
+            var serial1stTier = null;
+            if (dispSerialIdxLst) serial1stTier = [];
+            var pgseg1stTier = [];
+            var sumVal = [];
+            var sumValL = 1;
+            if (sortedSequence) {
+                var arrDupVals = sortedSequence[segIdx];
+                var arrDupSumVals = null;
+                if (sorted_sum_value_Lst != null) {
+                    arrDupSumVals = sorted_sum_value_Lst[segIdx];
+                    sumValL = arrDupSumVals[0].length;
+                }
+
+                for (var i = 0; i < nextRec; i++) {
+                    if (arrDupVals.length <= preRec + i) {
+                        pgseg1stTier[i] = JV.BLANK_VALUE_INDEX;
+                        sumVal[i] = [];
+                        for (var ei = 0; ei < sumValL; ei++) {
+                            sumVal[i][ei] = null;
+                        }
+                        if (serial1stTier != null) {
+                            serial1stTier[i] = JV.BLANK_VALUE_INDEX;
+                        }
+                        continue;
+                    }
+                    var duplicateValueArr = arrDupVals[preRec + i];
+                    pgseg1stTier[i] = duplicateValueArr[0];
+                    if (arrDupSumVals != null) sumVal[i] = arrDupSumVals[preRec + i];
+
+                    if (serial1stTier != null) {
+                        serial1stTier[i] = preRec + i;
+                    }
+                }
+                tabValuedIdxLst.push(pgseg1stTier);
+                if (dispSerialIdxLst != null) {
+                    dispSerialIdxLst.push(serial1stTier);
+                }
+                if (sorted_sum_value_Lst != null && rst_sum_value_Lst != null) {
+                    rst_sum_value_Lst.push(sumVal);
+                }
+            } else {
+                //should push blank value index rather than null
+                for (var i = 0; i < nextRec; i++) {
+                    pgseg1stTier[i] = JV.BLANK_VALUE_INDEX;
+                    sumVal[i] = null;
+                    if (serial1stTier != null) {
+                        serial1stTier[i] = JV.BLANK_VALUE_INDEX;
+                    }
+                }
+                tabValuedIdxLst.push(pgseg1stTier);
+                if (dispSerialIdxLst != null) {
+                    dispSerialIdxLst.push(serial1stTier);
+                }
+                if (sorted_sum_value_Lst != null && rst_sum_value_Lst != null) {
+                    rst_sum_value_Lst.push(sumVal);
+                }
+            }
+        }
+    }
+    function private_addContentValue(dispValueIdxLst_Content, sortedContentSequence, segIdx, counterRowRec, maxRowRec, counterColRec, maxColRec, page_seg_map, pageIdx) {
+        if (dispValueIdxLst_Content != null) {
+            page_seg_map.push([pageIdx,segIdx]);
+            var arrContents = [];
+            if (sortedContentSequence != null) {
+                var arrAllContent = sortedContentSequence[segIdx];
+                for (var i = 0; i < maxRowRec; i++) {
+                    arrContents.push([]);
+                    for (var j = 0; j < maxColRec; j++) {
+                        if (arrAllContent.length <= counterRowRec + i || arrAllContent[counterRowRec + i].length <= counterColRec + j) {
+                            arrContents[i][j] = JV.BLANK_VALUE_INDEX;
+                        } else {
+                            arrContents[i][j] = arrAllContent[counterRowRec + i][counterColRec + j];
+                        }
+                    }
+                }
+                dispValueIdxLst_Content.push(arrContents);
+            } else {
+                //should push blank value index rather than null
+                for (var i = 0; i < maxRowRec; i++) {
+                    arrContents.push([]);
+                    for (var j = 0; j < maxColRec; j++) {
+                        arrContents[i][j] = JV.BLANK_VALUE_INDEX;
+                    }
+                }
+                dispValueIdxLst_Content.push(arrContents);
+            }
+        }
+    }
+    function private_SortAndOptimize(rptTpl, dataObj, dataSeq, sortTab, rstFieldsIdx) {
+        var result = [];
+        var tab = rptTpl[JV.NODE_CROSS_INFO][sortTab];
+        if (tab) {
+            var sIDX = 0;
+            //1. prepare and sort by tab-field
+            var fields = [];
+            JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, tab[JV.TAB_CROSS_FIELDS], fields, rstFieldsIdx);
+            var data_details = dataObj[JV.DATA_DETAIL_DATA];
+            JpcCrossTabHelper.sortTabFields(fields, rstFieldsIdx, data_details, dataSeq);
+            //2. distinguish sort tab fields value
+            var b1 = false;
+            for (var i = 0; i < dataSeq.length; i++) {
+                sIDX = 0;
+                var segArr = [];
+                if (dataSeq[i].length == 1) {
+                    JpcCrossTabHelper.pushToSeg(segArr, dataSeq, i, 0, 1);
+                } else {
+                    for (var j = 1; j < dataSeq[i].length; j++) {
+                        b1 = false;
+                        for (var k = 0; k < rstFieldsIdx.length; k++) {
+                            if (data_details[rstFieldsIdx[k]][dataSeq[i][j - 1]] != data_details[rstFieldsIdx[k]][dataSeq[i][j]]) {
+                                b1 = true;
+                                break;
+                            }
+                        }
+                        if (b1) {
+                            JpcCrossTabHelper.pushToSeg(segArr, dataSeq, i, sIDX, j);
+                            sIDX = j;
+                            if (j == dataSeq[i].length - 1) {
+                                JpcCrossTabHelper.pushToSeg(segArr, dataSeq, i, j, dataSeq[i].length);
+                            }
+                        } else if (j == dataSeq[i].length - 1) {
+                            JpcCrossTabHelper.pushToSeg(segArr, dataSeq, i, sIDX, dataSeq[i].length);
+                        }
+                    }
+                }
+                if (segArr.length > 0) result.push(segArr);
+            }
+        }
+        return result;
+    }
+    function private_SortForDisplayContent(rptTpl, rowSeq, colSeq, rstFieldsIdx){
+        var result = [];
+        var tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT];
+        if (tab) {
+            JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, tab[JV.TAB_CROSS_FIELDS], null, rstFieldsIdx);
+        }
+        for (var i = 0; i < rowSeq.length; i++) {
+            var rl = rowSeq[i], cl = colSeq[i];
+            var ds = [];
+            //1. initialize to blank value index
+            for (var j = 0; j < rl.length; j++) {
+                ds.push([]);
+                for (var k = 0; k < cl.length; k++) {
+                    ds[j].push(JV.BLANK_VALUE_INDEX);
+                }
+            }
+            //2. then fill up the right index
+            for (var j = 0; j < rl.length; j++) {
+                var ra = rl[j];
+                for (var k = 0; k < ra.length; k++) {
+                    var colIdx = JpcCrossTabHelper.getColIDX(cl, ra[k]);
+                    if (colIdx >= 0) {
+                        ds[j][colIdx] = ra[k];
+                    }
+                }
+            }
+            result.push(ds);
+        }
+        return result;
+    }
+
+    var JpcCrossTabResult = {};
+    JpcCrossTabResult.initialize = function() {
+        var me = this;
+        me.dispValueIdxLst_Row = [];
+        me.dispValueIdxLst_Col = [];
+        me.dispValueIdxLst_Content = [];
+        me.dispSerialIdxLst_Row = [];
+        me.col_sum_fields_idx = [];
+        me.col_sum_fields_value_total = [];
+        me.dispSumValueLst_Col = [];
+        me.page_seg_map = [];
+        me.row_fields_idx = [];
+        me.col_fields_idx = [];
+        me.content_fields_idx = [];
+        me.row_extension_fields_idx = [];
+        me.row_sum_extension_fields_idx = [];
+        me.crsOrient = JV.PAGE_ORIENTATION_V_FIRST;
+        me.pageStatusLst = [];
+    };
+    JpcCrossTabResult.sorting = function(rptTpl, dataObj, dataSeq) {
+        var me = this;
+        //IMPORTANT: the data should be sorted in SQL/NoSQL level!
+        me.sortedRowSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_ROW, me.row_fields_idx);
+        me.sortedColSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_COL, me.col_fields_idx);
+        me.sortedContentSequence = private_SortForDisplayContent(rptTpl, me.sortedRowSequence, me.sortedColSequence, me.content_fields_idx);
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL_SUM][JV.TAB_CROSS_FIELDS], null, me.col_sum_fields_idx);
+        //pre-sum the data(for col sum display)
+        var data_details = dataObj[JV.DATA_DETAIL_DATA],
+            data_fields = [];
+        for (var i = 0; i < me.col_sum_fields_idx.length; i++) {
+            var data_field = data_details[me.col_sum_fields_idx[i]];
+            data_fields.push(data_field);
+        }
+        for (var i = 0; i < me.sortedRowSequence.length; i++) { //seg level
+            if (me.sortedRowSequence[i].length > 0) {
+                me.col_sum_fields_value_total.push([]);
+                for (var j = 0; j < me.sortedRowSequence[i].length; j++) {
+                    var rowGrandTotal = [];
+                    for (var di = 0; di < data_fields.length; di++) {
+                        rowGrandTotal.push(0.0);
+                        for (var k = 0; k < me.sortedRowSequence[i][j].length; k++) {
+                            //3. start to sum
+                            rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(data_fields[di], me.sortedRowSequence[i][j][k]);
+                        }
+                    }
+                    me.col_sum_fields_value_total[i].push(rowGrandTotal);
+                }
+            }
+
+        }
+    };
+    JpcCrossTabResult.preSetupPages = function(rptTpl, defProperties) {
+        var rst = 0, me = this;
+        //1. original initialize
+        var maxRowRec = 1, maxColRec = 1, counterRowRec = 0, counterColRec = 0, pageIdx = 0, segCnt = me.sortedContentSequence.length;
+        var pageStatus = [true, true, false, true, false, false, false, false];
+        //2. calculate the page info one by one
+        var bands = JpcBand.createNew(rptTpl, defProperties);
+        function private_resetBandArea() {
+            JpcBandHelper.setBandArea(bands, rptTpl, pageStatus);
+            maxRowRec = JpcCrossTabHelper.getMaxRowsPerPage(bands, rptTpl);
+            maxColRec = JpcCrossTabHelper.getMaxColsPerPage(bands, rptTpl);
+        }
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_EXT][JV.TAB_CROSS_FIELDS], null, me.row_extension_fields_idx);
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT][JV.TAB_CROSS_FIELDS], null, me.row_sum_extension_fields_idx);
+        for (var segIdx = 0; segIdx < segCnt; segIdx++) {
+            //2.1. seg level initialize
+            private_resetBandArea();
+            var orgMaxRowRec = maxRowRec, orgMaxColRec = maxColRec;
+            var rowSplitCnt = Math.ceil(1.0 * me.sortedRowSequence[segIdx].length / maxRowRec);
+            var colSplitCnt = Math.ceil(1.0 * me.sortedColSequence[segIdx].length / maxColRec);
+            pageStatus[JV.STATUS_CROSS_ROW_END] = true;
+            private_resetBandArea();
+            var hasAdHocRow = !JpcCrossTabHelper.chkTabEnd(JV.NODE_CROSS_ROW_SUM, rptTpl, bands, me.sortedRowSequence, segIdx, (rowSplitCnt - 1) * orgMaxRowRec, maxRowRec);
+            if (hasAdHocRow) {
+                hasAdHocRow = !JpcCrossTabHelper.chkTabEnd(JV.NODE_CROSS_ROW_EXT, rptTpl, bands, me.sortedRowSequence, segIdx, (rowSplitCnt - 1) * orgMaxRowRec, maxRowRec);
+            }
+            pageStatus[JV.STATUS_CROSS_ROW_END] = false;
+            pageStatus[JV.STATUS_CROSS_COL_END] = true;
+            private_resetBandArea();
+            var hasAdHocCol = !JpcCrossTabHelper.chkTabEnd(JV.NODE_CROSS_COL_SUM, rptTpl, bands, me.sortedColSequence, segIdx, (colSplitCnt - 1) * orgMaxColRec, maxColRec);
+            pageStatus[JV.STATUS_CROSS_COL_END] = false;
+            private_resetBandArea();
+            if (hasAdHocRow) rowSplitCnt++;
+            if (hasAdHocCol) colSplitCnt++;
+            //2.2
+            for (var colIdx = 0; colIdx < colSplitCnt; colIdx++) {
+                pageStatus[JV.STATUS_CROSS_COL_END] = colIdx == (colSplitCnt - 1)?true:false;
+                private_resetBandArea();
+                counterColRec = orgMaxColRec * colIdx;
+                var currentSortedContentSequence = me.sortedContentSequence;
+                var currentSortedColSequence = me.sortedColSequence;
+                if (hasAdHocCol && colIdx == (colSplitCnt - 1)) {
+                    currentSortedColSequence = null;
+                    currentSortedContentSequence = null;
+                    counterColRec = 0;
+                }
+                for (var rowIdx = 0; rowIdx < rowSplitCnt; rowIdx++) {
+                    pageStatus[JV.STATUS_CROSS_ROW_END] = rowIdx == (rowSplitCnt - 1)?true:false;
+                    private_resetBandArea();
+                    me.pageStatusLst.push(pageStatus.slice(0));
+                    pageIdx++;
+                    counterRowRec = orgMaxRowRec * rowIdx;
+                    var currentSortedRowSequence = me.sortedRowSequence;
+                    if (hasAdHocRow && rowIdx == (rowSplitCnt - 1)) {
+                        currentSortedRowSequence = null;
+                        currentSortedContentSequence = null;
+                        counterRowRec = 0;
+                    }
+                    private_addTabValue(me.dispValueIdxLst_Row, currentSortedRowSequence, segIdx, counterRowRec, maxRowRec, me.dispSerialIdxLst_Row, me.col_sum_fields_value_total, me.dispSumValueLst_Col);
+                    private_addTabValue(me.dispValueIdxLst_Col, currentSortedColSequence, segIdx, counterColRec, maxColRec, null, null, null);
+                    private_addContentValue(me.dispValueIdxLst_Content, currentSortedContentSequence, segIdx, counterRowRec, maxRowRec, counterColRec, maxColRec, me.page_seg_map, pageIdx);
+                }
+            }
+            JpcCrossTabHelper.initialPageStatus(pageStatus);
+        }
+        bands = null;
+        //3. set pageSeq and return the result
+        rst = pageIdx;
+        return rst;
+    };
+    JpcCrossTabResult.outputAsSimpleJSONPage = function(rptTpl, dataObj, page, bands, controls, $CURRENT_RPT) {
+        var me = this, rst = [], tabRstLst = [];
+        var segIdx = JpcCommonHelper.getSegIdxByPageIdx(page, me.page_seg_map);
+        //1 calculate the band position
+        JpcBandHelper.setBandArea(bands, rptTpl, me.pageStatusLst[page - 1]);
+        //2. start to output detail-part
+        var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        //2.1 Row-Tab
+        tabRstLst.push(me.outputRowTab(rptTpl, dataObj, page, bands, unitFactor, controls));
+        //2.2 Col-Tab
+        tabRstLst.push(me.outputColTab(rptTpl, dataObj, page, bands, unitFactor, controls));
+        //2.3 Content-Tab
+        tabRstLst.push(me.outputContent(rptTpl, dataObj, page, bands, unitFactor, controls));
+        //2.4 Sum-Tab Row
+        //2.4 Sum-tab Col
+        tabRstLst.push(me.outputTabSum(rptTpl, dataObj, page, bands, unitFactor, JV.NODE_CROSS_COL_SUM, controls));
+        //2.x row tab ext
+        tabRstLst.push(me.outputTabExt(rptTpl, dataObj, page, bands, unitFactor, controls));
+        tabRstLst.push(me.outputSumTabExt(rptTpl, dataObj, page, bands, unitFactor, segIdx, controls));
+        //2.5 Discrete
+        tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, 1, 0, $CURRENT_RPT));
+        for (var i = 0; i < tabRstLst.length; i++) {
+            rst = rst.concat(tabRstLst[i]);
+            tabRstLst[i] = null;
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputRowTab = function(rptTpl, dataObj, page, bands, unitFactor, controls) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS];
+                var data_details = dataObj[JV.DATA_DETAIL_DATA];
+                var valuesIdx = me.dispValueIdxLst_Row[page - 1];
+                var serialsIdx = me.dispSerialIdxLst_Row[page - 1];
+                for (var i = 0; i < me.row_fields_idx.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = data_details[me.row_fields_idx[i]];
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        var rows = valuesIdx.length;
+                        for (var rowIdx = 0; rowIdx < rows; rowIdx++) {
+                            rst.push(me.outputTabField(band, tab_field, data_field, valuesIdx[rowIdx], serialsIdx[rowIdx], rows, rowIdx, 1, 0, unitFactor, true, controls));
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputColTab = function(rptTpl, dataObj, page, bands, unitFactor, controls) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS];
+                var data_details = dataObj[JV.DATA_DETAIL_DATA];
+                var valuesIdx = me.dispValueIdxLst_Col[page - 1];
+                for (var i = 0; i < me.col_fields_idx.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = data_details[me.col_fields_idx[i]];
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        var cols = valuesIdx.length;
+                        for (var colIdx = 0; colIdx < cols; colIdx++) {
+                            rst.push(me.outputTabField(band, tab_field, data_field, valuesIdx[colIdx], -1, 1, 0, cols, colIdx, unitFactor, false, controls));
+                            //2. output texts
+                            if (tab[JV.PROP_TEXT]) {
+                                rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, cols, colIdx, 1, 0));
+                            }
+                            if (tab[JV.PROP_TEXTS]) {
+                                for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, cols, colIdx, 1, 0));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputContent = function (rptTpl, dataObj, page, bands, unitFactor, controls) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS];
+                var data_details = dataObj[JV.DATA_DETAIL_DATA];
+                var contentValuesIdx = me.dispValueIdxLst_Content[page - 1];
+                for (var i = 0; i < tab_fields.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = data_details[me.content_fields_idx[i]];
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        var rows = contentValuesIdx.length;
+                        for (var rowIdx = 0; rowIdx < rows; rowIdx++) {
+                            var cols = contentValuesIdx[rowIdx].length;
+                            for (var colIdx = 0; colIdx < cols; colIdx++) {
+                                rst.push(me.outputTabField(band, tab_field, data_field, contentValuesIdx[rowIdx][colIdx], -1, rows, rowIdx, cols, colIdx, unitFactor, true, controls));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputTabSum = function (rptTpl, dataObj, page, bands, unitFactor, tabNodeName, controls) {
+        var me = this, rst = [],
+            tab = rptTpl[JV.NODE_CROSS_INFO][tabNodeName],
+            band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS];
+                for (var i = 0; i < me.dispSumValueLst_Col[page - 1].length; i++) {
+                    if (me.dispSumValueLst_Col[page - 1][i] != null) {
+                        for (var j = 0; j < me.dispSumValueLst_Col[page - 1][i].length; j++) {
+                            var tab_field = tab_fields[j];
+                            var val = me.dispSumValueLst_Col[page - 1][i][j];
+                            var cellItem = JpcCommonOutputHelper.createCommonOutput(tab_field, val, controls);
+                            cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, me.dispSumValueLst_Col[page - 1].length, i, 1, 0, 1, 0, true, false);
+                            rst.push(cellItem);
+                        }
+                    } else {
+                        var sumL = 1;
+                        for (var si = 0; si < me.dispSumValueLst_Col.length; si++) {
+                            if (me.dispSumValueLst_Col[si][0] != null) {
+                                sumL = me.dispSumValueLst_Col[si][0].length;
+                                break;
+                            }
+                        }
+                        for (var j = 0; j < sumL; j++) {
+                            var tab_field = tab_fields[j];
+                            var val = null;
+                            var cellItem = JpcCommonOutputHelper.createCommonOutput(tab_field, val, controls);
+                            cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, me.dispSumValueLst_Col[page - 1].length, i, 1, 0, 1, 0, true, false);
+                            rst.push(cellItem);
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputTabExt = function (rptTpl, dataObj, page, bands, unitFactor, controls) {
+        var me = this, rst = [],
+            tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_EXT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS],
+                    data_details = dataObj[JV.DATA_DETAIL_DATA],
+                    valuesIdx = me.dispValueIdxLst_Col[page - 1];
+                for (var i = 0; i < me.row_extension_fields_idx.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = data_details[me.row_extension_fields_idx[i]];
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        var cols = valuesIdx.length;
+                        for (var colIdx = 0; colIdx < cols; colIdx++) {
+                            rst.push(me.outputTabField(band, tab_field, data_field, valuesIdx[colIdx], -1, 1, 0, cols, colIdx, unitFactor, false, controls));
+                            //2. output texts if has
+                            if (tab[JV.PROP_TEXT]) {
+                                rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, cols, colIdx, 1, 0));
+                            }
+                            if (tab[JV.PROP_TEXTS]) {
+                                for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, cols, colIdx, 1, 0));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputSumTabExt = function (rptTpl, dataObj, page, bands, unitFactor, segIdx, controls) {
+        var me = this, rst = [],
+            tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true && pageStatus[JV.STATUS_CROSS_ROW_END] === true) {
+                var tab_fields = tab[JV.TAB_CROSS_FIELDS],
+                    data_details = dataObj[JV.DATA_DETAIL_DATA],
+                    data_fields = [];
+                for (var i = 0; i < me.row_sum_extension_fields_idx.length; i++) {
+                    var data_field = data_details[me.row_sum_extension_fields_idx[i]];
+                    data_fields.push(data_field);
+                }
+                //2. initialize grand total value
+                var rowGrandTotal = [];
+                for (var di = 0; di < data_fields.length; di++) {
+                    rowGrandTotal[di] = 0.0;
+                    //3. start to sum
+                    for (var i = 0; i < me.sortedColSequence[segIdx].length; i++) {
+                        //me.sortedColSequence[segIdx][i][0] //this is the data field value index!
+                        rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(data_fields[di], me.sortedColSequence[segIdx][i][0]);
+                    }
+                }
+                //4. output
+                for (var di = 0; di < tab_fields.length; di++) {
+                    var tab_field = tab_fields[di];
+                    if (!tab_field[JV.PROP_HIDDEN]) {
+                        var val = rowGrandTotal[di];
+                        var cellItem = JpcCommonOutputHelper.createCommonOutput(tab_field, val, controls);
+                        cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, 1, 0, false, false);
+                        rst.push(cellItem);
+                    }
+                }
+                //output texts if has
+                if (tab[JV.PROP_TEXT]) {
+                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, 1, 0, 1, 0));
+                }
+                if (tab[JV.PROP_TEXTS]) {
+                    for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                        rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, 1, 0, 1, 0));
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcCrossTabResult.outputTabField = function (band, tab_field, data_field, valueIdx, serialIdx, rows, rowIdx, cols, colIdx, unitFactor, isRow, controls) {
+        var me = this, rst = null;
+        if (isRow == true && tab_field[JV.PROP_IS_SERIAL] && tab_field[JV.PROP_IS_SERIAL] == true) {
+            if (serialIdx >= 0) rst = JpcCommonOutputHelper.createCommonOutput(tab_field, serialIdx + 1)
+            else rst = JpcCommonOutputHelper.createCommonOutput(tab_field, "", controls);
+        } else {
+            rst = JpcCommonOutputHelper.createCommonOutput(tab_field, JpcFieldHelper.getValue(data_field, valueIdx), controls);
+        }
+        //position
+        if (isRow == true) {
+            rst[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, rows, rowIdx, cols, colIdx, 1, 0, true, false);
+        } else {
+            rst[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, rows, rowIdx, cols, colIdx, 1, 0, false, false);
+        }
+        return rst;
+    }
+    return JpcCrossTabResult;
+}
+
+module.exports = new JpcCrossTabSrv();

+ 98 - 0
modules/reports/rpt_component/Jpc_Data.js

@@ -0,0 +1,98 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcData = {
+    createNew: function() {
+        var JpcDataRst = {};
+        JpcDataRst.dataSeq = [];
+        JpcDataRst.analyzeData = function(rptTpl, dataObj) {
+            var me = this;
+            if ((rptTpl) && (dataObj)) {
+                //1. get ID fields
+                var masterIDs = [];
+                for (var i = 0; i < rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS].length; i++) {
+                    var mstFieldObj = rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS][i];
+                    if ((mstFieldObj[JV.PROP_IS_ID]) && (mstFieldObj[JV.PROP_IS_ID] === 'T')) {
+                        masterIDs.push({"idx": i, "seq": mstFieldObj[JV.PROP_ID_SEQ]});
+                    }
+                }
+                var detailIDs = [];
+                for (var i = 0; i < rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length; i++) {
+                    var dtlFieldObj = rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS][i];
+                    if ((dtlFieldObj[JV.PROP_IS_ID]) && (dtlFieldObj[JV.PROP_IS_ID] === 'T')) {
+                        detailIDs.push({"idx": i, "seq": dtlFieldObj[JV.PROP_ID_SEQ]});
+                    }
+                }
+                //2. sort the ID fields
+                if (masterIDs.length > 1) {
+                    masterIDs.sort(function(a, b) {
+                        return 1*a["seq"] - 1*b["seq"];
+                    })
+                }
+                if (detailIDs.length > 1) {
+                    detailIDs.sort(function(a, b) {
+                        return 1*a["seq"] - 1*b["seq"];
+                    })
+                }
+                //3. prepare data sequence
+                if (masterIDs.length > 0) {
+                    var mst_dt_len = 0, dtl_dt_len = 0, mst_fields = [];
+                    for (var i = 0; i < masterIDs.length; i++) {
+                        mst_fields.push(dataObj[JV.DATA_MASTER_DATA][masterIDs[i]["idx"]]);
+                        mst_dt_len = dataObj[JV.DATA_MASTER_DATA][masterIDs[i]["idx"]].length;
+                    }
+                    var dtl_fields = [];
+                    for (var i = 0; i < detailIDs.length; i++) {
+                        dtl_fields.push(dataObj[JV.DATA_DETAIL_DATA][detailIDs[i]["idx"]]);
+                        dtl_dt_len = dataObj[JV.DATA_DETAIL_DATA][detailIDs[i]["idx"]].length;
+                    }
+                    var sIdx = 0;
+                    var isEqual = true;
+                    for (var i = 0; i < mst_dt_len; i++) {
+                        me.dataSeq.push([]);
+                        //then compare the master/detail ID-field value
+                        for (var j = sIdx; j < dtl_dt_len; j++) {
+                            isEqual = true;
+                            for (var k = 0; k < mst_fields.length; k++) {
+                                if (!(mst_fields[k][i] === dtl_fields[k][j])) {
+                                    isEqual = false;
+                                    break;
+                                }
+                            }
+                            if (isEqual) {
+                                me.dataSeq[i].push(j);
+                            } else {
+                                sIdx = j;
+                                //below logic is for the data robustness purpose, to avoid those strange record(detail level) which could not match even one of the master record!
+                                if (i < mst_dt_len - 1 && j < dtl_dt_len - 1) {
+                                    for (var j1 = j; j1 < dtl_dt_len; j1++) {
+                                        isEqual = true;
+                                        for (var k = 0; k < mst_fields.length; k++) {
+                                            if (!(mst_fields[k][i + 1] === dtl_fields[k][j1])) {
+                                                isEqual = false;
+                                                break;
+                                            }
+                                        }
+                                        if (isEqual) {
+                                            sIdx = j1;
+                                            break;
+                                        }
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    }
+                } else { //if no master data
+                    var field = dataObj[JV.DATA_DETAIL_DATA][0];
+                    me.dataSeq = [[]];
+                    for (var i = 0; i < field.length; i++) {
+                        me.dataSeq[0].push(i);
+                    }
+                }
+            }
+            //alert(3);
+        };
+        return JpcDataRst;
+    }
+}
+
+module.exports = JpcData;

+ 47 - 0
modules/reports/rpt_component/Jpc_Field.js

@@ -0,0 +1,47 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcField = {
+    createNew: function(rptTpl) {
+        var JpcFieldResult = {};
+        var me = this;
+        JpcFieldResult[JV.NODE_DISCRETE_FIELDS] = {};
+        if (rptTpl[JV.NODE_FIELD_MAP] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS][i], JpcFieldResult[JV.NODE_DISCRETE_FIELDS], rptTpl, JV.DATA_DISCRETE_DATA, i);
+            }
+        }
+        JpcFieldResult[JV.NODE_MASTER_FIELDS] = {};
+        if (rptTpl[JV.NODE_FIELD_MAP] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS][i], JpcFieldResult[JV.NODE_MASTER_FIELDS], rptTpl, JV.DATA_MASTER_DATA, i);
+            }
+        }
+        JpcFieldResult[JV.NODE_DETAIL_FIELDS] = {};
+        if (rptTpl[JV.NODE_FIELD_MAP] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS][i], JpcFieldResult[JV.NODE_DETAIL_FIELDS], rptTpl, JV.DATA_DETAIL_DATA, i);
+            }
+        }
+        JpcFieldResult[JV.NODE_NO_MAPPING_FIELDS] = {};
+        if (rptTpl[JV.NODE_NO_MAPPING_FIELDS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_NO_MAPPING_FIELDS].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_NO_MAPPING_FIELDS][i], JpcFieldResult[JV.NODE_NO_MAPPING_FIELDS], rptTpl, "NA", JV.BLANK_FIELD_INDEX);
+            }
+        }
+        //
+        return JpcFieldResult;
+    },
+    createSingle: function(fieldNode, parentObj, rptTpl, dataNodeName, sequence) {
+        var me = this;
+        if (fieldNode && fieldNode[JV.PROP_ID]) {
+            var item = {};
+            item[JV.PROP_ID] = fieldNode[JV.PROP_ID];
+            item[JV.PROP_NAME] = fieldNode[JV.PROP_NAME];
+            item[JV.PROP_DATA_TYPE] = fieldNode[JV.PROP_DATA_TYPE];
+            item.DataNodeName = dataNodeName;
+            item.DataSeq = sequence;
+            parentObj[JV.PROP_ID + "_" + fieldNode[JV.PROP_ID]] = item;
+        }
+    }
+}
+
+module.exports = JpcField;

+ 229 - 0
modules/reports/rpt_component/Jpc_FlowTab.js

@@ -0,0 +1,229 @@
+var JV = require('./Jpc_ValueDefine');
+var JE = require('./Jpc_RTE');
+var JpcFieldHelper = require('./helper/Jpc_Helper_Field');
+var JpcBandHelper = require('./helper/Jpc_Helper_Band');
+var JpcBand = require('./Jpc_Band');
+var JpcFlowTabHelper = require('./helper/Jpc_Helper_FlowTab');
+var JpcCommonHelper = require('./helper/Jpc_Helper_Common');
+var JpcDiscreteHelper = require('./helper/Jpc_Helper_Discrete');
+var JpcTextHelper = require('./helper/Jpc_Helper_Text');
+var JpcCommonOutputHelper = require('./helper/Jpc_Helper_CommonOutput');
+var JpcAreaHelper = require('./helper/Jpc_Helper_Area');
+
+var JpcFlowTabSrv = function(){};
+JpcFlowTabSrv.prototype.createNew = function(){
+    function private_addPageValue(ValuedIdxLst, sortedSequence, preRec, nextRec,page_seg_map, segIdx, pageIdx) {
+        var vIdx = [];
+        for (var vi = 0; vi < nextRec; vi++) {
+            if (sortedSequence.length > preRec + vi) {
+                vIdx.push(sortedSequence[preRec + vi]);
+            } else {
+                vIdx.push(JV.BLANK_VALUE_INDEX);
+            }
+        }
+        page_seg_map.push([pageIdx, segIdx]);
+        ValuedIdxLst.push(vIdx);
+    }
+    var JpcFlowTabResult = {};
+    JpcFlowTabResult.initialize = function() {
+        var me = this;
+        me.segments = [];
+        me.dispValueIdxLst = [];
+        me.page_seg_map = [];
+        me.disp_fields_idx = [];
+        me.seg_sum_fields_idx = [];
+        me.seg_sum_tab_fields = [];
+        me.page_sum_fields_idx = [];
+        me.group_fields_idx = [];
+        me.pageStatusLst = [];
+        me.groupSumValLst = [];
+        me.segSumValLst = [];
+        me.multiCols = 1;
+    };
+    JpcFlowTabResult.sorting = function(rptTpl, dataObj, dataSeq) {
+        var me = this;
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM][JV.PROP_SUM_FIELDS], me.seg_sum_tab_fields, me.seg_sum_fields_idx);
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM][JV.PROP_SUM_FIELDS], null, me.page_sum_fields_idx);
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_FIELDS], null, me.group_fields_idx);
+        for (var si = 0; si < dataSeq.length; si++) {
+            me.segments.push(dataSeq[si].slice(0));
+        }
+        //pre-sum the data(for seg sum display)
+        var data_details = dataObj[JV.DATA_DETAIL_DATA],
+            data_fields = [];
+        for (var i = 0; i < me.seg_sum_fields_idx.length; i++) {
+            var data_field = data_details[me.seg_sum_fields_idx[i]];
+            data_fields.push(data_field);
+        }
+        for (var i = 0; i < me.segments.length; i++) { //seg level
+            if (me.segments[i].length > 0) {
+                var rowGrandTotal = [];
+                for (var di = 0; di < data_fields.length; di++) {
+                    rowGrandTotal.push(0.0);
+                    for (var j = 0; j < me.segments[i].length; j++) {
+                        //3. start to sum
+                        rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(data_fields[di], me.segments[i][j]);
+                    }
+                }
+                me.segSumValLst.push(rowGrandTotal);
+            }
+
+        }
+    };
+    JpcFlowTabResult.preSetupPages = function (rptTpl, dataOjb, defProperties) {
+        var rst = 0, me = this, counterRowRec = 0, maxRowRec = 1, pageIdx = 0;
+        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS], null, me.disp_fields_idx);
+        var bands = JpcBand.createNew(rptTpl, defProperties);
+        var pageStatus = [true, true, false, false, false, false, false, false];
+        if (rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN]) {
+            me.multiCols = 1 * rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN];
+        }
+        function private_resetBandArea() {
+            JpcBandHelper.setBandArea(bands, rptTpl, pageStatus);
+            maxRowRec = JpcFlowTabHelper.getMaxRowsPerPage(bands, rptTpl);
+        }
+        for (var segIdx = 0; segIdx < me.segments.length; segIdx++) {
+            private_resetBandArea();
+            var orgMaxRowRec = maxRowRec;
+            var rowSplitCnt = Math.ceil(1.0 * me.segments[segIdx].length / orgMaxRowRec);
+            pageStatus[JV.STATUS_SEGMENT_END] = true;
+            private_resetBandArea();
+            var hasAdHocRow = !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, me.segments, segIdx, (rowSplitCnt - 1) * orgMaxRowRec, maxRowRec);
+            if (hasAdHocRow) rowSplitCnt++;
+            if (rowSplitCnt % me.multiCols > 0) {
+                rowSplitCnt++
+            }
+            for (var rowIdx = 0; rowIdx < rowSplitCnt; rowIdx++) {
+                pageStatus[JV.STATUS_SEGMENT_END] = rowIdx == (rowSplitCnt - 1)?true:false;
+                if (pageIdx > 0) pageStatus[JV.STATUS_REPORT_START] = false;
+                private_resetBandArea();
+                me.pageStatusLst.push(pageStatus.slice(0));
+                pageIdx++;
+                counterRowRec = orgMaxRowRec * rowIdx;
+                private_addPageValue(me.dispValueIdxLst, me.segments[segIdx], counterRowRec, maxRowRec,me.page_seg_map, segIdx, pageIdx);
+            }
+            pageStatus[JV.STATUS_SEGMENT_END] = false;
+            pageStatus[JV.STATUS_REPORT_START] = false;
+        }
+        rst = Math.ceil(1.0 * pageIdx / me.multiCols);
+        return rst;
+    };
+    JpcFlowTabResult.outputAsSimpleJSONPage = function (rptTpl, dataObj, page, bands, controls, $CURRENT_RPT) {
+        var me = this, rst = [], tabRstLst = [];
+        var segIdx = JpcCommonHelper.getSegIdxByPageIdx(page, me.page_seg_map);
+        //1 calculate the band position
+        JpcBandHelper.setBandArea(bands, rptTpl, me.pageStatusLst[page - 1]);
+        //2. start to output detail-part
+        var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        for (var pi = 0; pi < me.multiCols; pi++) {
+            var actualPage = (page - 1) * me.multiCols + pi + 1;
+            //2.1 Content-Tab
+            tabRstLst.push(me.outputContent(rptTpl, dataObj, actualPage, bands, unitFactor, controls, pi));
+            //2.2 Column tab
+            tabRstLst.push(me.outputColumn(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls, pi));
+            //2.3 Sum Seg
+            tabRstLst.push(me.outputSegSum(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls));
+            //2.4 Sum Page
+            //2.5 Discrete
+            if (pi == 0) {
+                tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[actualPage - 1], segIdx, 1, pi, $CURRENT_RPT));
+            }
+        }
+        for (var i = 0; i < tabRstLst.length; i++) {
+            rst = rst.concat(tabRstLst[i]);
+            tabRstLst[i] = null;
+        }
+        return rst;
+    };
+    JpcFlowTabResult.outputContent = function(rptTpl, dataObj, page, bands, unitFactor, controls, multiColIdx, $CURRENT_RPT) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = tab[JV.PROP_FLOW_FIELDS];
+                var data_details = dataObj[JV.DATA_DETAIL_DATA];
+                var contentValuesIdx = me.dispValueIdxLst[page - 1];
+                for (var i = 0; i < tab_fields.length; i++) {
+                    var tab_field = tab_fields[i];
+                    var data_field = null;
+                    if (me.disp_fields_idx[i] != JV.BLANK_FIELD_INDEX) {
+                        data_field = data_details[me.disp_fields_idx[i]];
+                    } else {
+                        data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                        if (data_field) {
+                            data_field = data_field[JV.PROP_AD_HOC_DATA];
+                        }
+                    }
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        for (var rowIdx = 0; rowIdx < contentValuesIdx.length; rowIdx++) {
+                            rst.push(me.outputTabField(band, tab_field, data_field, contentValuesIdx[rowIdx], -1, contentValuesIdx.length, rowIdx, 1, 0, unitFactor, true, controls, multiColIdx));
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    };
+    JpcFlowTabResult.outputColumn = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, multiColIdx) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_COLUMN];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                if (tab[JV.PROP_TEXT]) {
+                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, 1, 0, me.multiCols, multiColIdx));
+                }
+                if (tab[JV.PROP_TEXTS]) {
+                    for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                        rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, 1, 0, me.multiCols, multiColIdx));
+                    }
+                }
+                if (tab[JV.NODE_DISCRETE_INFO]) {
+                    rst = rst.concat(JpcDiscreteHelper.outputDiscreteInfo(tab[JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, me.multiCols, multiColIdx));
+                }
+            }
+        }
+        return rst;
+    };
+    JpcFlowTabResult.outputSegSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls) {
+        var me = this, rst = [];
+        var tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var pageStatus = me.pageStatusLst[page - 1];
+            if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                var tab_fields = me.seg_sum_tab_fields;
+                for (var i = 0; i < tab_fields.length; i++) {
+                    var cellItem = JpcCommonOutputHelper.createCommonOutput(tab_fields[i], me.segSumValLst[segIdx][i], controls);
+                    cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_fields[i][JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, me.multiCols, 0, true, false);
+                    rst.push(cellItem);
+                }
+                if (tab[JV.PROP_TEXT]) {
+                    rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXT], band, unitFactor, 1, 0, 1, 0, me.multiCols, 0));
+                }
+                if (tab[JV.PROP_TEXTS]) {
+                    for (var j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                        rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, 1, 0, 1, 0, me.multiCols, 0));
+                    }
+                }
+                if (tab[JV.NODE_DISCRETE_INFO]) {
+                    rst = rst.concat(JpcDiscreteHelper.outputDiscreteInfo(tab[JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, me.multiCols, 0));
+                }
+            }
+        }
+        return rst;
+    };
+    JpcFlowTabResult.outputTabField = function (band, tab_field, data_field, valueIdx, serialIdx, rows, rowIdx, cols, colIdx, unitFactor, isRow, controls, multiColIdx) {
+        var me = this, rst = null;
+        rst = JpcCommonOutputHelper.createCommonOutput(tab_field, JpcFieldHelper.getValue(data_field, valueIdx), controls);
+        rst[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, unitFactor, rows, rowIdx, cols, colIdx, me.multiCols, multiColIdx, true, false);
+        return rst;
+    }
+
+    return JpcFlowTabResult;
+}
+
+module.exports = new JpcFlowTabSrv();

+ 18 - 0
modules/reports/rpt_component/Jpc_Function.js

@@ -0,0 +1,18 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcFunc = {
+    createNew: function (rptTpl) {
+        var me = this;
+        var rst = [];
+        if (rptTpl[JV.NODE_FORMULAS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_FORMULAS].length; i++) {
+                var item = {};
+                item[JV.PROP_RUN_TYPE] = rptTpl[JV.NODE_FORMULAS][i][JV.PROP_RUN_TYPE];
+                item[JV.PROP_EXPRESSION] = rptTpl[JV.NODE_FORMULAS][i][JV.PROP_EXPRESSION];
+                rst.push(item);
+            }
+        }
+        return rst;
+    }
+};
+
+module.exports = JpcFunc;

+ 27 - 0
modules/reports/rpt_component/Jpc_Param.js

@@ -0,0 +1,27 @@
+var JV = require('./Jpc_ValueDefine');
+var JpcParam = {
+    createNew: function(rptTpl) {
+        var JpcParamResult = {};
+        var me = this;
+        if (rptTpl[JV.NODE_DISCRETE_PARAMS]) {
+            for (var i = 0; i < rptTpl[JV.NODE_DISCRETE_PARAMS].length; i++) {
+                me.createSingle(rptTpl[JV.NODE_DISCRETE_PARAMS][i], JpcParamResult, rptTpl, i);
+            }
+        }
+        return JpcParamResult;
+    },
+    createSingle: function(paramNode, parentObj, rptTpl, sequence) {
+        var me = this;
+        if (paramNode && paramNode[JV.PROP_ID]) {
+            var item = {};
+            item[JV.PROP_ID] = paramNode[JV.PROP_ID];
+            item[JV.PROP_NAME] = paramNode[JV.PROP_NAME];
+            item[JV.PROP_DATA_TYPE] = paramNode[JV.PROP_DATA_TYPE];
+            if (paramNode[JV.PROP_DFT_VALUE]) item[JV.PROP_DFT_VALUE] = paramNode[JV.PROP_DFT_VALUE];
+            item.DataSeq = sequence;
+            parentObj[JV.PROP_ID + "_" + paramNode[JV.PROP_ID]] = item;
+        }
+    }
+}
+
+module.exports = JpcParam;

+ 47 - 0
modules/reports/rpt_component/Jpc_RTE.js

@@ -0,0 +1,47 @@
+/**
+ * Created by Tony on 2016/12/28.
+ */
+
+var JV = require('./Jpc_ValueDefine');
+var JE = {
+    F: function(fID, $CURRENT_RPT) {
+        var rst = null;
+        if ($CURRENT_RPT && ($CURRENT_RPT.fields[JV.NODE_DETAIL_FIELDS][JV.PROP_ID + "_" + fID])) {
+            rst = $CURRENT_RPT.fields[JV.NODE_DETAIL_FIELDS][JV.PROP_ID + "_" + fID];
+        } else if ($CURRENT_RPT && ($CURRENT_RPT.fields[JV.NODE_MASTER_FIELDS][JV.PROP_ID + "_" + fID])) {
+            rst = $CURRENT_RPT.fields[JV.NODE_MASTER_FIELDS][JV.PROP_ID + "_" + fID];
+        } else if ($CURRENT_RPT && ($CURRENT_RPT.fields[JV.NODE_DISCRETE_FIELDS][JV.PROP_ID + "_" + fID])) {
+            rst = $CURRENT_RPT.fields[JV.NODE_DISCRETE_FIELDS][JV.PROP_ID + "_" + fID];
+        } else if ($CURRENT_RPT && ($CURRENT_RPT.fields[JV.NODE_NO_MAPPING_FIELDS][JV.PROP_ID + "_" + fID])) {
+            rst = $CURRENT_RPT.fields[JV.NODE_NO_MAPPING_FIELDS][JV.PROP_ID + "_" + fID];
+        } else {
+            rst = {msg: "the Field-ID is not valid, no result could be found!"};
+        }
+        return rst;
+    },
+    P: function(pID, $CURRENT_RPT) {
+        var rst = null;
+        if ($CURRENT_RPT && ($CURRENT_RPT.params[JV.PROP_ID + "_" + pID])) {
+            rst = $CURRENT_RPT.params[JV.PROP_ID + "_" + pID];
+        } else {
+            rst = {msg: "the Param-ID is not valid, no result was found!"};
+        }
+        return rst;
+    },
+    getCurrentPage: function ($CURRENT_RPT) {
+        var rst = 0;
+        if ($CURRENT_RPT) {
+            rst = $CURRENT_RPT.runTimePageData.currentPage;
+        }
+        return rst;
+    },
+    getTotalPage: function ($CURRENT_RPT) {
+        var rst = 0;
+        if ($CURRENT_RPT) {
+            rst = $CURRENT_RPT.totalPages;
+        }
+        return rst;
+    }
+}
+
+module.exports = JE;

+ 197 - 0
modules/reports/rpt_component/Jpc_ValueDefine.js

@@ -0,0 +1,197 @@
+var JV = {
+    NODE_CROSS_INFO: "交叉表_信息",
+    NODE_CROSS_ROW: "交叉行",
+    NODE_CROSS_COL: "交叉列",
+    NODE_CROSS_CONTENT: "交叉数据",
+    NODE_CROSS_ROW_SUM: "交叉行合计",
+    NODE_CROSS_COL_SUM: "交叉列合计",
+    NODE_CROSS_ROW_EXT: "交叉行拓展",
+    NODE_CROSS_ROW_SUM_EXT: "交叉行拓展合计",
+    NODE_FIELD_MAP: "指标_数据_映射",
+    NODE_DISCRETE_FIELDS: "离散指标_集合",
+    NODE_NO_MAPPING_FIELDS: "无映射离散指标_集合",
+    NODE_DISCRETE_PARAMS: "离散参数_集合",
+    NODE_MASTER_FIELDS: "主数据指标_集合",
+    NODE_DETAIL_FIELDS: "从数据指标_集合",
+    NODE_BAND_COLLECTION: "布局框_集合",
+    NODE_FORMULAS: "计算式_集合",
+    NODE_DISCRETE_INFO: "离散信息",
+    NODE_BILL_INFO: "账单式表_信息",
+    NODE_BILL_CONTENT : "账单式表_数据",
+    NODE_FLOW_INFO: "流水式表_信息",
+    NODE_FLOW_GROUP: "流水式表_分组信息",
+    NODE_FLOW_SEG_SUM: "流水式表_段统计信息",
+    NODE_FLOW_PAGE_SUM: "流水式表_页统计信息",
+    NODE_FLOW_COLUMN : "流水式表_列",
+    NODE_FLOW_CONTENT : "流水式表_数据",
+    PROP_MULTI_COLUMN: "多列显示数量",
+
+    NODE_MAIN_INFO: "主信息",
+    NODE_PAGE_INFO: "打印页面_信息",
+    NODE_MARGINS: "页边距",
+
+    NODE_FONT_COLLECTION: "font_collection",
+    NODE_STYLE_COLLECTION: "style_collection",
+    NODE_CONTROL_COLLECTION: "control_collection",
+
+    PROP_ID: "ID",
+    PROP_AD_HOC_DATA: "data_field",
+    PROP_CMN_HEIGHT: "CommonHeight",
+    PROP_CMN_WIDTH: "CommonWidth",
+    PROP_BAND_NAME: "BandName",
+    PROP_UNITS: "单位",
+    PROP_PAGE_SIZE: "页规格",
+    PROP_ORIENTATION: "方向",
+    PROP_LEFT: "Left",
+    PROP_RIGHT: "Right",
+    PROP_TOP: "Top",
+    PROP_BOTTOM: "Bottom",
+    PROP_DATA_TYPE: "DataType",
+    PROP_NAME: "Name",
+    PROP_DFT_VALUE: "Default_Value",
+    PROP_EXPRESSION: "expression",
+    PROP_RUN_TYPE: "run_type",
+    PROP_BORDER_STYLE: "border_style",
+    PROP_POSITION: "Position",
+    PROP_HIDDEN: "Hidden",
+    PROP_IS_SERIAL: "isSerial",
+    PROP_FONT: "font",
+    PROP_CONTROL: "control",
+    PROP_STYLE: "style",
+    PROP_VALUE: "Value",
+    PROP_LABEL: "Label",
+    PROP_AREA: "area",
+    PROP_DISCRETE_FIELDS: "discrete_field_s",
+    PROP_FLOW_FIELDS: "flow_field_s",
+    PROP_BILL_FIELDS: "bill_field_s",
+    PROP_GROUP_FIELDS: "group_field_s",
+    PROP_SUM_FIELDS: "sum_field_s",
+    PROP_TEXTS: "text_s",
+    PROP_TEXT: "text",
+    PROP_FIELD_ID: "FieldID",
+    PROP_PARAM_ID: "ParamID",
+    PROP_PREFIX: "Prefix",
+    PROP_SUFFIX: "Suffix",
+    PROP_FORMAT: "Format",
+
+    PROP_SHOW_ZERO: "ShowZero",
+    PROP_EXTENSION_TYPE: "ExtType",
+
+    PROP_CALCULATION: "CalculationType",
+    PROP_H_CALCULATION: "H_CalculationType",
+    PROP_V_CALCULATION: "V_CalculationType",
+
+    IDX_LEFT: 0,
+    IDX_TOP: 1,
+    IDX_RIGHT: 2,
+    IDX_BOTTOM: 3,
+
+    BAND_PROP_NAME: "Name",
+    BAND_PROP_MERGE_BAND: "MergeBand",
+    BAND_PROP_STYLE: "style",
+    BAND_PROP_CONTROL: "control",
+    BAND_PROP_HEIGHT: "Height",
+    BAND_PROP_WIDTH: "Width",
+    BAND_PROP_DISPLAY_TYPE: "DisplayType",
+    BAND_PROP_ALIGNMENT: "Alignment",
+    BAND_PROP_MERGE_BORDER: "MergeBorder",
+    BAND_PROP_SUB_BANDS: "band_s",
+
+    MEASUREMENT: {
+        PIXEL:["像素点", "象素点", "PIXEL"],
+        CM: ["厘米", "CM"],
+        INCH: ["英寸","INCH"]
+    },
+
+    PROP_IS_ID: "isID",
+    PROP_ID_SEQ: "IDSeq",
+
+    TAB_CROSS_FIELDS: "cross_field_s",
+    TAB_FIELD_PROP_SORT: "Sort",
+    TAB_FIELD_PROP_SORT_VAL_NOSORT: "no_sort",
+    TAB_FIELD_PROP_SORT_VAL_ASC: "ascend",
+    TAB_FIELD_PROP_SORT_VAL_DESC: "descend",
+
+    DATA_DISCRETE_DATA: "discrete_data",
+    DATA_MASTER_DATA: "master_data",
+    DATA_DETAIL_DATA: "detail_data",
+
+    BLANK_FIELD_INDEX: -10,
+    BLANK_VALUE_INDEX: -100,
+    BLANK_PAGE_VALUE_INDEX: -200,
+
+    RUN_TYPE_BEFORE_PAGING: "before_paging",
+    RUN_TYPE_BEFORE_OUTPUT: "before_output",
+
+    PAGE_STATUS: ["EveryPage","FirstPage", "LastPage", "SegmentStart", "SegmentEnd", "Group", "CrossRowEnd", "CrossColEnd"],
+
+    CONTROL_PROPS: ["Shrink", "ShowZero", "Horizon", "Vertical", "Wrap"],
+    BORDER_STYLE_PROPS: ["LineWeight", "DashStyle", "Color"],
+    PROP_LINE_WEIGHT: "LineWeight",
+    PROP_DASH_STYLE: "DashStyle",
+    PROP_COLOR: "Color",
+    FONT_PROPS: ["Name", "FontHeight", "FontColor", "FontBold", "FontItalic", "FontUnderline", "FontStrikeOut", "FontAngle"],
+
+    STATUS_NORMAL: 0,
+    STATUS_REPORT_START: 1,
+    STATUS_REPORT_END: 2,
+    STATUS_SEGMENT_START: 3,
+    STATUS_SEGMENT_END: 4,
+    STATUS_GROUP: 5,
+    STATUS_CROSS_ROW_END: 6,
+    STATUS_CROSS_COL_END: 7,
+
+    LAYOUT: ["Top","Bottom", "Left", "Right", "Fulfill"],
+    LAYOUT_TOP: 0,
+    LAYOUT_BOTTOM: 1,
+    LAYOUT_LEFT: 2,
+    LAYOUT_RIGHT: 3,
+    LAYOUT_FULFILL: 4,
+
+    OUTPUT_ALIGN: {
+        H: ["Left", "Center", "Right"],
+        V: ["Top", "Center", "Bottom"]
+    },
+
+    CAL_TYPE:["percentage","abstract"],
+    CAL_TYPE_PERCENTAGE: 0,
+    CAL_TYPE_ABSTRACT: 1,
+
+    PAGE_ORIENTATION_V_FIRST: 0,
+    PAGE_ORIENTATION_H_FIRST: 1,
+
+    ORIENTATION_PORTRAIT: "PORTRAIT",
+    ORIENTATION_LANDSCAPE: "LANDSCAPE",
+    ORIENTATION_PORTRAIT_CHN: "纵",
+    ORIENTATION_LANDSCAPE_CHN: "横",
+    SIZE_A3: [11.69, 16.54],
+    SIZE_A4: [8.27, 11.69],
+    SIZE_A5: [5.83, 8.27],
+    SIZE_B5: [6.93, 9.84],
+    SIZE_LETTER: [8.5, 11.0],
+    SIZE_LEGAL: [8.5, 14.0],
+    SIZE_16K: [7.75, 10.75],
+    SIZE_EXECUTIVE: [7.25, 10.5],
+
+    OUTPUT_OFFSET: [2,1,2,3],
+    OFFSET_IDX_LEFT: 0,
+    OFFSET_IDX_RIGHT: 1,
+    OFFSET_IDX_TOP: 2,
+    OFFSET_IDX_BOTTOM: 3,
+
+    PROP_PAGE_SEQ: "page_seq",
+
+    PAGE_SELF_DEFINE: "自定义",
+
+    PAGES_SIZE_STR: ["A3", "A4", "A5", "B5", "LETTER", "LEGAL", "EXECUTIVE", "16K"],
+    PAGES_SIZE: [[11.69, 16.54], [8.27, 11.69], [5.83, 8.27], [6.93, 9.84], [8.5, 11.0], [8.5, 14.0], [7.25, 10.5], [7.25, 10.5]],
+
+    HUNDRED_PERCENT : 100.0,
+
+    VERTICAL_ANGLE: "90",
+    ANTI_VERTICAL_ANGLE: "-90",
+
+    LAST_DEF: ""
+}
+
+module.exports = JV;

+ 58 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Area.js

@@ -0,0 +1,58 @@
+var JV = require('../Jpc_ValueDefine');
+
+var JpcAreaHelper = {
+    outputArea: function(areaNode, band, unitFactor, rowAmount, rowIdx, colAmount, colIdx, multipleDispCol, multipleColIdx,syncHeight, syncWidth) {
+        var rst = {}, maxMultiColumns = 3;
+        if (multipleDispCol > 0 && multipleDispCol <= maxMultiColumns) {
+            //1. calculate left/right
+            var areaWidth = 1.0 * (band[JV.PROP_RIGHT] - band[JV.PROP_LEFT]) / multipleDispCol;
+            areaWidth = areaWidth / colAmount;
+            var innerLeft = 0.0, innerRight = areaWidth;
+            switch (areaNode[JV.PROP_H_CALCULATION]) {
+                case JV.CAL_TYPE[JV.CAL_TYPE_PERCENTAGE] :
+                    innerLeft = (1.0 * areaNode[JV.PROP_LEFT] * areaWidth / JV.HUNDRED_PERCENT);
+                    innerRight = (1.0 * areaNode[JV.PROP_RIGHT] * areaWidth / JV.HUNDRED_PERCENT) ;
+                    break;
+                case JV.CAL_TYPE[JV.CAL_TYPE_ABSTRACT] :
+                    innerLeft = 1.0 * areaNode[JV.PROP_LEFT] * unitFactor;
+                    innerRight = 1.0 * areaNode[JV.PROP_RIGHT] * unitFactor ;
+                    break;
+            }
+            //2. calculate top/bottom
+            var  areaHeight = 1.0 * (band[JV.PROP_BOTTOM] - band[JV.PROP_TOP]);
+            areaHeight = areaHeight / rowAmount;
+            var innerTop = 0.0, innerBottom = areaHeight;
+            switch (areaNode[JV.PROP_V_CALCULATION]) {
+                case JV.CAL_TYPE[JV.CAL_TYPE_PERCENTAGE] :
+                    innerTop = (1.0 * areaNode[JV.PROP_TOP] * areaHeight / JV.HUNDRED_PERCENT);
+                    innerBottom = (1.0 * areaNode[JV.PROP_BOTTOM] * areaHeight / JV.HUNDRED_PERCENT) ;
+                    break;
+                case JV.CAL_TYPE[JV.CAL_TYPE_ABSTRACT] :
+                    innerTop = 1.0 * areaNode[JV.PROP_TOP] * unitFactor;
+                    innerBottom = 1.0 * areaNode[JV.PROP_BOTTOM] * unitFactor ;
+                    break;
+            }
+            //
+            var rstLeft = 0.0, rstRight = 0.0, rstTop = 0.0, rstBottom = 0.0;
+            if (syncHeight) {
+                rstBottom = Math.round(1.0 * band[JV.PROP_TOP] + areaHeight * (rowIdx + 1) + innerTop);
+            } else {
+                rstBottom = Math.round(1.0 * band[JV.PROP_TOP] + areaHeight * rowIdx + innerBottom);
+            }
+            if (syncWidth) {
+                rstRight = Math.round(1.0 * band[JV.PROP_LEFT] + areaWidth * (colIdx + 1) + innerLeft + multipleColIdx * areaWidth);
+            } else {
+                rstRight = Math.round(1.0 * band[JV.PROP_LEFT] + areaWidth * colIdx + innerRight + multipleColIdx * areaWidth);
+            }
+            rstLeft = Math.round(1.0 * band[JV.PROP_LEFT] + areaWidth * colIdx + innerLeft + multipleColIdx * areaWidth);
+            rstTop = Math.round(1.0 * band[JV.PROP_TOP] + areaHeight * rowIdx + innerTop);
+            rst[JV.PROP_LEFT] = rstLeft;
+            rst[JV.PROP_RIGHT] = rstRight;
+            rst[JV.PROP_TOP] = rstTop;
+            rst[JV.PROP_BOTTOM] = rstBottom;
+        }
+        return rst;
+    }
+};
+
+module.exports = JpcAreaHelper;

+ 74 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Band.js

@@ -0,0 +1,74 @@
+var JV = require('../Jpc_ValueDefine');
+var JpcCommonHelper = require('./Jpc_Helper_Common');
+
+var JpcBandHelper = {
+    getBandTypeValByString: function(bandType) {
+        var rst = JV.PAGE_STATUS.indexOf(bandType);
+        if (rst < 0) rst = JV.STATUS_NORMAL;
+        return rst;
+    },
+    setBandArea: function(bands, rptTpl, pageStatus) {
+        var me = this;
+        if (rptTpl[JV.NODE_BAND_COLLECTION]) {
+            var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+            var orgArea = JpcCommonHelper.getReportArea(rptTpl, unitFactor);
+            for (var i = 0; i < rptTpl[JV.NODE_BAND_COLLECTION].length; i++) {
+                me.setBandPos(bands, rptTpl[JV.NODE_BAND_COLLECTION][i], orgArea, unitFactor, pageStatus);
+            }
+        }
+    },
+    setBandPos: function(bands, bandNode, orgArea, unitFactor, pageStatus) {
+        var me = this, band = bands[bandNode[JV.BAND_PROP_NAME]];
+        //1. initialize
+        band[JV.PROP_LEFT] = orgArea[JV.IDX_LEFT];
+        band[JV.PROP_TOP] = orgArea[JV.IDX_TOP];
+        band[JV.PROP_RIGHT] = orgArea[JV.IDX_RIGHT];
+        band[JV.PROP_BOTTOM] = orgArea[JV.IDX_BOTTOM];
+        //2. set this band
+        if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+            switch (band[JV.BAND_PROP_ALIGNMENT]) {
+                case JV.LAYOUT_TOP:
+                    if (band[JV.PROP_CALCULATION] == JV.CAL_TYPE_ABSTRACT) {
+                        band.Bottom = band.Top + unitFactor * band[JV.BAND_PROP_HEIGHT];
+                    } else {
+                        band.Bottom = band.Top + (band.Bottom - band.Top) * band[JV.BAND_PROP_HEIGHT] / 100;
+                    }
+                    orgArea[JV.IDX_TOP] = band.Bottom;
+                    break;
+                case JV.LAYOUT_BOTTOM:
+                    if (band[JV.PROP_CALCULATION] == JV.CAL_TYPE_ABSTRACT) {
+                        band.Top = band.Bottom - unitFactor * band[JV.BAND_PROP_HEIGHT];
+                    } else {
+                        band.Top = band.Bottom - (band.Bottom - band.Top) * band[JV.BAND_PROP_HEIGHT] / 100;
+                    }
+                    orgArea[JV.IDX_BOTTOM] = band.Top;
+                    break;
+                case JV.LAYOUT_LEFT:
+                    if (band[JV.PROP_CALCULATION] == JV.CAL_TYPE_ABSTRACT) {
+                        band.Right = band.Left + unitFactor * band[JV.BAND_PROP_WIDTH];
+                    } else {
+                        band.Right = band.Left + (band.Right - band.Left) * band[JV.BAND_PROP_WIDTH] / 100;
+                    }
+                    orgArea[JV.IDX_LEFT] = band.Right;
+                    break;
+                case JV.LAYOUT_RIGHT:
+                    if (band[JV.PROP_CALCULATION] == JV.CAL_TYPE_ABSTRACT) {
+                        band.Left = band.Right - unitFactor * band[JV.BAND_PROP_WIDTH];
+                    } else {
+                        band.Left = band.Right - (band.Right - band.Left) * band[JV.BAND_PROP_WIDTH] / 100;
+                    }
+                    orgArea[JV.IDX_RIGHT] = band.Left;
+                    break;
+            }
+            //3. set sub-bands
+            if (bandNode[JV.BAND_PROP_SUB_BANDS]) {
+                var bandArea = [band.Left, band.Top, band.Right, band.Bottom];
+                for (var i = 0; i < bandNode[JV.BAND_PROP_SUB_BANDS].length; i++) {
+                    me.setBandPos(bands, bandNode[JV.BAND_PROP_SUB_BANDS][i], bandArea, unitFactor, pageStatus);
+                }
+            }
+        }
+    }
+};
+
+module.exports = JpcBandHelper;

+ 148 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Common.js

@@ -0,0 +1,148 @@
+var JV = require('../Jpc_ValueDefine');
+
+var JpcCommonHelper = {
+    commonConstant: {},
+    getResultByID: function (KeyID, collectionList) {
+        var rst = null;
+        if (KeyID) {
+            for (var i = 0; i < collectionList.length; i++) {
+                var collection = collectionList[i];
+                if (collection && collection instanceof Array) {
+                    for (var j = 0; j < collection.length; j++) {
+                        if (collection[j][JV.PROP_ID] === KeyID) {
+                            rst = collection[j];
+                            break;
+                        }
+                    }
+                    if (rst) break;
+                }
+            }
+        }
+        return rst;
+    },
+    getFont: function(fontName, dftFonts, rptTpl) {
+        var me = this, rst = null, list = [];
+        if (rptTpl) list.push(rptTpl[JV.NODE_FONT_COLLECTION]);
+        list.push(dftFonts);
+        rst = me.getResultByID(fontName, list);
+        return rst;
+    },
+    getStyle: function(styleName, dftStyles, rptTpl) {
+        var me = this, rst = null, list = [];
+        if (rptTpl) list.push(rptTpl[JV.NODE_STYLE_COLLECTION]);
+        list.push(dftStyles);
+        rst = me.getResultByID(styleName, list);
+        return rst;
+    },
+    getControl: function(controlName, dftControls, rptTpl) {
+        var me = this, rst = null, list = [];
+        if (rptTpl) list.push(rptTpl[JV.NODE_CONTROL_COLLECTION]);
+        list.push(dftControls);
+        rst = me.getResultByID(controlName, list);
+        return rst;
+    },
+    getLayoutAlignment: function(alignStr) {
+        var rst = JV.LAYOUT.indexOf(alignStr);
+        if (rst < 0) rst = JV.LAYOUT_FULFILL;
+        return rst;
+    },
+    getPosCalculationType: function (typeStr) {
+        var rst = JV.CAL_TYPE.indexOf(typeStr);
+        if (rst < 0) rst = JV.CAL_TYPE_ABSTRACT;
+        return rst;
+    },
+    getScreenDPI: function() {
+        var me = this, arrDPI = [];
+        if (!me.commonConstant.resolution) {
+            arrDPI = [96,96];
+            me.commonConstant.resolution = arrDPI;
+        } else {
+            arrDPI = me.commonConstant.resolution;
+        }
+        return arrDPI;
+    },
+    getScreenDPI_bk: function() {
+        var me = this, arrDPI = [];
+        if (!me.commonConstant.resolution) {
+            if (window) {
+                if (window.screen.deviceXDPI != undefined) {
+                    arrDPI.push(window.screen.deviceXDPI);
+                    arrDPI.push(window.screen.deviceYDPI);
+                } else {
+                    var tmpNode = document.createElement("DIV");
+                    tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
+                    document.body.appendChild(tmpNode);
+                    arrDPI.push(parseInt(tmpNode.offsetWidth));
+                    arrDPI.push(parseInt(tmpNode.offsetHeight));
+                    tmpNode.parentNode.removeChild(tmpNode);
+                }
+            } else {
+                arrDPI = [96,96];
+            }
+            me.commonConstant.resolution = arrDPI;
+        } else {
+            arrDPI = me.commonConstant.resolution;
+        }
+        return arrDPI;
+    },
+    getUnitFactor: function(rptTpl) {
+        var me = this;
+        return me.translateUnit(rptTpl[JV.NODE_MAIN_INFO][JV.PROP_UNITS]);
+    },
+    translateUnit: function(unitStr) {
+        var me = this, rst = 1.0;
+        if (unitStr) {
+            var resolution = me.getScreenDPI();
+            if (JV.MEASUREMENT.PIXEL.indexOf(unitStr) >= 0) {
+                rst = 1.0;
+            } else if (JV.MEASUREMENT.CM.indexOf(unitStr) >= 0) {
+                rst = 1.0 * resolution[0] / 2.54;
+            } else if (JV.MEASUREMENT.INCH.indexOf(unitStr) >= 0) {
+                rst = 1.0 * resolution[0];
+            }
+        }
+        return rst;
+    },
+    getPageSize: function (rptTpl) {
+        var me = this, size = null;
+        var sizeStr = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE];
+        var sizeIdx = JV.PAGES_SIZE_STR.indexOf(sizeStr);
+        if (sizeIdx >= 0) {
+            size = JV.PAGES_SIZE[sizeIdx].slice(0);
+        } else if (sizeStr === JV.PAGE_SELF_DEFINE) {
+            //
+        } else {
+            size = JV.SIZE_A4.slice(0);
+        }
+        var page_orientation = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_ORIENTATION];
+        if (page_orientation === JV.ORIENTATION_LANDSCAPE || page_orientation === JV.ORIENTATION_LANDSCAPE_CHN) {
+            //swap x,y
+            var tmp = size[0];
+            size[0] = size[1];
+            size[1] = tmp;
+        }
+        return size;
+    },
+    getReportArea: function(rptTpl, unitFactor) {
+        var me = this, resolution = me.getScreenDPI(), rst = [], size = me.getPageSize(rptTpl);
+        size[0] = resolution[0] * size[0];
+        size[1] = resolution[0] * size[1];
+        rst.push(unitFactor * rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_LEFT]);
+        rst.push(unitFactor * rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_TOP]);
+        rst.push(size[0] - unitFactor * rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_RIGHT]);
+        rst.push(size[1] - unitFactor * rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM]);
+        return rst;
+    },
+    getSegIdxByPageIdx: function(page, page_seg_map) {
+        var rst = -1;
+        for (var pIdx = 0; pIdx < page_seg_map.length; pIdx++) {
+            if (page_seg_map[pIdx][0] == page) {
+                rst = page_seg_map[pIdx][1];
+                break;
+            }
+        }
+        return rst;
+    }
+};
+
+module.exports = JpcCommonHelper;

+ 60 - 0
modules/reports/rpt_component/helper/Jpc_Helper_CommonOutput.js

@@ -0,0 +1,60 @@
+var JV = require('../Jpc_ValueDefine');
+var JpcFieldHelper = require('./Jpc_Helper_Field');
+
+var JpcCommonOutputHelper = {
+    createCommonOutputWithoutDecorate: function (node, value, controls) {
+        var rst = {};
+        //1. font/style/control
+        rst[JV.PROP_FONT] = node[[JV.PROP_FONT]];
+        rst[JV.PROP_CONTROL] = node[[JV.PROP_CONTROL]];
+        rst[JV.PROP_STYLE] = node[[JV.PROP_STYLE]];
+        //2. value
+        rst[JV.PROP_VALUE] = value;
+        if (node[JV.PROP_FORMAT]) {
+            if (!(isNaN(parseFloat(rst[JV.PROP_VALUE])))) {
+                var dotIdx = node[JV.PROP_FORMAT].indexOf(".");
+                if (dotIdx >= 0) {
+                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(node[JV.PROP_FORMAT].length - dotIdx - 1);
+                } else {
+                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(0);
+                }
+            }
+        }
+        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] != null) {
+            rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX] + rst[JV.PROP_VALUE];
+        }
+        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] != null) {
+            rst[JV.PROP_VALUE] = rst[JV.PROP_VALUE] + node[JV.PROP_SUFFIX];
+        }
+        return rst;
+    },
+    createCommonOutput: function (node, value, controls) {
+        var rst = {};
+        //1. font/style/control
+        rst[JV.PROP_FONT] = node[[JV.PROP_FONT]];
+        rst[JV.PROP_CONTROL] = node[[JV.PROP_CONTROL]];
+        rst[JV.PROP_STYLE] = node[[JV.PROP_STYLE]];
+        //2. value
+        rst[JV.PROP_VALUE] = value;
+        JpcFieldHelper.decorateValue(rst, controls);
+        if (node[JV.PROP_FORMAT]) {
+            if (!(isNaN(parseFloat(rst[JV.PROP_VALUE])))) {
+                var dotIdx = node[JV.PROP_FORMAT].indexOf(".");
+                if (dotIdx >= 0) {
+                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(node[JV.PROP_FORMAT].length - dotIdx - 1);
+                } else {
+                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(0);
+                }
+            }
+        }
+        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] != null && rst[JV.PROP_VALUE] != "") {
+            rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX] + rst[JV.PROP_VALUE];
+        }
+        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] != null && rst[JV.PROP_VALUE] != "") {
+            rst[JV.PROP_VALUE] = rst[JV.PROP_VALUE] + node[JV.PROP_SUFFIX];
+        }
+        return rst;
+    }
+}
+
+module.exports = JpcCommonOutputHelper;

+ 189 - 0
modules/reports/rpt_component/helper/Jpc_Helper_CrossTab.js

@@ -0,0 +1,189 @@
+var JV = require('../Jpc_ValueDefine');
+var JpcCommonHelper = require('./Jpc_Helper_Common');
+
+var JpcCrossTabHelper = {
+    getColIDX: function(cl, val) {
+        var rst = -1;
+        for (var i = 0; i < cl.length; i++) {
+            var ca = cl[i];
+            for (var j = 0; j < ca.length; j++) {
+                if (ca[j] == val) {
+                    rst = i;
+                    break;
+                }
+            }
+            if (rst != -1) {
+                break;
+            }
+        }
+        return rst;
+    },
+    pushToSeg: function(segArr, dataSeq, segIdx, sIdx, eIdx) {
+        var arrIdx = [];
+        for (var k = sIdx; k < eIdx; k++) {
+            arrIdx.push(dataSeq[segIdx][k]);
+        }
+        segArr.push(arrIdx);
+    },
+    sortFieldValue: function(sIDX, eIDX, sortOrder, dataField, dataValSeq) {
+        var tmpSeq = [];
+        if ((sortOrder) && (sortOrder != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
+            if (sIDX >= 0 && eIDX >= sIDX && dataValSeq.length > eIDX) {
+                var reversed = 1;
+                if (sortOrder === JV.TAB_FIELD_PROP_SORT_VAL_DESC) {
+                    reversed = -1;
+                }
+                for (var i = sIDX; i <= eIDX; i++) {
+                    tmpSeq.push(dataValSeq[i]);
+                }
+                tmpSeq.sort(function(idx1, idx2) {
+                    var rst = 0;
+                    if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
+                        if (dataField[idx1] > dataField[idx2]) {
+                            rst = reversed;
+                        } else if (dataField[idx1] < dataField[idx2]) {
+                            rst = -reversed;
+                        }
+                    } else {
+                        if ((1.0 * dataField[idx1]) > (1.0 * dataField[idx2])) {
+                            rst = reversed;
+                        } else if ((1.0 * dataField[idx1]) < (1.0 * dataField[idx2])) {
+                            rst = -reversed;
+                        }
+                    }
+                    return rst;
+                });
+            }
+        }
+        if (tmpSeq.length > 0) {
+            for (var i = sIDX; i <= eIDX; i++) {
+                dataValSeq[i] = tmpSeq[i - sIDX];
+            }
+        }
+        return tmpSeq;
+    },
+    checkIfEqual: function(dataFields, seq1, seq2) {
+        var rst = true;
+        for (var i = 0; i < dataFields.length; i++) {
+            if ((dataFields[i][seq1] !== dataFields[i][seq2])) {
+                rst = false;
+                break;
+            }
+        }
+        return rst;
+    },
+    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq) {
+        var me = this;
+        var sIDX = 0, eIDX = -1, isFirstSort = true;
+        for (var i = 0; i < tabFields.length; i++) {
+            var tabField = tabFields[i];
+            if (tabField[JV.TAB_FIELD_PROP_SORT] != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
+                if (isFirstSort) {
+                    isFirstSort = false;
+                    //first field, should sort all data items
+                    for (var j = 0; j < dataSeq.length; j++) {
+                        sIDX = 0;
+                        eIDX = dataSeq[j].length - 1;
+                        //sort the field value here
+                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                    }
+                } else {
+                    //then sort the rest fields one by one
+                    for (var j = 0; j < dataSeq.length; j++) {
+                        var chkFields = [];
+                        for (var k = 0; k < i; k++) {
+                            chkFields.push(data_details[fieldSeqs[k]]);
+                        }
+                        sIDX = 0, eIDX = -1;
+                        for (var m = 1; m < dataSeq[j].length; m++) {
+                            if (!(me.checkIfEqual(chkFields, dataSeq[j][m - 1], dataSeq[j][m]))) {
+                                eIDX = m - 1;
+                            } else if (m == dataSeq[j].length - 1) {
+                                eIDX = m;
+                            };
+                            if (eIDX >= sIDX) {
+                                if (eIDX != sIDX) {
+                                    me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                                }
+                                sIDX = m;
+                                eIDX = m - 1; //for protection purpose
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    },
+    getMaxTabCntPerPage: function(bands, rptTpl, tabNodeName, tabMeasurePropName, measureForCal) {
+        var rst = 1;
+        if (rptTpl[JV.NODE_CROSS_INFO][tabNodeName]) {
+            var tab = rptTpl[JV.NODE_CROSS_INFO][tabNodeName];
+            var maxFieldMeasure = 1.0;
+            if (JV.CAL_TYPE_ABSTRACT == JpcCommonHelper.getPosCalculationType(tab[JV.PROP_CALCULATION])) {
+                var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+                maxFieldMeasure = 1.0 * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] * unitFactor;
+            } else {
+                maxFieldMeasure = measureForCal * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] / JV.HUNDRED_PERCENT;
+            }
+            rst = Math.floor(measureForCal / maxFieldMeasure);
+        }
+        return rst;
+    },
+    getMaxRowsPerPage: function(bands, rptTpl) {
+        var me = this, rst = 1;
+        var band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.PROP_BAND_NAME]];
+        if (band) {
+            rst =  me.getMaxTabCntPerPage(bands, rptTpl, JV.NODE_CROSS_ROW, JV.PROP_CMN_HEIGHT, band.Bottom - band.Top);
+        }
+        return rst;
+    },
+    getMaxColsPerPage: function(bands, rptTpl) {
+        var me = this, rst = 1;
+        var band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.PROP_BAND_NAME]];
+        if (band) {
+            rst =  me.getMaxTabCntPerPage(bands, rptTpl, JV.NODE_CROSS_COL, JV.PROP_CMN_WIDTH, band.Right - band.Left);
+        }
+        return rst;
+    },
+    chkTabEnd: function(tabType, rptTpl, bands, sortedSequence, segIdx, preRec, nextRec) {
+        var me = this, rst = true;
+        var remainAmt = preRec + nextRec - sortedSequence[segIdx].length;
+        rst = me.hasEnoughSpace(tabType, rptTpl, bands, remainAmt);
+        return rst;
+    },
+    hasEnoughSpace: function (tabType, rptTpl, bands, remainAmt) {
+        if (remainAmt < 0) return false;
+        var rst = true, measurement = 1.0, douDiffForCompare = 0.00001;
+        var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        var band = null;
+        if (rptTpl[JV.NODE_CROSS_INFO][tabType]) {
+            band = bands[rptTpl[JV.NODE_CROSS_INFO][tabType][JV.PROP_BAND_NAME]];
+        }
+        if (band != null && band != undefined) {
+            if (tabType === JV.NODE_CROSS_ROW_SUM || tabType === JV.NODE_CROSS_ROW_EXT) {
+                measurement = 1.0 * rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.PROP_CMN_HEIGHT] * unitFactor;
+                var spareHeight = measurement * remainAmt;
+                var douH = 1.0 * (band.Bottom - band.Top);
+                rst = (spareHeight >= douH) || (spareHeight - douH <= douDiffForCompare);
+            } else if (tabType === JV.NODE_CROSS_COL_SUM) {
+                measurement = 1.0 * rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.PROP_CMN_WIDTH] * unitFactor;
+                var spareWidth = measurement * remainAmt;
+                var douW = 1.0 * (band.Right - band.Left);
+                rst = (spareWidth >= douW) || (spareWidth - douW <= douDiffForCompare);
+            }
+        }
+        return rst;
+    },
+    initialPageStatus: function (pageStatus) {
+        pageStatus[JV.STATUS_NORMAL] = true;
+        pageStatus[JV.STATUS_REPORT_START] = false;
+        pageStatus[JV.STATUS_REPORT_END] = false;
+        pageStatus[JV.STATUS_SEGMENT_START] = false;
+        pageStatus[JV.STATUS_SEGMENT_END] = false;
+        pageStatus[JV.STATUS_GROUP] = false;
+        pageStatus[JV.STATUS_CROSS_ROW_END] = false;
+        pageStatus[JV.STATUS_CROSS_COL_END] = false;
+    }
+};
+
+module.exports = JpcCrossTabHelper;

+ 58 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Discrete.js

@@ -0,0 +1,58 @@
+var JV = require('../Jpc_ValueDefine');
+var JE = require('../Jpc_RTE');
+var JpcTextHelper = require('./Jpc_Helper_Text');
+var JpcCommonOutputHelper = require('./Jpc_Helper_CommonOutput');
+var JpcAreaHelper = require('./Jpc_Helper_Area');
+
+var JpcDiscreteHelper = {
+    outputDiscreteInfo: function (discreteArray, bands, dataObj, unitFactor, pageStatus, segIdx, multiCols, multiColIdx, $CURRENT_RPT) {
+        var rst = [];
+        if (discreteArray && dataObj) {
+            for (var i = 0; i < discreteArray.length; i++) {
+                var band = bands[discreteArray[i][JV.PROP_BAND_NAME]];
+                if (band && pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] == true) {
+                    if (discreteArray[i][JV.PROP_TEXT]) {
+                        rst.push(JpcTextHelper.outputText(discreteArray[i][JV.PROP_TEXT], band, unitFactor, 1, 0, 1, 0, multiCols, multiColIdx));
+                    }
+                    if (discreteArray[i][JV.PROP_TEXTS]) {
+                        for (var j = 0; j < discreteArray[i][JV.PROP_TEXTS].length; j++) {
+                            rst.push(JpcTextHelper.outputText(discreteArray[i][JV.PROP_TEXTS][j], band, unitFactor, 1, 0, 1, 0, multiCols, multiColIdx));
+                        }
+                    }
+                    if (discreteArray[i][JV.PROP_DISCRETE_FIELDS]) {
+                        for (var j = 0; j < discreteArray[i][JV.PROP_DISCRETE_FIELDS].length; j++) {
+                            var df = discreteArray[i][JV.PROP_DISCRETE_FIELDS][j];
+                            var value = "";
+                            if (df[JV.PROP_FIELD_ID]) {
+                                var field = JE.F(df[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                                if (field.DataSeq != JV.BLANK_FIELD_INDEX) {
+                                    var data = dataObj[field.DataNodeName][field.DataSeq];
+                                    if (data && data.length > 0) {
+                                        if (data.length > segIdx) {
+                                            value = data[segIdx];
+                                        } else {
+                                            value = data[0];
+                                        }
+                                    }
+                                } else {
+                                    if (field[JV.PROP_AD_HOC_DATA] && field[JV.PROP_AD_HOC_DATA].length > 0) value = field[JV.PROP_AD_HOC_DATA][0]
+                                    else value = "";
+                                }
+                            } else if (df[JV.PROP_PARAM_ID]) {
+                                var param = JE.P(df[JV.PROP_PARAM_ID], $CURRENT_RPT);
+                                value = param[JV.PROP_DFT_VALUE];
+                            }
+                            var item = JpcCommonOutputHelper.createCommonOutputWithoutDecorate(df, value, null);
+                            //position
+                            item[JV.PROP_AREA] = JpcAreaHelper.outputArea(df[JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, multiCols, multiColIdx, false, false);
+                            rst.push(item);
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    }
+}
+
+module.exports = JpcDiscreteHelper;

+ 44 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Field.js

@@ -0,0 +1,44 @@
+var JV = require('../Jpc_ValueDefine');
+
+var JpcFieldHelper = {
+    getValue: function(dataField, valueIdx) {
+        var rst = "";
+        if (dataField && (dataField.length > valueIdx) && (valueIdx >= 0)) {
+            rst = dataField[valueIdx];
+        }
+        return rst;
+    },
+    decorateValue: function (cell, controls) {
+        if (controls) {
+            var val = cell[JV.PROP_VALUE];
+            var showZero = controls[cell[JV.PROP_CONTROL]][JV.PROP_SHOW_ZERO];
+            if (showZero && showZero == 'F' ) {
+                if (0.0 == 1.0 * (0 + val)) {
+                    cell[JV.PROP_VALUE] = "";
+                }
+            }
+        }
+    },
+    findAndPutDataFieldIdx: function (rptTpl, tab_fields, rstFields, rstFieldsIdx) {
+        if (tab_fields) {
+            var detail_fields = rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS];
+            for (var i = 0; i < tab_fields.length; i++) {
+                var isFounded = false;
+                for (var j = 0; j < detail_fields.length; j++) {
+                    if (tab_fields[i]["FieldID"] == detail_fields[j]["ID"]) {
+                        isFounded = true;
+                        if (rstFields) rstFields.push(tab_fields[i]);
+                        if (rstFieldsIdx) rstFieldsIdx.push(j);
+                        break;
+                    }
+                }
+                if (!isFounded) {
+                    if (rstFields) rstFields.push(tab_fields[i]);
+                    if (rstFieldsIdx) rstFieldsIdx.push(JV.BLANK_FIELD_INDEX);
+                }
+            }
+        }
+    }
+};
+
+module.exports = JpcFieldHelper;

+ 43 - 0
modules/reports/rpt_component/helper/Jpc_Helper_FlowTab.js

@@ -0,0 +1,43 @@
+var JV = require('../Jpc_ValueDefine');
+var JpcCommonHelper = require('./Jpc_Helper_Common');
+
+var JpcFlowTabHelper = {
+    getMaxRowsPerPage: function(bands, rptTpl) {
+        var me = this, rst = 1;
+        var tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            var maxFieldMeasure = 1.0;
+            if (JV.CAL_TYPE_ABSTRACT == JpcCommonHelper.getPosCalculationType(tab[JV.PROP_CALCULATION])) {
+                var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+                maxFieldMeasure = 1.0 * rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_CMN_HEIGHT] * unitFactor;
+            } else {
+                maxFieldMeasure = (band.Bottom - band.Top) * rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_CMN_HEIGHT] / JV.HUNDRED_PERCENT;
+            }
+            rst = Math.floor((band.Bottom - band.Top) / maxFieldMeasure);
+        }
+        return rst;
+    },
+    chkSegEnd: function (bands, rptTpl, sortedSequence, segIdx, preRec, nextRec) {
+        var me = this, rst = true;
+        var remainAmt = preRec + nextRec - sortedSequence[segIdx].length;
+        rst = me.hasEnoughSpace(rptTpl, bands, remainAmt);
+        return rst;
+    },
+    hasEnoughSpace: function (rptTpl, bands, remainAmt) {
+        if (remainAmt < 0) return false;
+        var rst = true, measurement = 1.0, douDiffForCompare = 0.00001;
+        var unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        var tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT];
+        var band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band != null && band != undefined) {
+            measurement = 1.0 * tab[JV.PROP_CMN_HEIGHT] * unitFactor;
+            var spareHeight = measurement * remainAmt;
+            var douH = 1.0 * (band.Bottom - band.Top);
+            rst = (spareHeight >= douH) || (spareHeight - douH <= douDiffForCompare);
+        }
+        return rst;
+    }
+};
+
+module.exports = JpcFlowTabHelper;

+ 14 - 0
modules/reports/rpt_component/helper/Jpc_Helper_Text.js

@@ -0,0 +1,14 @@
+var JV = require('../Jpc_ValueDefine');
+var JpcCommonOutputHelper = require('./Jpc_Helper_CommonOutput');
+var JpcAreaHelper = require('./Jpc_Helper_Area');
+
+var JpcTextHelper = {
+    outputText: function (textNode, band, unitFactor, rows, rowIdx, cols, colIdx, multiCols, multiColIdx) {
+        var rst = JpcCommonOutputHelper.createCommonOutput(textNode, textNode[JV.PROP_LABEL], null);
+        //position
+        rst[JV.PROP_AREA] = JpcAreaHelper.outputArea(textNode[JV.PROP_AREA], band, unitFactor, rows, rowIdx, cols, colIdx, multiCols, multiColIdx, false, false);
+        return rst;
+    }
+};
+
+module.exports = JpcTextHelper;