├── Custom Bar Chart Samples.qvf ├── customBarChart.qext ├── CHANGELOG.MD ├── README.md ├── customBarChart.js └── properties.js /Custom Bar Chart Samples.qvf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WedersonCD/customBarChart/HEAD/Custom Bar Chart Samples.qvf -------------------------------------------------------------------------------- /customBarChart.qext: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Custom Bar charts", 3 | "description" : "Custom chart based in e-charts library", 4 | "icon" : "extension", 5 | "type" : "visualization", 6 | "version": "2.17.0", 7 | "author": "Wederson Domingues" 8 | } -------------------------------------------------------------------------------- /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | 9 | 10 | ## [2.18.0] - 2025-09-06 11 | 12 | ### Added 13 | 14 | - Add options to change these object CSS: Background-color, border-style, border-width, border-color 15 | 16 | ### Changed 17 | 18 | - e-charts version updated to 6.0.0; 19 | 20 | 21 | ## [2.17.0] - 2023-06-08 22 | 23 | ### Added 24 | 25 | - Add option to chose between 'start' or 'end' to DataZoom propertie. 26 | 27 | 28 | ## [2.16.0] - 2023-05-10 29 | 30 | ### Added 31 | 32 | - Add option to change line symbol type 33 | 34 | 35 | ## [2.15.0] - 2023-04-28 36 | 37 | ### Added 38 | 39 | - Add option to hide measures in legend 40 | 41 | ## [2.14.0] - 2023-04-01 42 | 43 | ### Addded 44 | 45 | - Add line step option (Thanks to HG14 for this feature) 46 | 47 | 48 | ## [2.14.0] - 2023-04-01 49 | 50 | ### Addded 51 | 52 | - Add Tooltip Section 53 | - Add option to show/hide individual expression in tooltip 54 | 55 | ### Changed 56 | 57 | - e-charts version updated to 5.4.2; 58 | 59 | ## [2.13.0] - 2022-11-04 60 | 61 | ### Addded 62 | 63 | - Now you can pick custom font bold; 64 | - Now you can pick font bold for individual measures; 65 | - Now you can change font family of data label 66 | 67 | ### Changed 68 | 69 | - e-charts version updated to 5.4.0; 70 | - Data label rotation changed from slider to expression box 71 | 72 | ## [2.12.0] - 2022-08-13 73 | 74 | ### Addded 75 | 76 | - Add axis label formatter option in 'yAxis: Left' and 'yAxis: Right' section. 77 | 78 | ## [2.11.0] - 2022-02-25 79 | 80 | ### Changed 81 | 82 | - e-charts version updated to 5.3.3; 83 | - parseInt line size 84 | 85 | ## [2.10.0] - 2022-02-25 86 | 87 | ### Changed 88 | 89 | - e-charts version updated to 5.3; 90 | 91 | ### Addded 92 | 93 | - Now the extension get the whole dataset using getData function from the api. 94 | 95 | ## [2.9.0] - 2021-11-25 96 | 97 | ### Changed 98 | 99 | - 'Settings' section name changed to 'Global Settings' 100 | - e-charts version updated to 5.2.1; 101 | 102 | ### Addded 103 | 104 | - Option to use a custom data label; 105 | - Option 'Use Global Settings' in measure, now you can overwrite global settings for one particular measure giving more control in the visualization; 106 | - 'Switch Axis' option on 'Grid' section that invert 'X' and 'Y' axis; 107 | - Option to Show/Hide the data zoom. 108 | - Add more samples 109 | 110 | 111 | ## [2.8.1] - 2021-06-20 112 | 113 | ### Changed 114 | 115 | - fix bug problem that make line width always be 0 116 | 117 | ## [2.8.0] - 2021-06-15 118 | 119 | ### Addded 120 | 121 | - Now you can export the extension as image and PDF. ( It is working on StoryTelling); 122 | - e-charts version updated to 5.1.2; 123 | - Now can you select different icons to line and bar measure type; 124 | - Now can you change the symbol size of line measures. 125 | 126 | 127 | ## [2.7.0] - 2021-06-05 128 | 129 | ### Addded 130 | 131 | - Add 'Keep Colors' on 'On Focus' option; 132 | 133 | 134 | 135 | ## [2.6.0] - 2021-05-27 136 | 137 | ### Addded 138 | 139 | - Now you can change legend position; 140 | - Now you can change legend distance of the corner based in legend position. 141 | 142 | ### Changed 143 | 144 | - Now you can add 15 measures; 145 | - Paint method return qlik.promise. 146 | 147 | ## [2.5.0] - 2021-04-03 148 | 149 | ### Added 150 | 151 | - You can now change the line width; 152 | - Now you can choose between 'Solid','Dashed' or 'Dotted' line types; 153 | - Add option to put border on data labels and choose their color; 154 | - Option to allow users to drag and drop the position of the data label (only works when the border width is 0), with this functionality you can enable the label line option as well; 155 | - You can define axis label color with expression; 156 | - You can put border on axis label and choose its color; 157 | - You can put border on legend text and choose its color; 158 | - Add 'yAxis: Left' and 'yAxis: Right' settings to define custom max and min values and define its visibility 159 | 160 | ## [2.4.0] - 2021-03-31 161 | 162 | ### Added 163 | 164 | - Now you can change the chart position with Grid options. 165 | 166 | ### Changed 167 | 168 | - DataZoom appears correct now. 169 | - update 'README.md' file. 170 | 171 | ## [2.3.0] - 2021-03-26 172 | 173 | ### Added 174 | 175 | - Add legend text size option 176 | 177 | ## [2.2.0] - 2021-03-17 178 | 179 | ### Added 180 | 181 | - Add bar options in settings (barWidth,minBarWidth,maxBarWidth) 182 | 183 | ### Changed 184 | 185 | - Bar Gap options changed from 'Other' to 'Bar Options' 186 | 187 | ## [2.1.0] - 2021-03-10 188 | 189 | ### Added 190 | 191 | - Add option to change legend text color. 192 | 193 | ### Changed 194 | 195 | - Add label in 'change icon' dropdow. 196 | 197 | 198 | ## [2.0.0] - 2021-03-06 199 | 200 | ### Added 201 | 202 | - This changelog file 203 | - 'Legend' section is added into 'Settings', now you can: Hide/Show the legend and change legends icon. 204 | - 'On Focus' section is added into 'Settings', now you can hight the measures on mouse hover. 205 | - In 'Others' section you can hide zero values in graph. 206 | 207 | ### Changed 208 | 209 | - Echarts version updated to [5.0](https://echarts.apache.org/en/tutorial.html#New%20features%20in%20ECharts%205) 210 | - Metrics colors can be seted by expression. 211 | - Is possible choose between 'By expression' and 'Single Color' in expression section. 212 | - Don't shows 'Label Color' component when 'Label Color Auto' is setted as 'on'. 213 | - Now DataZoom only appear when the number of dimension values is greater than 'Number Visible Items' in 'Others' section. 214 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Custom Bar Chart 3 | 4 | A custom bar/line chart created based in [echarts library](https://echarts.apache.org/en/index.html "echarts library"). 5 | 6 | See the changes [here](https://github.com/WedersonCD/customBarChart/blob/main/CHANGELOG.MD "Changed Log"), updated in 2025-09-06. 7 | 8 | - Expression Options 9 | - Data Label Settings 10 | - Axis Label Settings 11 | - Legend 12 | - On Focus 13 | - Bar Options 14 | - yAxis 15 | - Grid Settings 16 | - Tooltip Settings 17 | - Object Style 18 | - Others Settings 19 | - Samples 20 | 21 | 22 | ### Expression Options 23 | 24 | ------------ 25 | 26 | - stack: Stack the measures on your on way! if two or more measures have the same stack property they are satcked; 27 | 28 | - type: How the measure will be presented, in bar or line; 29 | 30 | - line type: If 'type' option is 'Line' you can choose between 'Solid','Dashed' or 'Dotted' line types; 31 | 32 | - line width: If 'type' option is 'Line' you can define the line width; 33 | 34 | - line symbol size: change the line simbol size; 35 | 36 | - y-axis: Defines which y-axis the measure will follow; 37 | 38 | - color: Define the measure color; 39 | 40 | - label Weight: font thick weight. 41 | 42 | - label color auto: Let Echarts select the right color; 43 | 44 | - label color: select label color. (label color auto option must be off); 45 | 46 | - label border width: Change border width; 47 | 48 | - label border border: Change border color. 49 | 50 | 51 | ### Data Label Settings 52 | 53 | ------------ 54 | 55 | - visibility: Show/Hide 56 | 57 | - distance: Distance to the host graphic element. Works when position is value 'top' ou 'insideRight'. 58 | 59 | - rotate: Rotate label, from -90 degree to 90, positive value represents rotate anti-clockwise. 60 | 61 | - position: label position 62 | 63 | - style: font style. 64 | 65 | - Weight: font thick weight. 66 | 67 | - Size: font size. 68 | 69 | - Align: Horizontal alignment of text. 70 | 71 | - Allow Drag&Drop: If this option is ennable allow to users change data label position. (Label border width must be 0) 72 | 73 | - Show Lable Line: Place a connected line between the label and the Bar/Line 74 | 75 | 76 | ### Axis Label Settings 77 | 78 | ------------ 79 | 80 | - visibility: Show/Hide 81 | 82 | - rotate: Rotate label, from -90 degree to 90, positive value represents rotate anti-clockwise. 83 | 84 | - style: font style. 85 | 86 | - Weight: font thick weight. 87 | 88 | - Size: font size. 89 | 90 | - Align: Horizontal alignment of text. 91 | 92 | - text border width: Change border width 93 | 94 | - text border border: Change border color 95 | 96 | 97 | ### Legend Settings 98 | 99 | ------------ 100 | 101 | - visibility: Show/Hide. 102 | 103 | - position: legend position. 104 | 105 | - distance: distance between the legend and the corner, can be absolute or relative values like 0,20,0%,20% etc. 106 | 107 | - bar legend icon: legend icon shape of the bar measures. 108 | 109 | - line legend icon: legend icon shape of the line measures. 110 | 111 | - text size: font size. 112 | 113 | - color type: change between single color or color by expression 114 | 115 | - text color: text color. 116 | 117 | - text border width: width value of the text vorder. 118 | 119 | - text border color: color of the border 120 | 121 | 122 | ### On Focus 123 | 124 | ------------ 125 | 126 | - Focus: On/Off focus based in [emphasis](https://echarts.apache.org/en/option.html#series-bar.emphasis) echarts funcionality 127 | 128 | - Color: Bar/line color. 129 | 130 | - Label Color: Label color 131 | 132 | - Label Size: Label Size. 133 | 134 | ### Bar Options 135 | 136 | ------------ 137 | 138 | - Bar Gap: gap between the bars in %, you can use '30%' or 0.3 values. Use '-100%' to overlap the bars. 139 | 140 | - Bar Width Auto: Enable width bar options. 141 | 142 | - Bar Width: Width of the bars, yout can use absolute values like '70' or percentage values like '20%'. 143 | 144 | - Max\Min Bar Width: Define max and min values for bar width. 145 | 146 | ### yAxis 147 | 148 | ------------ 149 | 150 | - visibility: Show/Hide the axis. 151 | 152 | - Label Formatter Auto: Show/Hide formatter options. 153 | 154 | - Label Formatter Style: Style of the number.(Currency,percent and decimal) 155 | 156 | - Label Formatter Currency Symbol: Currency symbol. (in ISO 4217 partner,see more [here](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=isin) ) 157 | 158 | - Label Formatter Currency Locales: Currency locales format. (in BCP 47 partner, see more [here](https://www.techonthenet.com/js/language_tags.php)) 159 | 160 | - Interval: Choose between custom and auto axis interval. You can set custom Max and Min values. 161 | 162 | - Inverse: Invert the axis. 163 | 164 | ### Grid Options 165 | 166 | ------------ 167 | - Switch Axis: Switch X and Y axis making the graph horizontal. 168 | 169 | - Contain Label: Change the grid size based on label. ( see more [here](https://echarts.apache.org/en/option.html#grid.containLabel) ) 170 | 171 | - Custom Grid Position: Enable grid position options 172 | 173 | - Left\Right\Top\Bottom: Define the position of the chart relative to each side. Can be absolute values like '60' or percentage values like '10%'. 174 | 175 | - width\height: Define the Height and width of the chart, can be absolute values, percentage values or 'auto' to let eCharts define the values. 176 | 177 | ### Tooltip Settings 178 | 179 | ------------ 180 | 181 | - Show: On/Off Tooltip 182 | 183 | - Always Show: Whether to show tooltip content all the time. 184 | 185 | - Group By Stack: Group measures by value on stack property in individual measures. 186 | 187 | - Transition Duration: Speed of tool tip. 188 | 189 | - Use Custom Formatter: You can write a javascript function to draw the tooltip. ( see more [here](https://echarts.apache.org/en/option.html#tooltip.formatter) ) 190 | 191 | ### Object Style 192 | 193 | ------------ 194 | 195 | - Use Object Style: Enable/Disable object style settings (On/Off). Default: Off. 196 | 197 | - Include Object Title: Include the object title when applying the object style (On/Off). Default: Off. 198 | 199 | - Background Color: Background color for the object (CSS color string). Default: rgba(255,255,255,0.7). 200 | 201 | - Border Width (px): Border width in pixels. Default: 5. 202 | 203 | - Border Color: Border color (CSS color string). Default: #333. 204 | 205 | - Border Style: Border style (e.g., solid, dashed, dotted). Default: solid. 206 | 207 | 208 | ### Others Settings 209 | 210 | ------------ 211 | 212 | - Show Zero Values: Hide 0 values. 213 | 214 | - Number Visible Items: Number of visible items in X axis. 215 | 216 | ### Samples 217 | 218 | ------------ 219 | ![](https://i.imgur.com/X32MBv4.png) 220 | ![](https://i.imgur.com/FNvoj4D.png) 221 | ![](https://i.imgur.com/iLLN8VO.png) 222 | ![](https://i.imgur.com/2x4x4nc.png) 223 | ![](https://i.imgur.com/iQHXxPH.png) 224 | ![](https://i.imgur.com/zgBTdmw.png) 225 | ![](https://i.imgur.com/TP99m1c.png) 226 | ![](https://i.imgur.com/KhJFj3D.png) 227 | -------------------------------------------------------------------------------- /customBarChart.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | './echarts.min', 4 | './properties', 5 | 'qlik' 6 | ], 7 | function ($, echarts, props, qlik) { 8 | //Number of initial rows used in qInitialDataFetch prop 9 | const initialRows = 625; 10 | 11 | 12 | function getDimensionArray(layout) { 13 | 14 | 15 | return layout.qHyperCube.qDataPages[0].qMatrix.map((item) => { 16 | return item[0].qText; 17 | }); 18 | } 19 | 20 | function getDimensionArrayDistinct(layout) { 21 | 22 | dimension = getDimensionArray(layout); 23 | 24 | return [...new Set(dimension)] 25 | 26 | } 27 | 28 | function getColorType(layout, measurePosition) { 29 | 30 | return layout.qHyperCube.qMeasureInfo[measurePosition].colorType; 31 | } 32 | 33 | function getSerieValueItemStyleColor(layout, measurePosition, qMatrixItem) { 34 | 35 | var colorType = getColorType(layout, measurePosition); 36 | 37 | var color; 38 | 39 | //0 is single color 1 is color by expression 40 | if (colorType == 0) { 41 | color = layout.qHyperCube.qMeasureInfo[measurePosition].color.color 42 | } else if (colorType == 1) { 43 | color = qMatrixItem[measurePosition + 1].qAttrExps.qValues[0].qText 44 | } 45 | 46 | return color; 47 | } 48 | 49 | function getSerieValue(layout, measurePosition) { 50 | 51 | 52 | return layout.qHyperCube.qDataPages[0].qMatrix.map((item) => { 53 | 54 | var value = item[measurePosition + 1].qNum; 55 | 56 | //check if the number will be showed 57 | if (value == 0 && !layout.settings.others.showZeroBars) { 58 | value = '-'; 59 | } 60 | 61 | textValue = item[measurePosition + 1].qText 62 | 63 | //get custom label 64 | if (layout.qHyperCube.qMeasureInfo[measurePosition].customDataLabel && layout.qHyperCube.qMeasureInfo[measurePosition].customDataLabel.use) { 65 | textValue = item[measurePosition + 1].qAttrExps.qValues[1].qText 66 | } 67 | 68 | return { 69 | value: value 70 | , valueText: textValue 71 | //Make to get stack name in tool tip 72 | , stack: layout.qHyperCube.qMeasureInfo[measurePosition].stack 73 | , showInToolTip: layout.qHyperCube.qMeasureInfo[measurePosition].showInToolTip 74 | , itemStyle: { 75 | color: getSerieValueItemStyleColor(layout, measurePosition, item) 76 | } 77 | } 78 | 79 | }); 80 | } 81 | 82 | function getSerieLabel(layout, measurePosition) { 83 | 84 | settings = layout.settings 85 | 86 | var labelSettings = { 87 | show: settings.dataLabel.visibility, 88 | align: settings.dataLabel.align, 89 | fontSize: parseInt(settings.dataLabel.size), 90 | fontStyle: settings.dataLabel.style, 91 | position: settings.dataLabel.position, 92 | distance: parseInt(settings.dataLabel.distance), 93 | rotate: settings.dataLabel.rotate, 94 | formatter: function (params) { 95 | return params.data.valueText; 96 | } 97 | } 98 | var measureInfo = layout.qHyperCube.qMeasureInfo[measurePosition]; 99 | 100 | if (measureInfo.dataLabel.auto == false) { 101 | 102 | //set single color 103 | if (getColorType(layout, measurePosition) == 0) { 104 | 105 | labelSettings.color = measureInfo.dataLabel.color.color; 106 | 107 | //set color by expression 108 | } else if (getColorType(layout, measurePosition) == 1) { 109 | 110 | labelSettings.color = measureInfo.dataLabel.colorExpression; 111 | } 112 | 113 | //Color Border 114 | if (measureInfo.dataLabel.border) { 115 | 116 | labelSettings.textBorderWidth = measureInfo.dataLabel.border.width 117 | 118 | if (getColorType(layout, measurePosition) == 0) { 119 | 120 | labelSettings.textBorderColor = color = measureInfo.dataLabel.border.color.color; 121 | 122 | } else if (getColorType(layout, measurePosition) == 1) { 123 | 124 | labelSettings.textBorderColor = measureInfo.dataLabel.border.colorExpression; 125 | } 126 | } 127 | 128 | } 129 | 130 | if (settings.dataLabel.family) { 131 | labelSettings.fontFamily = settings.dataLabel.family 132 | } 133 | 134 | if (settings.dataLabel.weight === 'custom') { 135 | labelSettings.fontWeight = parseInt(settings.dataLabel.weightCustom) 136 | } else { 137 | labelSettings.fontWeight = settings.dataLabel.weight 138 | } 139 | 140 | 141 | //Overwrite global settings 142 | if (measureInfo.globalSettings && !measureInfo.globalSettings.use) { 143 | 144 | labelSettings.show = measureInfo.globalSettings.dataLabel.visibility; 145 | labelSettings.align = measureInfo.globalSettings.dataLabel.align; 146 | labelSettings.fontSize = parseInt(measureInfo.globalSettings.dataLabel.size); 147 | labelSettings.position = measureInfo.globalSettings.dataLabel.position; 148 | labelSettings.distance = parseInt(measureInfo.globalSettings.dataLabel.distance); 149 | labelSettings.rotate = measureInfo.globalSettings.dataLabel.rotate; 150 | 151 | if (measureInfo.globalSettings.dataLabel.weight && measureInfo.globalSettings.dataLabel.weight === 'custom') { 152 | labelSettings.fontWeight = parseInt(measureInfo.globalSettings.dataLabel.weightCustom) 153 | } else if (measureInfo.globalSettings.dataLabel.weight) { 154 | labelSettings.fontWeight = measureInfo.globalSettings.dataLabel.weight 155 | } 156 | 157 | if (measureInfo.globalSettings.dataLabel.family) { 158 | labelSettings.fontFamily = measureInfo.globalSettings.dataLabel.family 159 | } 160 | 161 | } 162 | 163 | return labelSettings; 164 | 165 | } 166 | 167 | function getAxisLabel(layout) { 168 | 169 | axisLabelLayout = layout.settings.axisLabel 170 | 171 | var labelSettings = { 172 | show: axisLabelLayout.visibility, 173 | align: axisLabelLayout.align, 174 | fontSize: parseInt(axisLabelLayout.size), 175 | fontWeight: axisLabelLayout.weight, 176 | fontStyle: axisLabelLayout.style, 177 | rotate: axisLabelLayout.rotate 178 | } 179 | 180 | 181 | //get text color 182 | if (axisLabelLayout.colorType >= 0) { 183 | 184 | if (axisLabelLayout.colorType == 0) { 185 | labelSettings.color = axisLabelLayout.color.color 186 | 187 | } else if (axisLabelLayout.colorType == 1) { 188 | labelSettings.color = axisLabelLayout.colorByExpression 189 | 190 | } 191 | } 192 | 193 | //Get text border 194 | if (axisLabelLayout.border) { 195 | 196 | labelSettings.textBorderWidth = axisLabelLayout.border.width 197 | 198 | if (axisLabelLayout.colorType == 0) { 199 | 200 | labelSettings.textBorderColor = axisLabelLayout.border.color.color 201 | 202 | } else if (axisLabelLayout.colorType == 1) { 203 | 204 | labelSettings.textBorderColor = axisLabelLayout.border.colorByExpression 205 | 206 | } 207 | 208 | } 209 | 210 | 211 | return labelSettings; 212 | 213 | } 214 | 215 | function getLabelLine(layout, measureInfo) { 216 | 217 | labelLineLayout = layout.settings.dataLabel.labelLine 218 | 219 | var labelLine = { 220 | show: true, 221 | length2: 5, 222 | lineStyle: { 223 | width: parseInt(labelLineLayout.width), 224 | opacity: labelLineLayout.opacity, 225 | type: labelLineLayout.type 226 | } 227 | } 228 | 229 | 230 | //Define line color 231 | 232 | //Single Color 233 | if (labelLineLayout.colorType == 0) { 234 | 235 | labelLine.lineStyle.color = labelLineLayout.color.color 236 | //Color by expression 237 | } else if (labelLineLayout.colorType == 1) { 238 | 239 | labelLine.lineStyle.color = labelLineLayout.color.colorExpression 240 | 241 | //Keep Label Color 242 | } else if (labelLineLayout.colorType == 2) { 243 | 244 | if (measureInfo.colorType == 0) { 245 | labelLine.lineStyle.color = measureInfo.dataLabel.color.color 246 | } else if (measureInfo.colorType == 1) { 247 | labelLine.lineStyle.color = measureInfo.dataLabel.colorExpression 248 | } 249 | 250 | } 251 | 252 | return labelLine; 253 | 254 | } 255 | 256 | function getLabellabelLayout(layout) { 257 | 258 | var labelDrag = function (param) { 259 | return { 260 | x: param.rect.x + (param.rect.width / 2), 261 | y: param.labelRect.y, 262 | draggable: true 263 | } 264 | }; 265 | 266 | return labelDrag; 267 | 268 | } 269 | 270 | function getSerieCommumProperty(layout, measurePosition) { 271 | 272 | var measureInfo = layout.qHyperCube.qMeasureInfo[measurePosition]; 273 | var settings = layout.settings; 274 | 275 | var commumProperty = { 276 | 277 | barGap: settings.barOptions.barGap, 278 | type: measureInfo.type, 279 | stack: measureInfo.stack, 280 | name: measureInfo.qFallbackTitle, 281 | largeThreshold: 7000 282 | }; 283 | 284 | 285 | if (settings.grid.switchAxies) { 286 | commumProperty.xAxisIndex = measureInfo.yIndex; 287 | } else { 288 | commumProperty.yAxisIndex = measureInfo.yIndex; 289 | } 290 | 291 | if (measureInfo.line && measureInfo.type == 'line') { 292 | 293 | commumProperty.symbolSize = parseInt(measureInfo.line.symbolSize) 294 | commumProperty.symbol = measureInfo.line.symbolType || 'emptyCircle' 295 | commumProperty.lineStyle = { 296 | width: parseInt(measureInfo.line.width), 297 | type: measureInfo.line.type, 298 | } 299 | 300 | if (measureInfo.line.step) 301 | commumProperty.step = measureInfo.line.step; 302 | } 303 | 304 | if (settings.dataLabel.drag && settings.dataLabel.drag.isDraggable) { 305 | commumProperty.labelLayout = getLabellabelLayout(layout) 306 | 307 | //Only show label line if labeldrag is active" 308 | if (settings.dataLabel.labelLine && settings.dataLabel.labelLine.show) { 309 | commumProperty.labelLine = getLabelLine(layout, measureInfo) 310 | } 311 | } 312 | 313 | if (!settings.barOptions.barWidthAuto) { 314 | 315 | commumProperty.barWidth = settings.barOptions.barWidth 316 | commumProperty.barMaxWidth = settings.barOptions.maxBarWidth 317 | commumProperty.barMinWidth = settings.barOptions.minBarWidth 318 | } 319 | 320 | return commumProperty 321 | } 322 | 323 | function getEmphasis(layout) { 324 | 325 | var focus = layout.settings.focus 326 | 327 | //check if On Focus option is on 328 | if (!focus.on) { 329 | return { focus: 'none' } 330 | } 331 | 332 | var emphasis = { 333 | focus: 'series', 334 | label: { 335 | fontSize: focus.label.size 336 | }, 337 | itemStyle: {}, 338 | lineStyle: {}, 339 | 340 | }; 341 | 342 | //Set single color 343 | if (focus.colorType == 0) { 344 | 345 | emphasis.label.color = focus.label.color.color 346 | emphasis.itemStyle.color = focus.item.color.color 347 | emphasis.lineStyle.color = focus.item.color.color 348 | 349 | //set expression colors if they not are '' 350 | } else if (focus.colorType == 1) { 351 | 352 | if (!focus.label.colorExpression.color == '') { 353 | 354 | emphasis.label.color = focus.label.colorExpression.color 355 | } 356 | if (!focus.item.colorExpression.color == '') { 357 | 358 | emphasis.itemStyle.color = focus.item.colorExpression.color 359 | emphasis.lineStyle.color = focus.item.colorExpression.color 360 | } 361 | } 362 | 363 | 364 | return emphasis; 365 | 366 | } 367 | 368 | function getSerieArray(layout) { 369 | serieArray = []; 370 | 371 | var expressionNumber = layout.qHyperCube.qMeasureInfo.length; 372 | 373 | for (var x = 0; x < expressionNumber; x++) { 374 | 375 | serieArray[x] = getSerieCommumProperty(layout, x) 376 | serieArray[x].label = getSerieLabel(layout, x) 377 | serieArray[x].data = getSerieValue(layout, x) 378 | serieArray[x].emphasis = getEmphasis(layout) 379 | } 380 | 381 | if (layout.qHyperCube.qMeasureInfo) 382 | return serieArray; 383 | } 384 | 385 | function getExpressionColorArray(layout) { 386 | 387 | var expressionNumber = layout.qHyperCube.qMeasureInfo.length; 388 | var expressionColorArray = []; 389 | 390 | for (var x = 0; x < expressionNumber; x++) { 391 | 392 | expressionColorArray[x] = layout.qHyperCube.qMeasureInfo[x].color.color; 393 | 394 | } 395 | 396 | return expressionColorArray; 397 | 398 | } 399 | 400 | function getDimensionName(layout) { 401 | 402 | return layout.qHyperCube.qDimensionInfo[0].qGroupFieldDefs[0]; 403 | } 404 | 405 | function getNumberVisibleItems(layout) { 406 | 407 | return layout.settings.others.numberVisibleItems - 1 408 | } 409 | 410 | function getDataZoom(layout) { 411 | 412 | visibleItens = getNumberVisibleItems(layout); 413 | qtdDimensionValues = getDimensionArrayDistinct(layout).length 414 | 415 | 416 | //if to keep compatibility 417 | if (typeof (layout.settings.others.showDataZoom) === 'undefined') { 418 | 419 | showDataZoom = qtdDimensionValues >= visibleItens 420 | } else { 421 | 422 | showDataZoom = layout.settings.others.showDataZoom 423 | } 424 | 425 | let dataZoomProperty = { 426 | type: 'slider', 427 | show: showDataZoom, 428 | filterMode: 'empty' 429 | } 430 | 431 | if (layout.settings.grid.switchAxies) { 432 | dataZoomProperty.id = 'dataZoomY'; 433 | dataZoomProperty.yAxisIndex = 0; 434 | dataZoomProperty.start = 100; 435 | dataZoomProperty.end = (1 - visibleItens / qtdDimensionValues) * 100; 436 | 437 | } else { 438 | dataZoomProperty.id = 'dataZoomX'; 439 | dataZoomProperty.xAxisIndex = 0; 440 | 441 | if (!layout.settings.others.dataZoomPosition || layout.settings.others.dataZoomPosition == 'start') { 442 | dataZoomProperty.startValue = 0; 443 | dataZoomProperty.endValue = visibleItens 444 | } else { 445 | dataZoomProperty.startValue = qtdDimensionValues; 446 | dataZoomProperty.endValue = qtdDimensionValues - visibleItens 447 | } 448 | 449 | 450 | } 451 | 452 | return [ 453 | dataZoomProperty 454 | ]; 455 | } 456 | 457 | 458 | function getGrid(layout) { 459 | 460 | gridLayout = layout.settings.grid 461 | 462 | var grid = { 463 | containLabel: gridLayout.containLabel, 464 | width: gridLayout.width, 465 | height: gridLayout.height 466 | } 467 | 468 | if (gridLayout.customGridPosition) { 469 | 470 | grid.left = gridLayout.position.left 471 | grid.right = gridLayout.position.right 472 | grid.top = gridLayout.position.top 473 | grid.bottom = gridLayout.position.bottom 474 | 475 | } 476 | 477 | 478 | return grid 479 | } 480 | 481 | function getLegendTextStyle(layout) { 482 | 483 | legendLayout = layout.settings.legend.text; 484 | 485 | var legendTextStyle = { 486 | fontSize: legendLayout.size 487 | } 488 | 489 | if (layout.settings.legend.colorType == 0) { 490 | 491 | legendTextStyle.color = legendLayout.color.color 492 | 493 | } else if (layout.settings.legend.colorType == 1) { 494 | 495 | legendTextStyle.color = legendLayout.colorExpression 496 | 497 | } 498 | 499 | if (legendLayout.border) { 500 | 501 | legendTextStyle.textBorderWidth = legendLayout.border.width 502 | 503 | if (layout.settings.legend.colorType == 0) { 504 | 505 | legendTextStyle.textBorderColor = legendLayout.border.color.color 506 | 507 | } else if (layout.settings.legend.colorType == 1) { 508 | 509 | legendTextStyle.textBorderColor = legendLayout.border.colorExpression 510 | 511 | } 512 | 513 | } 514 | 515 | 516 | 517 | return legendTextStyle 518 | 519 | } 520 | 521 | function getLegendPosition(legendLayout) { 522 | 523 | legendPosition = {} 524 | legendPosition[legendLayout.position] = legendLayout.distance 525 | 526 | if (legendLayout.position == 'left' || legendLayout.position == 'right') { 527 | legendPosition.orient = 'vertical' 528 | 529 | } 530 | 531 | return legendPosition; 532 | } 533 | 534 | function getLegendIcon(legendProperty, measureType) { 535 | 536 | //If measure type is bar or iconline don't exists 537 | if (measureType == 'bar' || !legendProperty.iconLine) { 538 | 539 | legendType = 'icon' 540 | 541 | } else if (measureType == 'line') { 542 | 543 | legendType = 'iconLine' 544 | 545 | } 546 | 547 | return legendProperty[legendType] 548 | } 549 | 550 | function geLegendData(layout) { 551 | 552 | var legendDataArray = []; 553 | var expressionNumber = layout.qHyperCube.qMeasureInfo.length; 554 | 555 | for (var x = 0; x < expressionNumber; x++) { 556 | 557 | if (typeof (layout.qHyperCube.qMeasureInfo[x].showInLegend) === 'undefined' || layout.qHyperCube.qMeasureInfo[x].showInLegend) { 558 | 559 | measureInfo = layout.qHyperCube.qMeasureInfo[x]; 560 | 561 | icon = getLegendIcon(layout.settings.legend, measureInfo.type) 562 | dataItem = { 563 | name: measureInfo.qFallbackTitle, 564 | icon: icon 565 | } 566 | 567 | legendDataArray.push(dataItem) 568 | } 569 | 570 | 571 | } 572 | 573 | return legendDataArray; 574 | } 575 | 576 | function getLegend(layout) { 577 | 578 | var legend = { 579 | show: layout.settings.legend.visibility, 580 | textStyle: getLegendTextStyle(layout), 581 | data: geLegendData(layout) 582 | } 583 | 584 | if (layout.settings.legend.position) { 585 | 586 | var legendPosition = getLegendPosition(layout.settings.legend) 587 | 588 | //put the selected position in legend object. 589 | for (x in legendPosition) { 590 | legend[x] = legendPosition[x] 591 | } 592 | } 593 | 594 | return legend; 595 | 596 | } 597 | 598 | function getXAxis(layout) { 599 | 600 | var xAxis = { 601 | data: getDimensionArray(layout), 602 | axisLabel: getAxisLabel(layout) 603 | } 604 | 605 | 606 | return xAxis; 607 | 608 | } 609 | 610 | function getYAxisProperty(yAxis) { 611 | 612 | yAxisProperty = { 613 | show: yAxis.show, 614 | inverse: yAxis.inverse 615 | } 616 | 617 | if (!yAxis.autoInterval) { 618 | 619 | if (yAxis.intervalType == 0 || yAxis.intervalType == 2) { 620 | 621 | yAxisProperty.min = yAxis.min 622 | } 623 | 624 | if (yAxis.intervalType == 1 || yAxis.intervalType == 2) { 625 | 626 | yAxisProperty.max = yAxis.max 627 | } 628 | 629 | } 630 | 631 | if (yAxis.label && !yAxis.label.on) { 632 | yAxisProperty.axisLabel = { 633 | formatter: function (value) { 634 | 635 | options = { 636 | style: yAxis.label.style, 637 | currency: yAxis.label.currencySymbol, 638 | minimumFractionDigits: parseInt(yAxis.label.minFractDigits) 639 | } 640 | 641 | return new Intl.NumberFormat(yAxis.label.locales, options).format(value) 642 | 643 | } 644 | } 645 | } 646 | 647 | return yAxisProperty; 648 | 649 | } 650 | 651 | function getYAxis(layout) { 652 | 653 | if (layout.settings.yAxis) { 654 | 655 | var yAxis = [ 656 | getYAxisProperty(layout.settings.yAxis.left), 657 | getYAxisProperty(layout.settings.yAxis.right) 658 | ] 659 | 660 | } else { 661 | 662 | var yAxis = [{ show: false }, { show: false }] 663 | } 664 | 665 | 666 | return yAxis; 667 | 668 | } 669 | 670 | //Get all date from the cube 671 | async function getWholeHyperCube(layout, self) { 672 | 673 | const totalRows = layout.qHyperCube.qSize.qcy; 674 | const totalColuns = layout.qHyperCube.qSize.qcx; 675 | 676 | //check if the initial dataset already is full 677 | if (initialRows / totalColuns >= totalRows) { 678 | return layout; 679 | 680 | } 681 | 682 | async function fetchPage(arrayLen) { 683 | 684 | var requestPage = [{ 685 | qTop: arrayLen, 686 | qLeft: 0, 687 | qWidth: totalColuns, 688 | qHeight: Math.min(initialRows, totalRows - arrayLen) 689 | }]; 690 | 691 | const aux = await self.backendApi.getData(requestPage) 692 | 693 | return aux[0].qMatrix; 694 | 695 | } 696 | 697 | let tempArray = [...layout.qHyperCube.qDataPages[0].qMatrix]; 698 | const maxRowsNumber = totalRows; 699 | 700 | while (tempArray.length < maxRowsNumber) { 701 | tempArray = tempArray.concat(await fetchPage(tempArray.length)); 702 | } 703 | 704 | layout.qHyperCube.qDataPages[0].qMatrix = [...tempArray]; 705 | 706 | return layout; 707 | 708 | 709 | } 710 | 711 | function getToolTipFormatter(layout, tooltipSettings) { 712 | 713 | if (tooltipSettings.customFormatter.use) { 714 | return new Function('params', tooltipSettings.customFormatter.function); 715 | } 716 | 717 | if (tooltipSettings.customFormatter.sortByStack) { 718 | 719 | return function (params) { 720 | tooltip = params[0].axisValue + '

' 721 | measureArray = {} 722 | 723 | params.forEach((variavel) => { 724 | if (variavel.data.showInToolTip) { 725 | if (!measureArray[variavel.data.stack]) 726 | measureArray[variavel.data.stack] = []; 727 | 728 | tooltipTemp = '' 729 | 730 | tooltipTemp = tooltipTemp + '
' 731 | tooltipTemp = tooltipTemp + '' + variavel.marker + variavel.seriesName + ':' + variavel.data.valueText 732 | tooltipTemp = tooltipTemp + '
' 733 | measureArray[variavel.data.stack].push(tooltipTemp) 734 | 735 | } 736 | }) 737 | 738 | for (stack in measureArray) { 739 | tooltip = tooltip + stack + '
' 740 | measureArray[stack].forEach((measures) => { 741 | tooltip = tooltip + measures 742 | }) 743 | tooltip = tooltip + '
' 744 | } 745 | 746 | return tooltip 747 | } 748 | } 749 | 750 | 751 | return function (params) { 752 | tooltip = params[0].axisValue 753 | 754 | params.forEach((variavel) => { 755 | if (variavel.data.showInToolTip) { 756 | tooltip = tooltip + '
' 757 | tooltip = tooltip + '' + variavel.marker + variavel.seriesName + ':' + variavel.data.valueText 758 | tooltip = tooltip + '
' 759 | } 760 | 761 | }) 762 | 763 | return tooltip 764 | } 765 | 766 | } 767 | 768 | function getToolTip(layout) { 769 | 770 | var toolTip = { 771 | show: false, 772 | trigger: 'axis', 773 | textStyle: {} 774 | } 775 | 776 | if (!layout.settings.tooltip || !layout.settings.tooltip.show) 777 | return toolTip; 778 | 779 | tooltipSettings = layout.settings.tooltip 780 | toolTip.show = tooltipSettings.show 781 | toolTip.alwaysShowContent = tooltipSettings.alwaysShow 782 | toolTip.transitionDuration = tooltipSettings.transitionDuration 783 | toolTip.backgroundColor = tooltipSettings.backgroundColor 784 | toolTip.borderWidth = parseInt(tooltipSettings.borderWidth) 785 | toolTip.borderColor = tooltipSettings.borderColor 786 | toolTip.textStyle.textBorderWidth = tooltipSettings.text.border.width 787 | toolTip.textStyle.fontSize = parseInt(tooltipSettings.text.size) 788 | 789 | toolTip.formatter = getToolTipFormatter(layout, tooltipSettings) 790 | 791 | 792 | if (layout.settings.tooltip.colorType == 0) { 793 | 794 | toolTip.textStyle.color = tooltipSettings.text.color.color 795 | toolTip.textStyle.textBorderColor = tooltipSettings.text.border.color.color 796 | 797 | } else if (layout.settings.tooltip.colorType == 1) { 798 | 799 | toolTip.textStyle.color = tooltipSettings.text.colorExpression 800 | toolTip.textStyle.textBorderColor = tooltipSettings.text.border.colorByExpression 801 | 802 | } 803 | 804 | return toolTip; 805 | 806 | } 807 | 808 | 809 | 810 | function setObjectStyle($element, layout) { 811 | const objectStyle = layout.settings?.objectStyle; 812 | 813 | if(!objectStyle) 814 | return; 815 | 816 | const objectStyleClassName = `customBarChart-${layout.qInfo.qId}`; 817 | const objectStyleClassNameWithDot = `.${objectStyleClassName}`; 818 | 819 | $(objectStyleClassNameWithDot).removeClass(objectStyleClassName) 820 | 821 | if(!objectStyle.use) 822 | return; 823 | 824 | var targetElement = null; 825 | if(objectStyle.includeObjectTitle) 826 | targetElement = $(`.qv-object-${layout.qInfo.qId}`) 827 | else 828 | targetElement = $element 829 | 830 | // Add the class to the target element 831 | targetElement.addClass(objectStyleClassName); 832 | 833 | const style = ` 834 | ${objectStyleClassNameWithDot} { 835 | background-color: ${objectStyle.backgroundColor} !important; 836 | border-color: ${objectStyle.borderColor} !important; 837 | border-width: ${objectStyle.borderWidth}px !important; 838 | border-style: ${objectStyle.borderStyle} !important; 839 | } 840 | `; 841 | 842 | $('